Contrib API 1

Next.js drop-in replacement for api1.contrib.co (PHP Yii) · eService external APIs on the External API tab

22 controllers187 endpoints14 database pools

What these APIs are

Server-to-server read APIs for Contrib eService orders — the paid cart tasks created when you POST item 37 (site submission package) via manage-app. Data comes from cart_order cart_order_list cart_microtask in domaindi_managedomain. Same tasks contributors see in the Contrib eService Kanban.

What these APIs are NOT

Do not use for AgentDAO fulfillmentWhat it actually is
/Request/GetdomainjobsVNOC company job board (company_jobs)
/Request/GeteservicesLegacy eservices catalog table
/Request/GetTotalTasksCountCrowd tasks count (crowd_tasks)
contrib.com /api/public/domain_tasksPublic crowd tasks — not cart_microtask

ID mapping (order_id vs task_id)

manage-app item-37 POST returns order_id (cart_order). Contributors and these APIs use task_id (cart_microtask). Always resolve task_id after order create, then poll by task_id.

manage-app POST (item 37)  →  order_id
GET /api/external/orders/{order_id}/tasks  →  task_id(s)
GET /api/external/tasks/{task_id}/status   →  poll status

Authentication

Include API key via one of:

  • Query: ?key=<api_key>
  • Header: Authorization: Bearer <api_key>
  • Header: X-Api-Key: <api_key>

Valid keys: master md5("vnoc.com"), domain MD5 keys, developer keys, or server env CONTRIB_EXTERNAL_API_KEY.

Task status (cart_microtask.status)

UI labelDB string (store verbatim)status_normalizedList filter
Work pendingpending or NULLpendingstatus=pending
On Goingon goingon_goingstatus=on_going
For Verificationfor verificationfor_verificationstatus=for_verification
Completedcompletedcompletedstatus=completed
Applied (not a status)cart_microtask_applicationsstatus=applied

AgentDAO payout: release ADAO when status_normalized === "completed". Lifecycle: pending → on going → for verification → completed.

1. GET /api/external/tasks/[task_id]/status

Purpose: Poll a single eService task. Primary endpoint for status sync.

Path param: task_id (integer)

curl -H "X-Api-Key: <master_key>" \
  "https://<host>/api/external/tasks/12345/status"

# Response
{
  "success": true,
  "data": {
    "task": {
      "task_id": 12345,
      "order_id": 999,
      "title": "Site submission for example.com",
      "slug": "site-submission-example",
      "description": "...",
      "instruction": null,
      "status": "on going",
      "status_normalized": "on_going",
      "domain_name": "pragent.com",
      "category_name": "Site Submission",
      "item_id": 37,
      "price": 25.0,
      "contrib_user": "tasker_username",
      "employer_name": null,
      "date_ordered": "2026-06-01T12:00:00.000Z",
      "is_open": false,
      "application_count": 2
    }
  }
}

is_open = true when no assignee (contrib_user is null). Errors: 401 (auth), 404 (task not found).

2. GET /api/external/orders/[order_id]/tasks

Purpose: Resolve task_id(s) immediately after manage-app item-37 order create.

Path param: order_id (integer)

curl "https://<host>/api/external/orders/999/tasks?key=<master_key>"

# Response
{
  "success": true,
  "data": {
    "order_id": 999,
    "count": 1,
    "tasks": [
      {
        "task_id": 12345,
        "order_id": 999,
        "status": "pending",
        "status_normalized": "pending",
        "domain_name": "pragent.com",
        "item_id": 37,
        "is_open": true,
        "application_count": 0
      }
    ]
  }
}

An order may have multiple tasks (one per line item). Item 37 usually produces one task.

3. GET /api/external/tasks

Purpose: List/filter eService tasks for AgentDAO task dashboards.

ParamRequiredDescription
domainOne of domain or statusExact domain, e.g. pragent.com, linkagent.com
statusOne of domain or statuspending | on_going | for_verification | completed | applied
item_idNoCart item filter — use 37 for site submission package
pageNoDefault 1
limitNoDefault 20, max 100
# Pending item-37 tasks on pragent.com
GET /api/external/tasks?domain=pragent.com&status=pending&item_id=37&key=<key>

