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

# Getting Started

> Quickest path to call the Surnex API.

## Quick setup

1. Obtain your API key from Surnex.

2. Send requests to the base URL from the live API:

   * `https://api.surnex.io`

3. Use the OpenAPI contract to test operations interactively and discover service coverage.

## Surnex-first execution model

* New integrations should use the provider-agnostic execution surface first:
  * `GET /v1/providers`
  * `GET /v1/providers/{provider}/catalog`
  * `GET /v1/providers/{provider}/capabilities`
  * `POST /v1/executions`
  * `GET /v1/executions/{id}`
  * `GET /v1/executions/{id}/results`
* `DataForSEO` remains available and fully supported through compatibility routes:
  * `GET /v1/dataforseo/catalog`
  * `POST /v1/dataforseo/executions`
  * `GET /v1/dataforseo/executions/{id}`
  * `GET /v1/dataforseo/executions/{id}/results`

## Current implementation status

* Canonical `/v1/providers` and `/v1/executions*` surfaces are the first-party Surnex API contract.
* `dataforseo` is the currently active upstream provider and remains as a compatibility-backed path for existing integrations.
* Provider extension work is next: additional providers should be added through `packages/provider-core` adapter implementations.
* Next in roadmap:
  * provider onboarding metadata and policy controls in `/v1/providers/{provider}/capabilities`,
  * project/tenant capabilities for future Surnex UI and sharing features,
  * and stronger multi-provider operational controls.

## Marketing site publishing integration

The marketing website setup now has its own page:

* [`Marketing Site`](/marketing)

Core pieces:

* SEO/LLM-first static pages and blog routes at `https://surnex.io`
* Content ingest contract: `POST /v1/webhooks/marketing/blog`
* Vercel deployment settings and environment mapping are documented in one place

## DataForSEO coverage workflow

* Catalog all known services:
  * `GET /v1/dataforseo/catalog`
* All service responses now include `category` for deterministic UI grouping.
* Filter catalog views by category with `?category=<slug>` (for example:
  `?category=serp`).
* Group services by discovery source:
  * `GET /v1/dataforseo/catalog?group_by=discovery_source&discover=false`
  * Group key order: `static`, `discovered`, `mixed`
* Discover live endpoints for one service:
  * `GET /v1/dataforseo/catalog?service=<service>&discover=true`
* Browse a service-scoped operations index (paginated and filterable):
  * `GET /v1/dataforseo/catalog/services/{service}`
* `/v1/dataforseo/catalog/services/{service}` returns operation rows; use
  `GET /v1/dataforseo/catalog/services/{service}/templates` for template
  rows with `path_variables` and execution hints.
* Group a service-scoped operation index:
  * `GET /v1/dataforseo/catalog/services/{service}?group_by=mode|method`
  * `GET /v1/dataforseo/catalog/services/{service}?group_by=discovery_source`
* Scope template discovery and execution scaffolding for one service:
  * `GET /v1/dataforseo/catalog/services/{service}/templates`
* `group_by=discovery_source` keys are `static`, `discovered`
* Group the global flat operation index by method, mode, or service:
  * `group_by=service` keys are alphabetical
  * `group_by=method` keys are `GET`, `POST`
  * `group_by=mode` keys are `live`, `task_post`, `task_get`, `tasks_ready`, `tasks_fixed`
  * `group_by=discovery_source` keys are `static`, `discovered`
  * `GET /v1/dataforseo/catalog/operations?group_by=service|mode|method|discovery_source`
* Discover all service endpoints at once:
  * `GET /v1/dataforseo/catalog?discover=true`
* Bootstrap everything at startup (manifest + operation counts):
  * `GET /v1/dataforseo/catalog/bootstrap`
* Get deterministic category buckets for UI sections:
  * `GET /v1/dataforseo/catalog/categories`
* Get services for a single category with pagination/filtering:
  * `GET /v1/dataforseo/catalog/categories/{category}`
* Build your UI service catalog quickly from capability summaries: `GET /v1/dataforseo/catalog/capabilities`
* Filter capability results with `method` and `mode`: `GET /v1/dataforseo/catalog/capabilities?method=GET&mode=live`
* Focus capabilities for one service: `GET /v1/dataforseo/catalog/capabilities?service=serp`
* Get operation templates (path variables + execution hints) for UI builders:
  * `GET /v1/dataforseo/catalog/templates`
* Filter and group operation templates for onboarding surfaces:
  * `GET /v1/dataforseo/catalog/templates?group_by=service&method=POST`
* Service-scoped templates are the same shape with URL-level scoping:
  * `GET /v1/dataforseo/catalog/services/{service}/templates?discover=false&group_by=mode&method=POST`
* Group capability output by service: `GET /v1/dataforseo/catalog/capabilities?group_by=service`
* Paginate capabilities list for large catalogs:
  * `GET /v1/dataforseo/catalog/capabilities?limit=25&offset=25`
* Group capability output with `group_by=service` (alphabetical) or `group_by=discovery_source` (`static`, `discovered`, `mixed`)
* Refresh discovery cache when needed:
  * `GET /v1/dataforseo/catalog?discover=true&refresh_discovery=true`
* Filter by source:
  * `GET /v1/dataforseo/catalog?discover=true&discovery_source=discovered`
* Refresh discovery in catalog queries when you need latest DataForSEO paths:
  * `GET /v1/dataforseo/catalog?discover=true&refresh_discovery=true`
  * `GET /v1/dataforseo/catalog/summary?discover=true&refresh_discovery=true`
  * `GET /v1/dataforseo/catalog/operations?discover=true&refresh_discovery=true`
