# REST API

One HTTP API for every connected account. Use it from scripts, servers, workflow tools or any agent that can make HTTP requests.

## Base URL and authentication

```text title=Base URL
https://api.oneapiforagents.com/v1
```

Every request carries an API key as a bearer token. Create keys in the dashboard under **API keys**; they start with `oa_` and are shown once.

```http
Authorization: Bearer oa_...
```

A key belongs to the member who created it and inherits that member's client limits. A **read-only** key (the default) cannot call endpoints or tools that change data. A missing or invalid key returns `401 unauthenticated`.

## Endpoints

| Method | Path | What it does |
| --- | --- | --- |
| `POST` | `/v1/call` | Call a raw endpoint or a smart tool on one of your connections. |
| `GET` | `/v1/providers` | List providers: id, name and supported auth methods. |
| `GET` | `/v1/providers/:id` | One provider's raw endpoints and smart tools, each with a JSON Schema for its input. |
| `GET` | `/v1/connections` | Connections this key can see. |
| `GET` | `/v1/logs` | Recent calls, newest first. |
| `GET` | `/v1/logs/:call_id` | One call with its redacted request and response. |

## POST /v1/call

Pass **exactly one** of `endpoint` or `tool`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `provider` | string | yes | Provider id, such as `gsc` or `ga4`. |
| `endpoint` | string | one of | Raw endpoint id, such as `searchanalytics.query`. |
| `tool` | string | one of | Smart tool name, such as `gsc_top_queries`. |
| `input` | object | depends | Input for the endpoint or tool. Validated against its JSON Schema before anything is sent. |
| `connection_id` | string | no | Which connection to use. Needed when more than one active connection exists for the provider. |
| `max_age` | integer | no | Seconds, 0 to 604800. Return a cached response if one is at most this old. See [Caching](/docs/caching.md). |

Raw endpoint input has up to three parts: `path` (URL placeholders), `query` (query string) and `body` (JSON body). Smart tools take a flat object.

```sh title=Raw endpoint
curl https://api.oneapiforagents.com/v1/call \
  -H "Authorization: Bearer $ONEAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "gsc",
    "endpoint": "searchanalytics.query",
    "input": {
      "path": { "siteUrl": "sc-domain:example.com" },
      "body": { "startDate": "2026-08-01", "endDate": "2026-08-28", "dimensions": ["query"], "rowLimit": 10 }
    }
  }'
```

```sh title=Smart tool
curl https://api.oneapiforagents.com/v1/call \
  -H "Authorization: Bearer $ONEAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider":"gsc","tool":"gsc_top_queries","input":{"siteUrl":"sc-domain:example.com"}}'
```

### Response

```json title=200 OK
{
  "call_id": "call_...",
  "connection_id": "con_...",
  "cached": false,
  "cost_usd": 0,
  "latency_ms": 312,
  "data": { "...": "provider response body, or the smart tool's compact output" }
}
```

Once a request is accepted, its response carries an `x-call-id` header, whether the call succeeded or failed. Use it to find the call in **Call logs** or at `GET /v1/logs/:call_id`.

### Errors

Errors use the HTTP status and a stable code:

```json title=Error
{
  "call_id": "call_...",
  "error": {
    "code": "connection_ambiguous",
    "message": "Several gsc connections are available; pass connection_id",
    "details": { "connection_ids": ["con_...", "con_..."] }
  }
}
```

The full list is in [Errors](/docs/errors.md).

## Choosing a connection

If a provider has exactly one active connection you can see, calls use it. If there are several (for example one per client), the call fails with `connection_ambiguous` and lists the ids in `details.connection_ids`. Call `GET /v1/connections`, pick one and pass it as `connection_id`.

