# Socai API

Run real browser research from your server, then read the answer and original-source records.

## Quickstart

Create a key from **API keys** in the Socai sidebar. Copy it once and save it in your server's secret manager as `SOCAI_API_KEY`; it cannot be retrieved later. Never put the key in browser code, a prompt or a public repository.

Choose the account's regional endpoint:

| Region | Base URL |
| --- | --- |
| Global | `https://agent.socai.io/api/server/v1` |
| China | `https://agentcn.socai.io/api/server/v1` |
| Development | `https://agent-dev.socai.io/api/server/v1` |

Every request uses `Authorization: Bearer $SOCAI_API_KEY`. Keys are scoped to an account and a project; use the same project throughout a workflow. Requests use that account's Credits and managed platform connections. Expired or revoked keys return `401`; revoking a key does not cancel work already running.

The paths below are relative to `/api/server` on the chosen host. The machine-readable specification is [openapi.json](./openapi.json); the interactive reference is [docs](./docs).

## 1. Create research

`POST /v1/responses`

```bash
export SOCAI_API_BASE_URL='https://agent.socai.io/api/server/v1'
# Set SOCAI_API_KEY securely in the server environment first.
export SOCAI_OPERATION_ID="$(uuidgen)"
curl --fail-with-body --max-time 30 "$SOCAI_API_BASE_URL/responses" \
  -H "Authorization: Bearer $SOCAI_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $SOCAI_OPERATION_ID" \
  --data '{"model":"socai-research","background":true,"input":"Research recent AI wearable feedback on X, including original links.","socai":{"platforms":["x"],"mode":"quick"}}'
```

Returns `202` and a Response `id`. Save both the ID and your operation ID before polling. This is asynchronous, not a synchronous LLM call. Use a new idempotency key for a new task; retry an uncertain creation only with the **same key and identical body**. A different body with the same key returns `409`.

`socai.mode` accepts `quick` or `deep`. Omit `socai.platforms` for Auto, or select `xhs`, `dy`, `tiktok`, `instagram`, `linkedin`, `x`, `web`, `weixin`, `podcast`, `github`.

The returned `socai.routing` object makes routing observable: `source` is
`automatic` or `explicit`, `includes_xhs` confirms whether XHS is in scope, and
`browser_strategy` is `shared_session` when several selected platforms reuse one
Kernel browser lifecycle. These fields report the accepted scope; they do not
claim that every source produced records. Legacy Responses created before this
metadata was persisted may report `unknown`.

For a follow-up, create another Response with `previous_response_id` set to the earlier ID; it must belong to the same account and project.

## 2. Read status and answer

`GET /v1/responses/{response_id}`

```bash
curl --fail-with-body --max-time 30 "$SOCAI_API_BASE_URL/responses/$RESPONSE_ID" \
  -H "Authorization: Bearer $SOCAI_API_KEY"
```

| Status | Action |
| --- | --- |
| `queued`, `in_progress` | Poll the same ID, typically every three seconds. |
| `requires_action` | Open `socai.required_action.authorization_url` as the signed-in Socai user, complete platform sign-in, then resume polling the same ID. |
| `completed` | Read `output_text` and fetch source records. |
| `failed` | Read the returned error; do not treat a partial answer as a completed task. |
| `cancelled` | Stop polling. |

A client waiting timeout does not cancel server work. Save the Response ID and resume it instead of automatically submitting a duplicate task. Set separate limits for an HTTP request (for example 30 seconds) and the overall waiting period (for example 30 minutes).

## 3. Read original-source records

`GET /v1/responses/{response_id}/records`

```bash
curl --fail-with-body --max-time 30 \
  "$SOCAI_API_BASE_URL/responses/$RESPONSE_ID/records?limit=20" \
  -H "Authorization: Bearer $SOCAI_API_KEY"
```

Read `items`, then continue with the opaque `next_cursor` until it is null. URL-encode the cursor and keep the same Response ID. `limit` is 1–200. Empty records are valid and must not be invented.

Records include source URLs, text, media references, metrics, parent identities and content versions when available. Publication time is distinct from observation time. Missing timestamps or metrics may be null.

## 4. Cancel unfinished research

`POST /v1/responses/{response_id}/cancel`

```bash
curl --fail-with-body --max-time 30 --request POST \
  "$SOCAI_API_BASE_URL/responses/$RESPONSE_ID/cancel" \
  -H "Authorization: Bearer $SOCAI_API_KEY"
```

Cancellation is explicit; closing a client or losing the connection does not cancel a task. Query the Response afterward for its actual status rather than assuming immediate termination.

## Other entry points

- `POST /v1/chat/completions` accepts Chat Completions-style messages.
- `POST /v1/messages` accepts Anthropic-style messages.
- Both require the Socai extension `background: true` and return `socai.response_id` for polling through Responses; neither emulates provider streaming or synchronous completion.
- `GET /v1/connections` reads managed platform connection status without exposing credentials.
- `POST /v1/monitor-tasks` creates a monitoring configuration; `enabled: false` keeps it paused. Starting an enabled schedule can create recurring billed work.
- `POST /v1/monitor-tasks/{task_id}/runs` starts a manual incremental or backfill collection. Poll `/v1/runs/{run_id}` and page `/v1/runs/{run_id}/records`.
- `POST /v1/analyses` analyzes submitted versioned records. Poll `/v1/analyses/{analysis_id}` and page `/v1/analyses/{analysis_id}/results`.

The OpenAPI reference describes full schemas, configuration versions, collection limits and pagination parameters.

## Errors and safe retries

```json
{"error":{"code":"UNAUTHORIZED","message":"...","retryable":false,"request_id":"req_..."}}
```

Check HTTP status before reading success fields. Save `X-Request-ID` or `error.request_id` for support, never the Bearer secret. Handle `401` expired/revoked keys, `403` account restrictions, `409` idempotency/version conflicts, `429` quota/rate limits, and `502`/`503` provider availability explicitly.

Honor `Retry-After` and `retry_after_seconds` when retrying a retryable rate limit; a quota error is not resolved by immediate retry. Avoid automatic retries of creation requests without the original idempotency key. Never forward Authorization across redirects.