* Search catalog services and operations:
  * `GET /v1/dataforseo/catalog?search=google_trends`
* Get compact coverage summary:
  * `GET /v1/dataforseo/catalog/summary`
* Get discovered-only summary:
  * `GET /v1/dataforseo/catalog/summary?discover=true&discovery_source=discovered`
* Filter summary coverage by search:
  * `GET /v1/dataforseo/catalog/summary?search=backlinks`
* Browse discoverable operations directly:
  * `GET /v1/dataforseo/catalog/operations`
* Discoverable operations with filters:
  * `GET /v1/dataforseo/catalog/operations?service=serp&method=POST&mode=live`
* Paginate operation catalogs for UI loaders:
  * `GET /v1/dataforseo/catalog/operations?service=serp&limit=25&offset=50`
* Sort operation list by fields (`service`, `operation_path`, `method`, `mode`, `discovery_source`) and ordering:
  * `GET /v1/dataforseo/catalog/operations?sort=service&order=desc`
* Sorts are stable for equal primary values using a deterministic secondary order (`service`, `operation_path`, `method`) so paginated clients can resume safely.
* Catalog responses include:
  * `discovery_source` per service (`static`, `discovered`, `mixed`)
  * `discovery_source` per operation (`static`, `discovered`)
* `discovery_context` on catalog/summary/operations responses:
  * `source` (`cache`, `provider`, `mixed`, or `none`)
  * `discovered_at` timestamp and cache metadata
  * `cache_hit` and `provider_calls`
* Execute a provider operation:
* `POST /v1/executions`
* Execute any provider endpoint path directly (including newly introduced or undocumented paths):
  * `POST /v1/dataforseo/executions`
* Use catalog templates for safer onboarding (`operation_template` + `path_variables`) so clients avoid manual string interpolation:
  * `POST /v1/dataforseo/executions`
* Read execution status and results:
  * `GET /v1/executions/{id}`
  * `GET /v1/executions/{id}/results`
* Compatibility reads for existing integrations:
  * `GET /v1/dataforseo/executions/{id}`
  * `GET /v1/dataforseo/executions/{id}/results`

LLM Mentions calls are policy-enforced. If a request targets `llm_mentions` operations, the following are enforced:

* `platform: "chat_gpt"`
* `location_code: 2840`
* `language_code: "en"`
* `targets.length <= 10`
* `limit <= 1000`
* `offset <= 9000`

## Required headers

* `x-api-key`: your Surnex API key
* `Content-Type`: `application/json`

## Web app auth flow

For local development, copy `apps/app/.env.example` to `apps/app/.env.local` and set:

```bash theme={null}
VITE_API_BASE_URL=http://localhost:3001
```

Session cookies are required and sent with cross-origin credentials:

* Cookie name: `surnex_session`
* Session requests include `credentials: 'include'` and carry `x-request-id`.

Run the SPA locally with:

```bash theme={null}
pnpm --filter @surnex/app dev
```

* Frontend application: `https://app.surnex.io`
* Session endpoints:
  * `POST /v1/auth/signup`
  * `POST /v1/auth/signin`
  * `POST /v1/auth/signout`
  * `GET /v1/auth/me`
* Project endpoints:
  * `GET /v1/projects`
  * `POST /v1/projects`
  * `GET /v1/projects/{projectId}`
* Cookies are required for app sessions using `surnex_session` and request-origin `app.surnex.io`.

## Observability contract

* All API responses include an `x-request-id` header.

* Error responses include `error.request_id`, which must match `x-request-id` exactly.

* Include this value in support tickets and logs when reporting incidents.

* Usage rollups are provider-aware:
  * `GET /v1/usage` returns the filtered rollup in `totals` plus per-provider rollups in `providers`.

## Base responses

All primary API health and metadata routes are publicly exposed:

* `GET /health`
* `GET /ready`
* `GET /.well-known/openapi.json`
* `GET /llms.txt`

Snapshots are created with `POST /v1/geo/snapshots` and checked via
`GET /v1/geo/snapshots/{id}` and `GET /v1/geo/snapshots/{id}/results`.

## Canonical execution payload pattern

Use this shape as a baseline for direct execution requests:

```json theme={null}
{
  "provider": "dataforseo",
  "service": "serp",
  "method": "POST",
  "mode": "live",
  "operation_template": "/serp/{se}/{type}/live",
  "path_variables": {
    "se": "google",
    "type": "organic"
  },
  "request_body": {
    "keyword": "example"
  },
  "request_query": {
    "api_key": "optional"
  },
  "expected_part_name": "serp_google_organic_live"
}
```

`provider` can be omitted in current releases and defaults to `dataforseo`.

Notes:

* Use `operation_path` when you already know exact path.
* Use `operation_template` + `path_variables` for onboarding with minimal risk of formatting errors.
* Only include one of `operation_path` or `operation_template`.

## Error contract reference

All API failures use a stable envelope and include the matching `request_id`:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request",
    "request_id": "a13e…"
  }
}
```

Most commonly observed codes:

* `VALIDATION_ERROR`: schema/parameter/body validation failure.
* `UNAUTHORIZED`: missing/invalid credentials.
* `NOT_FOUND`: resource not found.
* `PROVIDER_ERROR`: upstream provider unavailable or returned error.
* `INTERNAL_ERROR`: unexpected service exception.

Use `error.request_id` in support tickets and include the corresponding `x-request-id` response header.