```json title=GET /v1/connections
{
  "connections": [
    {
      "id": "con_...",
      "provider": "gsc",
      "auth_type": "oauth",
      "label": "acme.com",
      "client_id": "cli_...",
      "external_account": "marketing@acme.com",
      "scopes": ["https://www.googleapis.com/auth/webmasters.readonly"],
      "status": "active",
      "last_used_at": "2026-09-26T14:02:11.000Z",
      "created_at": "2026-09-01T09:30:00.000Z"
    }
  ]
}
```

`status` is `active`, `expired` or `revoked`. Credentials are never returned.

## Discovering endpoints and tools

`GET /v1/providers/:id` returns everything an agent needs to build a valid call: each raw endpoint's id, description, method, upstream URL, whether it writes, and `input_schema`; and each smart tool's name, description and `input_schema`. The schemas are JSON Schema generated from the same validators the API uses.

```sh
curl https://api.oneapiforagents.com/v1/providers/gsc -H "Authorization: Bearer $ONEAPI_KEY"
```

## Call logs

`GET /v1/logs` returns `{ "calls": [...], "cursor": "..." }`, newest first. Query parameters:

| Parameter | Description |
| --- | --- |
| `limit` | 1 to 200. Default 50. |
| `cursor` | The `cursor` from the previous page. |
| `provider` | Only calls to this provider. |
| `outcome` | `ok` or `error`. |

Each call has its id, provider, target (`raw:<endpoint>` or `tool:<name>`), outcome, HTTP status, error code, latency, cost, whether it was cached, and a timestamp. `GET /v1/logs/:call_id` adds the request and response bodies, with tokens, keys and auth headers redacted.

## Provider reference

Generated from the provider registry. Each provider page lists inputs, types and example calls.

### Google Search Console (`gsc`)

