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.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.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.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.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.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.