> ## Documentation Index
> Fetch the complete documentation index at: https://monid.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Run

> Execute a data endpoint.

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

```text theme={null}
POST /v1/run
```

### Headers

| 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

<CodeGroup>
  ```bash curl theme={null}
  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 TypeScript theme={null}
  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
    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 Python theme={null}
  import requests
  import time

  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:
      result = data
  else:
      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)

  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')}")
  ```
</CodeGroup>

## 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`](/api/runs#get-run) for 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    |
| `providerResponse.httpStatus` | number              | Provider HTTP status code     |
| `providerResponse.error`      | object \| undefined | Provider error body (non-2xx) |
| `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

```json theme={null}
{
  "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 theme={null}
{
  "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`](/api/runs#get-run) 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

```json theme={null}
{
  "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](/api/runs#status-vs-provider-http-status) for the full reference.

## Polling for Results

For async runs (`202` response), poll [`GET /v1/runs/:runId`](/api/runs#get-run) 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`](/api/runs#get-run) to retrieve run results.