| Kind | Name | Description |
| --- | --- | --- |
| `endpoint` | [`sites.list`](/providers/gsc.md#sites-list) | List Search Console properties this connection can read. |
| `endpoint` | [`sites.get`](/providers/gsc.md#sites-get) | Get one property and the connection's permission level on it. |
| `endpoint` | [`searchanalytics.query`](/providers/gsc.md#searchanalytics-query) | Search Analytics: clicks, impressions, CTR and position grouped by dimensions. |
| `endpoint` | [`sitemaps.list`](/providers/gsc.md#sitemaps-list) | List sitemaps submitted for a property. |
| `endpoint` | [`sitemaps.get`](/providers/gsc.md#sitemaps-get) | Get one submitted sitemap. |
| `endpoint` | [`urlInspection.index.inspect`](/providers/gsc.md#urlinspection-index-inspect) | URL Inspection: index status, crawl and rich-result details for one URL. |
| `tool` | [`gsc_top_queries`](/providers/gsc.md#gsc-top-queries) | Top search queries by clicks for a property over the last N days. |
| `tool` | [`gsc_quick_wins`](/providers/gsc.md#gsc-quick-wins) | Queries ranking just off page one (default positions 8–20) with meaningful impressions, sorted by impressions. |

### Google Analytics 4 (`ga4`)

| Kind | Name | Description |
| --- | --- | --- |
| `endpoint` | [`accountSummaries.list`](/providers/ga4.md#accountsummaries-list) | List GA4 accounts and properties this connection can read. |
| `endpoint` | [`properties.runReport`](/providers/ga4.md#properties-runreport) | Data API runReport: dimensions and metrics for a date range. |
| `endpoint` | [`properties.runRealtimeReport`](/providers/ga4.md#properties-runrealtimereport) | Data API realtime report (last 30 minutes). |
| `endpoint` | [`properties.getMetadata`](/providers/ga4.md#properties-getmetadata) | Dimensions and metrics available for a property, including custom ones. |
| `tool` | [`ga4_traffic_by_page`](/providers/ga4.md#ga4-traffic-by-page) | Top landing pages by sessions, with users and engagement rate, over the last N days. |
| `tool` | [`ga4_list_properties`](/providers/ga4.md#ga4-list-properties) | Every GA4 property this connection can read, with its account, as a flat list. |

### Bing Webmaster Tools (`bing`)

| Kind | Name | Description |
| --- | --- | --- |
| `endpoint` | [`GetUserSites`](/providers/bing.md#getusersites) | List the sites on this Bing Webmaster account, with verification status. |
| `endpoint` | [`GetQueryStats`](/providers/bing.md#getquerystats) | Top search queries with clicks, impressions and average positions, by week. Updated weekly. |
| `endpoint` | [`GetPageStats`](/providers/bing.md#getpagestats) | Top pages with clicks, impressions and average positions (the page URL is in `Query`). Updated weekly. |
| `endpoint` | [`GetRankAndTrafficStats`](/providers/bing.md#getrankandtrafficstats) | Daily clicks and impressions for the whole site. Updated daily. |
| `endpoint` | [`GetQueryPageStats`](/providers/bing.md#getquerypagestats) | Pages that ranked for one query, with clicks, impressions and positions. |
| `endpoint` | [`GetPageQueryStats`](/providers/bing.md#getpagequerystats) | Queries that led to one page, with clicks, impressions and positions. |
| `endpoint` | [`GetQueryTrafficStats`](/providers/bing.md#getquerytrafficstats) | Daily clicks and impressions for one query. |
| `endpoint` | [`GetCrawlStats`](/providers/bing.md#getcrawlstats) | Daily crawl stats for the last 6 months: pages crawled, in index, HTTP code counts, robots.txt blocks. |
| `endpoint` | [`GetCrawlIssues`](/providers/bing.md#getcrawlissues) | URLs with crawl issues. `Issues` is a bit flag: 1 Code301, 2 Code302, 4 Code4xx, 8 Code5xx, 16 BlockedByRobotsTxt, 32 ContainsMalware, 64 ImportantUrlBlockedByRobotsTxt, 128 DnsErrors, 256 TimeOutErrors. |
| `endpoint` | [`GetFeeds`](/providers/bing.md#getfeeds) | Sitemaps and feeds submitted for the site. |
| `endpoint` | [`GetUrlSubmissionQuota`](/providers/bing.md#geturlsubmissionquota) | How many URLs can still be submitted today and this month. |
| `endpoint` | [`GetKeywordStats`](/providers/bing.md#getkeywordstats) | Bing search volume history for a keyword (not tied to your site). |
| `endpoint` | [`SubmitUrl`](/providers/bing.md#submiturl) | Submit one URL for indexing. Uses the site's daily quota. |
| `endpoint` | [`SubmitUrlBatch`](/providers/bing.md#submiturlbatch) | Submit up to 500 URLs for indexing. Uses the site's daily quota. |
| `tool` | [`bing_top_queries`](/providers/bing.md#bing-top-queries) | Top Bing search queries by clicks for a site over the last N days, with impressions, CTR and average position. Bing updates this weekly. |
| `tool` | [`bing_top_pages`](/providers/bing.md#bing-top-pages) | Top pages in Bing search by clicks for a site over the last N days, with impressions, CTR and average position. |
| `tool` | [`bing_crawl_health`](/providers/bing.md#bing-crawl-health) | Crawl health for a site in Bing: pages in index, crawl and HTTP error totals over the last N days, and the URLs with crawl issues (most linked first). |
| `tool` | [`bing_list_sites`](/providers/bing.md#bing-list-sites) | Sites on the connected Bing Webmaster account and whether each is verified. |

### Google Sheets (`gsheets`)

| Kind | Name | Description |
| --- | --- | --- |
| `endpoint` | [`spreadsheets.get`](/providers/gsheets.md#spreadsheets-get) | Spreadsheet metadata: title, tabs and their grid sizes. Use `fields` (a field mask) to keep responses small; includeGridData returns cell data and is ignored when `fields` is set. |
| `endpoint` | [`values.get`](/providers/gsheets.md#values-get) | Read one range. Trailing empty rows and columns are omitted. |
| `endpoint` | [`values.batchGet`](/providers/gsheets.md#values-batchget) | Read several ranges in one request. |
| `endpoint` | [`values.update`](/providers/gsheets.md#values-update) | Overwrite one range with a ValueRange. valueInputOption is required. |
| `endpoint` | [`values.append`](/providers/gsheets.md#values-append) | Append rows after the table found in `range`. valueInputOption is required. |
| `endpoint` | [`values.batchUpdate`](/providers/gsheets.md#values-batchupdate) | Overwrite several ranges in one request. |
| `endpoint` | [`values.clear`](/providers/gsheets.md#values-clear) | Clear the values in a range. Formatting and validation are kept. |
| `endpoint` | [`spreadsheets.create`](/providers/gsheets.md#spreadsheets-create) | Create a spreadsheet from a Spreadsheet resource. Needs a Google sign-in connection: service accounts have no Drive storage to own files. |
| `endpoint` | [`spreadsheets.batchUpdate`](/providers/gsheets.md#spreadsheets-batchupdate) | Structural changes (add, rename or delete tabs, formatting, sorting, …) as a list of requests, applied atomically. |
| `tool` | [`sheets_read`](/providers/gsheets.md#sheets-read) | Read a tab or range as rows of objects keyed by the header row. Capped by `limit`; page with `offset`. |
| `tool` | [`sheets_list_tabs`](/providers/gsheets.md#sheets-list-tabs) | The spreadsheet's title, URL and tabs, with each tab's grid size (rows × columns, including empty cells). |
| `tool` | [`sheets_append_rows`](/providers/gsheets.md#sheets-append-rows) | Append rows below a tab's existing data. Pass objects keyed by header name, or arrays in column order. |
| `tool` | [`sheets_update_range`](/providers/gsheets.md#sheets-update-range) | Overwrite cells starting at a range with rows of values. |
| `tool` | [`sheets_create`](/providers/gsheets.md#sheets-create) | Create a spreadsheet in the connected Google account's Drive, optionally with a frozen header row. Returns its ID and URL. Needs a Google sign-in connection (service accounts can't own files). |

### Google Docs (`gdocs`)

| Kind | Name | Description |
| --- | --- | --- |
| `endpoint` | [`documents.get`](/providers/gdocs.md#documents-get) | The full Document resource. Pass includeTabsContent=true to get every tab in `tabs` (otherwise `body` holds the first tab only). |
| `endpoint` | [`documents.create`](/providers/gdocs.md#documents-create) | Create a blank document. Only `title` is used; add content with documents.batchUpdate. |
| `endpoint` | [`documents.batchUpdate`](/providers/gdocs.md#documents-batchupdate) | Apply Docs requests atomically (insertText, deleteContentRange, replaceAllText, createParagraphBullets, …). Indexes are UTF-16 code units; order edits from the highest index down. |
| `tool` | [`docs_read`](/providers/gdocs.md#docs-read) | Read a Google Doc as markdown-style text (headings, lists, tables, links), with its title, revisionId, tabs, heading outline with indexes, and endIndex. |
| `tool` | [`docs_create`](/providers/gdocs.md#docs-create) | Create a Google Doc with a title and optional initial text (markdown headings, lists and paragraphs become Docs styles). Returns its ID and URL. |
| `tool` | [`docs_append`](/providers/gdocs.md#docs-append) | Append text or simple markdown to the end of a Google Doc (or of one tab). |
| `tool` | [`docs_replace_text`](/providers/gdocs.md#docs-replace-text) | Replace every occurrence of some text in a Google Doc. Case-sensitive unless match_case is false. |
| `tool` | [`docs_insert`](/providers/gdocs.md#docs-insert) | Insert text or simple markdown into a Google Doc, either below a heading (matched by its text) or at an index from docs_read. Pass exactly one of heading or index. |