# All completed tasks (any domain)
GET /api/external/tasks?status=completed&limit=50&key=<key>

# Response
{
  "success": true,
  "data": {
    "tasks": [ { "task_id": 12345, "status": "for verification", "status_normalized": "for_verification", "..." : "..." } ],
    "total": 42,
    "page": 1,
    "limit": 20
  }
}

4. Contrib tasker provisioning (AgentDAO taskers only)

Purpose: Silently create a contrib_rdb.Members account so a tasker can log in to contrib.com and work eService tasks. VNOC domain team membership is not required for taskers.

# Check exists
GET /api/external/contrib-members?email=tasker@example.com&key=<key>

# Create tasker (EmailVerified=1 by default)
POST /api/external/contrib-members
  Header: X-Api-Key: <key>
  Body: { "email": "tasker@example.com", "first_name": "Jane", "last_name": "Doe", "password": "optional" }

# Response (created)
{
  "success": true,
  "data": {
    "created": true,
    "member": {
      "member_id": 12345,
      "email": "tasker@example.com",
      "first_name": "Jane",
      "last_name": "Doe",
      "username": "janeabc123",
      "email_verified": true
    },
    "message": "Contrib tasker created.",
    "generated_password": "..."   // only if password omitted
  }
}

If password is omitted, a random password is generated and returned once in generated_password — store it in AgentDAO. Re-posting the same email returns created: false with existing member_id.

5. Task messaging (read/post updates)

Purpose: Read and post messages on a task's update thread (cart_microtask_updates). Use for buyer ↔ contributor communication, delivery notes, and work-in-progress updates.

# List messages for a task
GET /api/external/tasks/12345/messages?key=<key>&limit=20

# Response
{
  "success": true,
  "data": {
    "task_id": 12345,
    "messages": [
      {
        "update_id": 3053,
        "message": "Here is the site submission link…",
        "sender_type": "contributor",
        "contrib_user": 114509,
        "date_created": "2026-06-01T15:54:48.000Z",
        "is_read": false
      }
    ],
    "total": 1,
    "page": 1,
    "limit": 20
  }
}

# Post a message
POST /api/external/tasks/12345/messages
  Header: X-Api-Key: <key>
  Body: { "message": "Task submitted, here is the link…", "sender_type": "external", "sender_name": "AgentDAO Bot" }

# Response (posted)
{
  "success": true,
  "data": {
    "update_id": 3275,
    "task_id": 12345,
    "message": "Task submitted, here is the link…",
    "sender_type": "external",
    "date_created": "2026-06-11T14:50:00.000Z"
  }
}

sender_type: contributor (needs contrib_user ID), employer (needs vnoc_member ID), or external (default — uses sender_name or "AgentDAO").

6. Domain registration (buyer domains)

Purpose: Register a buyer's domain in VNOC so eService orders can be placed against it. Domains are automatically linked to AgentDAO (company 243). Idempotent — re-posting an existing domain just ensures the company link.

# Check if domain exists in VNOC
GET /api/external/domains?domain=newsite.com&key=<key>

# Response (not found)
{ "success": true, "data": { "exists": false, "domain_name": "newsite.com" } }

# Register domain under AgentDAO
POST /api/external/domains
  Header: X-Api-Key: <key>
  Body: { "domain_name": "newsite.com", "category_id": 149, "title": "NewSite" }

# Response (created)
{
  "success": true,
  "data": {
    "created": true,
    "domain": {
      "domain_id": 49810,
      "domain_name": "newsite.com",
      "category_id": 149,
      "category_name": "Business",
      "company_id": 243,
      "company_name": "AgentDAO"
    },
    "company_linked": true,
    "message": "Domain newsite.com registered and linked to AgentDAO."
  }
}

# List available categories
GET /api/external/domains?action=categories&key=<key>

If category_id is omitted, defaults to 137 (Internet/Web). Use ?action=categories to list all available categories. If the domain already exists, it's linked to AgentDAO and returned with created: false.

7. Create eService order (checkout)

Purpose: Create a full eService order in one call — inserts cart_order, cart_order_list,cart_order_domain, and cart_microtask. Returns both order_id and task_id.Replaces the manage-app POST.

