Skip to content

POST /v1/run ​

Execute a data endpoint.

For providers which are executed synchronously (e.g. People Data Labs), they return the results immediately; for others (e.g. Apify), the server will return 202 with a run ID and processes the request in the background.

Request ​

POST /v1/run

Headers ​

HeaderRequiredDescription
AuthorizationYesBearer <api-key>
Content-TypeYesapplication/json

Body ​

FieldTypeRequiredDescription
providerstringYesProvider slug (e.g., "apify")
endpointstringYesEndpoint path (e.g., "/apidojo/tweet-scraper")
inputobjectYesInput parameters matching the endpoint's input schema

Example Request ​

bash
curl -X POST https://api.dev.monid.ai/v1/run \
  -H "Authorization: Bearer monid_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "apify",
    "endpoint": "/apidojo/tweet-scraper",
    "input": {
      "searchTerms": ["AI"],
      "maxItems": 10
    }
  }'
typescript
const response = await fetch("https://api.dev.monid.ai/v1/run", {
  method: "POST",
  headers: {
    "Authorization": "Bearer monid_live_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    provider: "apify",
    endpoint: "/apidojo/tweet-scraper",
    input: {
      searchTerms: ["AI"],
      maxItems: 10,
    },
  }),
});

const data = await response.json();

if (response.status === 200) {
  // Sync provider (e.g. PDL) -- results returned immediately
  // Check providerResponse.httpStatus for provider-level errors
  console.log(data.output);
} else {
  // 202 Accepted -- poll for results
  const runId = data.runId;
  const poll = async () => {
    const result = await fetch(`https://api.dev.monid.ai/v1/runs/${runId}`, {
      headers: { "Authorization": "Bearer monid_live_..." },
    });
    return result.json();
  };
}
python
import requests
import time

# Start the run
response = requests.post(
    "https://api.dev.monid.ai/v1/run",
    headers={
        "Authorization": "Bearer monid_live_...",
        "Content-Type": "application/json",
    },
    json={
        "provider": "apify",
        "endpoint": "/apidojo/tweet-scraper",
        "input": {
            "searchTerms": ["AI"],
            "maxItems": 10,
        },
    },
)

data = response.json()

if response.status_code == 200:
    # Sync provider -- results returned immediately
    result = data
else:
    # 202 Accepted -- poll for results
    run_id = data["runId"]
    while True:
        result = requests.get(
            f"https://api.dev.monid.ai/v1/runs/{run_id}",
            headers={"Authorization": "Bearer monid_live_..."},
        ).json()
        if result["status"] in ("COMPLETED", "FAILED"):
            break
        time.sleep(5)

# Check run status vs provider HTTP status
if result["status"] == "FAILED":
    print("Infrastructure error")
elif result.get("providerResponse", {}).get("httpStatus", 200) >= 400:
    print(f"Provider error: HTTP {result['providerResponse']['httpStatus']}")
else:
    print(f"Success: {result.get('output')}")

Response ​

The response depends on the provider's execution mode:

  • Sync providers return 200 with the completed result immediately -- no polling needed.
  • Async providers return 202 with a run ID. Poll GET /v1/runs/:runId for results.

200 OK (Sync) ​

The run completed immediately. Results are included in the response.

FieldTypeDescription
runIdstringUnique run identifier (ULID)
providerstringProvider slug
endpointstringEndpoint path
statusstringRun status: "COMPLETED"
outputany | nullProvider output data
providerResponseobjectProvider response metadata (see below)
providerResponse.httpStatusnumberProvider HTTP status code (200, 400, 404, 500, etc.)
providerResponse.errorobject | undefinedProvider error body (on non-2xx responses)
priceobjectEndpoint pricing
billingobjectBilling breakdown
resultCountnumber | nullNumber of result items
createdAtstringISO 8601 timestamp
completedAtstringISO 8601 timestamp

Example: Sync Success ​

json
{
  "runId": "01HXYZ1234567890ABCDEF",
  "provider": "pdl",
  "endpoint": "/person/enrich",
  "status": "COMPLETED",
  "output": {
    "full_name": "John Doe",
    "linkedin_url": "linkedin.com/in/johndoe"
  },
  "providerResponse": {
    "httpStatus": 200
  },
  "price": {
    "type": "PER_CALL",
    "amount": 0.003,
    "currency": "USD"
  },
  "billing": {
    "calculatedCost": { "value": 3000, "unit": "MICRO_DOLLAR", "currency": "USD" },
    "actualCost": { "value": 0, "unit": "MICRO_DOLLAR", "currency": "USD" },
    "reportedCost": { "value": 3000, "unit": "MICRO_DOLLAR", "currency": "USD" }
  },
  "resultCount": 1,
  "createdAt": "2026-03-28T10:30:00.000Z",
  "completedAt": "2026-03-28T10:30:01.000Z"
}

Example: Sync Provider Error ​

The run completed, but the provider returned an error. Note status is still "COMPLETED" -- the run lifecycle finished. The provider HTTP status tells you the result.

json
{
  "runId": "01HXYZ1234567890ABCDEF",
  "provider": "pdl",
  "endpoint": "/person/enrich",
  "status": "COMPLETED",
  "output": null,
  "providerResponse": {
    "httpStatus": 404,
    "error": {
      "status": 404,
      "message": "No match found for the given query"
    }
  },
  "price": {
    "type": "PER_CALL",
    "amount": 0.003,
    "currency": "USD"
  },
  "billing": {
    "calculatedCost": { "value": 3000, "unit": "MICRO_DOLLAR", "currency": "USD" },
    "actualCost": { "value": 0, "unit": "MICRO_DOLLAR", "currency": "USD" },
    "reportedCost": { "value": 0, "unit": "MICRO_DOLLAR", "currency": "USD" }
  },
  "resultCount": null,
  "createdAt": "2026-03-28T10:30:00.000Z",
  "completedAt": "2026-03-28T10:30:01.000Z"
}

202 Accepted (Async) ​

The run has been started. Poll GET /v1/runs/:runId for results.

FieldTypeDescription
runIdstringUnique run identifier (ULID)
providerstringProvider slug
endpointstringEndpoint path
statusstring"RUNNING"
priceobjectEndpoint pricing
createdAtstringISO 8601 timestamp

Example ​

json
{
  "runId": "01HXYZ1234567890ABCDEF",
  "provider": "apify",
  "endpoint": "/apidojo/tweet-scraper",
  "status": "RUNNING",
  "price": {
    "type": "PER_CALL",
    "amount": 0.003,
    "currency": "USD"
  },
  "createdAt": "2026-03-28T10:30:00.000Z"
}

Status vs Provider HTTP Status ​

Every completed run has two independent indicators:

  1. status -- the run lifecycle. "COMPLETED" means the provider was called and responded. "FAILED" means an infrastructure error (our fault).
  2. providerResponse.httpStatus -- the provider's HTTP response code. 200 = data returned. 404 = no match. 429 = rate limited. 500 = provider error.

A run with status: "COMPLETED" and providerResponse.httpStatus: 404 is normal -- the run completed, the provider just found no data. Provider errors are not charged.

See Status vs Provider HTTP Status for the full reference.

Polling for Results ​

For async runs (202 response), poll GET /v1/runs/:runId to check status and retrieve results. Most runs complete within 1-120 seconds.

When polling, check two things:

  1. status -- wait until "COMPLETED" or "FAILED" (terminal statuses)
  2. providerResponse.httpStatus -- once completed, check if the provider returned a success (2xx) or error (4xx/5xx)

Next Step ​

Use GET /v1/runs/:runId to retrieve run results.

The data layer for AI agents.