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/runHeaders
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <api-key> |
Content-Type | Yes | application/json |
Body
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | Provider slug (e.g., "apify") |
endpoint | string | Yes | Endpoint path (e.g., "/apidojo/tweet-scraper") |
input | object | Yes | Input parameters matching the endpoint's input schema |
Example Request
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
}
}'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();
};
}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
200with the completed result immediately -- no polling needed. - Async providers return
202with a run ID. PollGET /v1/runs/:runIdfor results.
200 OK (Sync)
The run completed immediately. Results are included in the response.
| Field | Type | Description |
|---|---|---|
runId | string | Unique run identifier (ULID) |
provider | string | Provider slug |
endpoint | string | Endpoint path |
status | string | Run status: "COMPLETED" |
output | any | null | Provider output data |
providerResponse | object | Provider response metadata (see below) |
providerResponse.httpStatus | number | Provider HTTP status code (200, 400, 404, 500, etc.) |
providerResponse.error | object | undefined | Provider error body (on non-2xx responses) |
price | object | Endpoint pricing |
billing | object | Billing breakdown |
resultCount | number | null | Number of result items |
createdAt | string | ISO 8601 timestamp |
completedAt | string | ISO 8601 timestamp |
Example: Sync Success
{
"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.
{
"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.
| Field | Type | Description |
|---|---|---|
runId | string | Unique run identifier (ULID) |
provider | string | Provider slug |
endpoint | string | Endpoint path |
status | string | "RUNNING" |
price | object | Endpoint pricing |
createdAt | string | ISO 8601 timestamp |
Example
{
"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:
status-- the run lifecycle."COMPLETED"means the provider was called and responded."FAILED"means an infrastructure error (our fault).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:
status-- wait until"COMPLETED"or"FAILED"(terminal statuses)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.