# Create order for pragent.com (item 37 = Site Submission Package)
POST /api/external/orders
  Header: X-Api-Key: <key>
  Body: {
    "domain": "pragent.com",
    "item_id": 37,
    "instruction": "Submit to top 10 directories",
    "assigned_to": 114509,          // optional: auto-assign contributor
    "customer_name": "John Doe",    // optional: external customer info
    "customer_email": "j@agentdao.com"
  }

# Response
{
  "success": true,
  "data": {
    "order_id": 37209,
    "task_id": 56095,
    "domain_name": "pragent.com",
    "item_id": 37,
    "title": "Pragent.com - SITE SUBMISSION PACKAGE",
    "slug": "pragent-com-site-submission-package",
    "price": 10,
    "service_fee": 2,
    "status": "pending",
    "status_normalized": "pending",
    "assigned_to": 114509
  }
}

Domain must exist in VNOC (use endpoint 6 first). The response gives you both order_id and task_id — no need to call GET /api/external/orders/{order_id}/tasks separately. If assigned_to is provided, the task is pre-assigned and an application record is created.

AgentDAO integration flow

  1. Tasker onboard: POST /api/external/contrib-members → save member_id + password
  2. Register domain: POST /api/external/domains → ensure buyer domain is in VNOC under AgentDAO
  3. Create order: POST /api/external/orders → returns order_id + task_id directly
  4. Store: contrib_status_raw = verbatim DB status; status = status_normalized
  5. Poll: GET /api/external/tasks/{task_id}/status every 5–15 min until completed
  6. Message: POST /api/external/tasks/{task_id}/messages for buyer instructions or updates
  7. Payout: release ADAO when status_normalized === "completed"

Agent domains: pragent.com, agent.listagent.com, linkagent.com

Endpoint reference

Contrib eService cart tasks (cart_microtask) — NOT VNOC jobs, crowd tasks, or legacy Geteservices.
EndpointMethodAuthParamsDescription
/api/external/tasks/[task_id]/statusGETkey|Bearer|X-Api-Keytask_id (path)Primary poll endpoint. Returns full task + status + status_normalized. Use task_id from order lookup.
/api/external/orders/[order_id]/tasksGETkey|Bearer|X-Api-Keyorder_id (path)Resolve task_id(s) after manage-app item-37 POST. Returns all cart_microtask rows for the order.
/api/external/tasksGETkey|Bearer|X-Api-Keydomain?, status?, item_id?, page?, limit?List/filter eService tasks for dashboards. Requires domain and/or status. item_id=37 for site submission package.
/api/external/contrib-membersGETkey|Bearer|X-Api-KeyemailCheck if a Contrib tasker (contrib_rdb.Members) exists by email.
/api/external/contrib-membersPOSTkey|Bearer|X-Api-Keyemail, first_name?, last_name?, password?, verify_email?Silently provision a Contrib tasker for agentdao.com. Sets EmailVerified=1 by default. VNOC team not required.
/api/external/tasks/[task_id]/messagesGETkey|Bearer|X-Api-Keytask_id (path), page?, limit?List messages/updates for a task thread (cart_microtask_updates). Returns sender_type, date, is_read.
/api/external/tasks/[task_id]/messagesPOSTkey|Bearer|X-Api-Keymessage, sender_type?, sender_name?, contrib_user?, vnoc_member?Post a message to a task's update thread. Used for buyer instructions, delivery notes, and work updates.
/api/external/domainsGETkey|Bearer|X-Api-Keydomain OR action=categoriesCheck if a domain exists in VNOC (returns company link), or list available domain categories.
/api/external/domainsPOSTkey|Bearer|X-Api-Keydomain_name, category_id?, title?, description?, company_id?Register a buyer's domain in VNOC and link it to AgentDAO (company 243). Idempotent — safe to re-post.
/api/external/ordersPOSTkey|Bearer|X-Api-Keydomain, item_id, instruction?, assigned_to?, customer_name?, customer_email?Create full eService order + task in one call. Returns order_id and task_id. Replaces manage-app POST.

Not included yet

  • Webhooks on status change — use polling for now
  • POST task messages / updates
  • contrib.com session APIs (/api/crypto/eservices/*) — contributor login only