# Multi-platform search & creator card

Two endpoints send one input to several platforms at once and give you the answers side by side. `GET /v1/search/multi` runs the same query on each platform's search endpoint; `GET /v1/creator/card` fetches the same handle's profile on each. Each platform is a separate leg that runs through the ordinary pipeline, so prices, caching and refunds are exactly those of the endpoint it uses.

```bash
GET https://api.onekey.dev/v1/search/multi?query={text}&platforms={a,b,c}
GET https://api.onekey.dev/v1/creator/card?handle={handle}&platforms={a,b,c}
x-api-key: YOUR_API_KEY
```

## When to use it

- **Search:** "what is being said about X" across communities, or "which packages are called Y" across registries, in one call rather than one per platform.
- **Creator card:** the same person or project across the platforms they use, given one handle.
- Both when you want per-platform outcomes without one platform's failure hiding the others.

For arbitrary mixes of endpoints and parameters, use [batch](https://onekey.dev/docs/batch.md) instead.

## Parameters

| Parameter | Endpoint | Required | What it is |
| --- | --- | --- | --- |
| `query` | `/v1/search/multi` | yes | The search text, at most 200 characters, sent as each search endpoint's query parameter. |
| `handle` | `/v1/creator/card` | yes | The username or handle, at most 200 characters. Each profile endpoint applies its own normalisation (a leading `@` is removed where the endpoint does that). |
| `platforms` | both | yes | Comma-separated platform ids from the tables below, up to 20. Case does not matter, duplicates are collapsed, and the order is the order of the legs. |
| `fuse` | `/v1/search/multi` | no | `rrf` adds a single merged list (see [Rank fusion](#rank-fusion-fuse-rrf)). Any other value is `422 INVALID_PARAMS`; on `/v1/creator/card` it is refused. |
| `include` | both | no | Reserved for optional enrichment steps that are **not available yet**. Any value is refused with `422 INVALID_PARAMS` rather than silently ignored. |

## Multi-platform search

```bash
curl "https://api.onekey.dev/v1/search/multi?query=rust&platforms=hackernews,bluesky,gitlab" \
  -H "x-api-key: YOUR_API_KEY"
```

```python
import requests

res = requests.get(
    "https://api.onekey.dev/v1/search/multi",
    params={"query": "rust", "platforms": "hackernews,bluesky,gitlab"},
    headers={"x-api-key": "YOUR_API_KEY"},
)
body = res.json()

if body["success"]:
    for platform, row in body["data"].items():
        print(platform, row["status"], len(row["data"] or []))
else:
    print(body["error"]["type"], body["error"]["message"])
```

```javascript
const params = new URLSearchParams({ query: "rust", platforms: "hackernews,bluesky,gitlab" });
const res = await fetch(`https://api.onekey.dev/v1/search/multi?${params}`, {
  headers: { "x-api-key": "YOUR_API_KEY" },
});
const body = await res.json();

if (body.success) for (const [platform, row] of Object.entries(body.data)) console.log(platform, row.status, row.data?.length ?? 0);
else console.error(body.error.type, body.error.message);
```

`data` is an object keyed by platform id, one row per requested platform. Recorded from the live API, lists shortened:

```json
{
  "success": true,
  "data": {
    "hackernews": {
      "index": 0, "platform": "hackernews", "endpoint": "search", "params": { "q": "rust" },
      "status": 200,
      "data": [ { "content": { "id": "22238335", "title": "Why Discord is switching from Go to Rust", "url": "https://blog.discordapp.com/...", "createdAt": "2020-02-04T17:30:40Z" }, "engagement": { "likes": 1582, "comments": 642 }, "author": { "username": "Sikul" }, "computed": { "engagement_rate": null, "language": "en" } }, "...9 more" ],
      "error": null, "credits_charged": 5, "cached": false,
      "pagination": { "next_cursor": "eyJiIjoiNGJlODQ0YmYwN2IzIiwicCI6IjEiLCJzIjoiaGFja2VybmV3cy5zZWFyY2giLCJ2IjoxfQ.UeYSZjaLLB5UZeSakGfkew", "has_more": true, "page_size": 10 }
    },
    "bluesky": {
      "index": 1, "platform": "bluesky", "endpoint": "search", "params": { "q": "rust" },
      "status": 200,
      "data": [ { "author": { "username": "rusty.todayintabs.com", "displayName": "Rusty Foster", "...": "..." }, "content": { "text": "..." } }, "...9 more" ],
      "error": null, "credits_charged": 5, "cached": false,
      "pagination": { "next_cursor": "...", "has_more": true, "page_size": 10 }
    },
    "gitlab": {
      "index": 2, "platform": "gitlab", "endpoint": "search", "params": { "q": "rust" },
      "status": 200,
      "data": [ { "content": { "id": "10174980", "title": "veloren", "url": "https://gitlab.com/veloren/veloren", "...": "..." }, "engagement": { "likes": 2399, "shares": 817 }, "author": { "username": "veloren" } }, "...9 more" ],
      "error": null, "credits_charged": 5, "cached": false
    }
  },
  "metadata": {
    "recipe": "search_multi", "query": "rust", "platforms": ["hackernews", "bluesky", "gitlab"],
    "legs": 3, "succeeded": 3, "failed": 0, "credits_charged": 15,
    "request_id": "81a469769d884da7b47b7fa118d50766", "idempotent_replay": false
  },
  "error": null
}
```

Each platform's list is that endpoint's **first page**, in the platform's own order. `endpoint` names the leg that ran, so you can read its page for the fields it returns. To page further, call that endpoint directly with its `next_cursor` (for the row above: `GET /v1/hackernews/search?q=rust&cursor=...`); a cursor is bound to the endpoint and its query, not to this call.

### Platforms with a search leg

19 platforms. Each platform has exactly one endpoint in this role, generated here from the same declaration the API uses; `x-platforms` on `/v1/search/multi` in [`/openapi.json`](https://onekey.dev/openapi.json) and `features.search` in `GET /v1/platforms` are the live list. Read the third column: some legs search people, packages or channels rather than posts, and the same `query` means whatever that endpoint makes of it.

| Platform | Endpoint | What the leg searches | Price |
| --- | --- | --- | --- |
| `bluesky` | [`bluesky.search`](https://onekey.dev/docs/api/bluesky/search.md) | Search Bluesky users by keyword | 1 credit |
| `crates` | [`crates.search`](https://onekey.dev/docs/api/crates/search.md) | Search crates.io | 5 credits |
| `devto` | [`devto.search`](https://onekey.dev/docs/api/devto/search.md) | List popular DEV articles for a tag | 5 credits |
| `dockerhub` | [`dockerhub.search`](https://onekey.dev/docs/api/dockerhub/search.md) | Search Docker Hub repositories | 5 credits |
| `github` | [`github.search_repos`](https://onekey.dev/docs/api/github/search_repos.md) | Search GitHub repositories (most starred first) | 5 credits |
| `gitlab` | [`gitlab.search`](https://onekey.dev/docs/api/gitlab/search.md) | Search public GitLab projects (most starred first) | 5 credits |
| `hackernews` | [`hackernews.search`](https://onekey.dev/docs/api/hackernews/search.md) | Search Hacker News stories by keyword | 1 credit |
| `huggingface` | [`huggingface.models`](https://onekey.dev/docs/api/huggingface/models.md) | Search Hugging Face models | 5 credits |
| `lemmy` | [`lemmy.search_posts`](https://onekey.dev/docs/api/lemmy/search_posts.md) | Search Lemmy posts | 5 credits |
| `mastodon` | [`mastodon.search_accounts`](https://onekey.dev/docs/api/mastodon/search_accounts.md) | Search Mastodon accounts | 5 credits |
| `npm` | [`npm.search`](https://onekey.dev/docs/api/npm/search.md) | Search the npm registry (with popularity and quality scores) | 5 credits |
| `reddit` | [`reddit.search_posts`](https://onekey.dev/docs/api/reddit/search_posts.md) | Search Reddit posts | 2 credits |
| `soundcloud` | [`soundcloud.search_tracks`](https://onekey.dev/docs/api/soundcloud/search_tracks.md) | Search SoundCloud tracks by keyword | 3 credits |
| `stackexchange` | [`stackexchange.search`](https://onekey.dev/docs/api/stackexchange/search.md) | Search Stack Exchange questions | 5 credits |
| `tiktok` | [`tiktok.search_videos`](https://onekey.dev/docs/api/tiktok/search_videos.md) | Search TikTok videos by keyword | 2 credits |
| `twitch` | [`twitch.search_channels`](https://onekey.dev/docs/api/twitch/search_channels.md) | Search Twitch channels | 5 credits |
| `wikipedia` | [`wikipedia.search`](https://onekey.dev/docs/api/wikipedia/search.md) | Search Wikipedia articles (English) | 5 credits |
| `x` | [`x.search`](https://onekey.dev/docs/api/x/search.md) | Search recent tweets by keyword or hashtag | 2 credits |
| `youtube` | [`youtube.search_videos`](https://onekey.dev/docs/api/youtube/search_videos.md) | Search YouTube videos by keyword | 2 credits |

## Creator card

```bash
curl "https://api.onekey.dev/v1/creator/card?handle=torvalds&platforms=github,gitlab,bluesky" \
  -H "x-api-key: YOUR_API_KEY"
```

```python
import requests

res = requests.get(
    "https://api.onekey.dev/v1/creator/card",
    params={"handle": "torvalds", "platforms": "github,gitlab,bluesky"},
    headers={"x-api-key": "YOUR_API_KEY"},
)
body = res.json()

if body["success"]:
    for platform, row in body["data"].items():
        print(platform, row["status"], row["data"] and row["data"]["author"]["followers"])
else:
    print(body["error"]["type"], body["error"]["message"])
```

```javascript
const params = new URLSearchParams({ handle: "torvalds", platforms: "github,gitlab,bluesky" });
const res = await fetch(`https://api.onekey.dev/v1/creator/card?${params}`, {
  headers: { "x-api-key": "YOUR_API_KEY" },
});
const body = await res.json();

if (body.success) for (const [platform, row] of Object.entries(body.data)) console.log(platform, row.status, row.data?.author?.followers ?? null);
else console.error(body.error.type, body.error.message);
```

Recorded from the live API. One leg succeeded (from cache), one handle does not exist on GitLab, and the Bluesky source failed for this handle (a bare name is not a full Bluesky handle), which is the normal shape of a partial success:

```json
{
  "success": true,
  "data": {
    "github": {
      "index": 0, "platform": "github", "endpoint": "profile", "params": { "username": "torvalds" },
      "status": 200,
      "data": { "author": { "id": "1024025", "username": "torvalds", "displayName": "Linus Torvalds", "followers": 325709, "following": 0, "url": "https://github.com/torvalds", "avatarUrl": "https://avatars.githubusercontent.com/u/1024025?v=4" }, "engagement": { "comments": 12 }, "content": { "text": null }, "computed": { "language": null } },
      "error": null, "credits_charged": 0, "cached": true
    },
    "gitlab": {
      "index": 1, "platform": "gitlab", "endpoint": "user", "params": { "username": "torvalds" },
      "status": 404, "data": null,
      "error": { "code": "not_found", "type": "NOT_FOUND", "message": "Not found", "doc_url": "https://onekey.dev/errors/NOT_FOUND" },
      "credits_charged": 0, "cached": false
    },
    "bluesky": {
      "index": 2, "platform": "bluesky", "endpoint": "profile", "params": { "handle": "torvalds" },
      "status": 502, "data": null,
      "error": { "code": "upstream_error", "type": "UPSTREAM_ERROR", "message": "The upstream platform failed to respond", "doc_url": "https://onekey.dev/errors/UPSTREAM_ERROR" },
      "credits_charged": 0, "cached": false
    }
  },
  "metadata": {
    "recipe": "creator_card", "handle": "torvalds", "platforms": ["github", "gitlab", "bluesky"],
    "legs": 3, "succeeded": 1, "failed": 2, "credits_charged": 0,
    "request_id": "22b51f3ee0854bedac053b0764811813", "idempotent_replay": false
  },
  "error": null
}
```

### Platforms with a profile leg

17 platforms. The same handle is sent to each endpoint's handle parameter, so a name that is spelled differently on one platform simply comes back `404` there.

| Platform | Endpoint | What the leg fetches | Price |
| --- | --- | --- | --- |
| `bluesky` | [`bluesky.profile`](https://onekey.dev/docs/api/bluesky/profile.md) | Fetch a Bluesky user's public profile | 1 credit |
| `crates` | [`crates.user`](https://onekey.dev/docs/api/crates/user.md) | Public profile of a crates.io user | 1 credit |
| `devto` | [`devto.profile`](https://onekey.dev/docs/api/devto/profile.md) | Fetch a DEV (dev.to) user's public profile | 1 credit |
| `github` | [`github.profile`](https://onekey.dev/docs/api/github/profile.md) | Fetch a GitHub user's public profile | 1 credit |
| `gitlab` | [`gitlab.user`](https://onekey.dev/docs/api/gitlab/user.md) | GitLab.com public user profile | 1 credit |
| `hackernews` | [`hackernews.user`](https://onekey.dev/docs/api/hackernews/user.md) | Fetch a Hacker News user profile | 1 credit |
| `huggingface` | [`huggingface.user`](https://onekey.dev/docs/api/huggingface/user.md) | Hugging Face user profile | 1 credit |
| `instagram` | [`instagram.profile`](https://onekey.dev/docs/api/instagram/profile.md) | Instagram profile: bio, followers, following, post count, verification, avatar | 2 credits |
| `lemmy` | [`lemmy.user`](https://onekey.dev/docs/api/lemmy/user.md) | A Lemmy user's profile | 1 credit |
| `lobsters` | [`lobsters.user`](https://onekey.dev/docs/api/lobsters/user.md) | Fetch a Lobsters user profile | 1 credit |
| `mastodon` | [`mastodon.profile`](https://onekey.dev/docs/api/mastodon/profile.md) | Fetch a Mastodon account (default instance mastodon.social) | 1 credit |
| `reddit` | [`reddit.user_about`](https://onekey.dev/docs/api/reddit/user_about.md) | A Reddit user's profile | 1 credit |
| `soundcloud` | [`soundcloud.profile`](https://onekey.dev/docs/api/soundcloud/profile.md) | SoundCloud artist page card: name, bio snippet, avatar | 1 credit |
| `tiktok` | [`tiktok.profile`](https://onekey.dev/docs/api/tiktok/profile.md) | TikTok user profile: nickname, bio, followers, following, likes, video count, secUid | 2 credits |
| `twitch` | [`twitch.profile`](https://onekey.dev/docs/api/twitch/profile.md) | Twitch channel profile: display name, bio, followers, avatar, creation date | 1 credit |
| `x` | [`x.user`](https://onekey.dev/docs/api/x/user.md) | Public profile for an X handle: followers, following, bio, avatar | 1 credit |
| `youtube` | [`youtube.channel_by_handle`](https://onekey.dev/docs/api/youtube/channel_by_handle.md) | YouTube channel details by @handle | 2 credits |

## The rows

| Field | Type | Meaning |
| --- | --- | --- |
| `index` | number | Position of this item in your request, from `0`. |
| `platform`, `endpoint` | string | The endpoint that ran. |
| `params` | object | The parameters it ran with, every value as a string. |
| `status` | number | The HTTP status this call would have had on its own: `200`, or `404`, `422`, `502`... |
| `data` | object, array or null | The unified result when `status` is `200`, exactly as the endpoint returns it (including its [`computed` block](https://onekey.dev/docs/computed.md) where it has one). `null` otherwise. |
| `error` | object or null | `null` on success. Otherwise `code`, `type`, `message`, `doc_url`, as in any [error](https://onekey.dev/docs/errors.md). |
| `credits_charged` | number | What this item cost. `0` for a cache hit or a failure. |
| `cached` | boolean | `true` when the answer came from cache. |
| `pagination` | object | Only when the endpoint pages: its `next_cursor`, `has_more`, `page_size`. To get the next page, call the endpoint directly with that cursor (see [Pagination](https://onekey.dev/docs/pagination.md)). |

### Metadata

| Field | Meaning |
| --- | --- |
| `recipe` | `search_multi` or `creator_card`. |
| `query` or `handle` | Your input, trimmed. |
| `platforms` | The platforms as run, in leg order. |
| `legs`, `succeeded`, `failed` | How many legs ran, how many rows have `status: 200`, and how many do not. |
| `credits_charged` | The sum of the rows' `credits_charged`. |
| `fuse` | Only with `fuse=rrf`: `{"method": "rrf", "k": 60}`. |
| `request_id`, `idempotent_replay` | As on every response. |

## Partial success

- A `200` means the call ran. Some rows may still be failures; `metadata.succeeded` and `failed` count them, and each failed row carries its own `error`.
- When **every** leg fails, the call fails with the **first** leg's error (in `platforms` order): a `404` if the first platform found nothing, a `502` if its source failed, and so on. Nothing is charged, since every leg was refunded.
- A platform with no endpoint in that role is refused **before** anything runs: `422 UNSUPPORTED_PLATFORM`, naming the platform(s), free. Check the tables above or `GET /v1/platforms` rather than guessing.
- A missing `query`, `handle` or `platforms`, more than 20 platforms, an input over 200 characters, or a reserved name such as `fused` given as a platform is `422 INVALID_PARAMS`, free.

```bash
curl "https://api.onekey.dev/v1/search/multi?query=rust&platforms=hackernews,myspace" \
  -H "x-api-key: YOUR_API_KEY"
# HTTP/1.1 422 Unprocessable Content
```

```json
{
  "success": false,
  "data": null,
  "metadata": { "request_id": "b030900d263840c491b87f8c2a4450de" },
  "error": {
    "code": "unsupported_platform",
    "type": "UNSUPPORTED_PLATFORM",
    "message": "No search endpoint for platform(s): myspace",
    "request_id": "b030900d263840c491b87f8c2a4450de",
    "doc_url": "https://onekey.dev/errors/UNSUPPORTED_PLATFORM"
  }
}
```

## What it costs

The sum of the legs that succeeded, each at its endpoint's own price (the last column of the tables; endpoints cost 1 to 8 credits). A leg served from cache is free (a cached response over 100 KB costs 0.2 credit), and failed legs are refunded. Three search legs at 5 credits each is 15 credits, as in the recorded response above; the creator card above cost 0 because its only successful leg was a cache hit. Fusion costs nothing extra.

Before anything runs, Onekey adds up the most every item could cost (each endpoint's price, or for an endpoint with more than one data route the price of its dearest one) and refuses the whole call if that sum exceeds your balance (`402 INSUFFICIENT_CREDITS`) or the key's remaining [credit limit](https://onekey.dev/docs/key-limits.md) (`402 KEY_BUDGET_EXCEEDED`). Nothing is run or charged, and the message states both numbers, for example `This call could cost up to 15 credits; the account balance is 10 credits. Nothing was run or charged` (for a key limit: `... this key has 4 of its 500-credit budget left ...`). The check does not look at the cache, so items that would have been free cache hits still count at full price here. Keep enough balance for the worst case even when you expect most items to be cached.

Rate limit: one call is **one request** against your per-minute allowance, however many platforms it fans out to. An [`Idempotency-Key`](https://onekey.dev/docs/idempotency.md) covers the whole call, bound to the query string (input, platforms and `fuse`); a replay returns the stored rows with `credits_charged: 0`. A call that fails as a whole releases the key.

## Rank fusion: fuse=rrf

Add `fuse=rrf` to `/v1/search/multi` and the answer gains `data.fused`: one merged list built by **reciprocal rank fusion**. It is plain arithmetic over the order each platform returned, no text analysis and no judgement of relevance on our side.

The rule: for every leg that succeeded, the item at 1-based position `r` in that platform's list scores

```text
score = 1 / (k + r)        with k = 60
```

so rank 1 scores 0.016393, rank 2 scores 0.016129, rank 10 scores 0.014286. An item that appears on several platforms adds up its scores: first on one platform and fourth on another is 0.016393 + 0.015625 = 0.032018, which beats anything that is first on a single platform. The constant 60 keeps the difference between neighbouring ranks small, so appearing on two platforms matters more than being one place higher on one of them.

```bash
curl "https://api.onekey.dev/v1/search/multi?query=rust&platforms=hackernews,devto&fuse=rrf" \
  -H "x-api-key: YOUR_API_KEY"
```

```json
{
  "success": true,
  "data": {
    "hackernews": { "index": 0, "status": 200, "data": [ "...10 stories..." ], "credits_charged": 0, "cached": true, "...": "..." },
    "devto": { "index": 1, "status": 200, "data": [ "...10 articles..." ], "credits_charged": 5, "cached": false, "...": "..." },
    "fused": [
      { "score": 0.016393, "platform": "hackernews", "platforms": ["hackernews"], "ranks": { "hackernews": 1 }, "key": "url", "item": { "content": { "title": "Why Discord is switching from Go to Rust", "...": "..." }, "...": "..." } },
      { "score": 0.016393, "platform": "devto", "platforms": ["devto"], "ranks": { "devto": 1 }, "key": "url", "item": { "...": "..." } },
      { "score": 0.016129, "platform": "hackernews", "platforms": ["hackernews"], "ranks": { "hackernews": 2 }, "key": "url", "item": { "...": "..." } },
      "...17 more"
    ]
  },
  "metadata": { "recipe": "search_multi", "query": "rust", "platforms": ["hackernews", "devto"], "fuse": { "method": "rrf", "k": 60 }, "legs": 2, "succeeded": 2, "failed": 0, "credits_charged": 5, "request_id": "17de1a377b09486399b279799307b805", "idempotent_replay": false },
  "error": null
}
```

| Fused entry field | Meaning |
| --- | --- |
| `score` | The summed reciprocal-rank score, 6 decimals. |
| `item` | The unified item, exactly as it appears in its platform's row (the copy from the first platform that had it). |
| `platform` | The first platform (in your `platforms` order) that returned it. |
| `platforms` | Every platform that returned it. |
| `ranks` | Its 1-based position in each of those platforms' lists. |
| `key` | How identity was decided: `url`, `id` or `pos` (below). |

**Which items count as the same thing.** Identity is the canonical `content.url` when the endpoint maps one: scheme and host lower-cased, a leading `www.` dropped, no fragment, no trailing slash. That is the only key that merges across platforms, so a story on one platform and an article on another merge only when they link to the same page. Items without a URL are keyed by `platform:content.id` and never merge across platforms; items with neither are keyed by their position. The same URL twice in one platform's list counts once, at its first rank.

**Order.** By `score` descending; ties are broken by the best rank the item reached, then by the position of its first platform in your `platforms` order, then by that rank. The result is fully deterministic: the same rows always fuse the same way.

The per-platform rows are unchanged, `metadata.fuse` records the method and `k`, and the price is the same as without `fuse`. A failed leg simply contributes nothing. When streaming, the fused list arrives as one `fused` frame before `done` (see [Streaming](https://onekey.dev/docs/streaming.md)).

## Honest limits

- **First page only.** Each leg is one page of its endpoint (its `page_size`). Page further on the endpoint itself.
- **A search leg is whatever that platform's search endpoint is.** On some platforms it searches users, packages, models or channels rather than posts; the table says which. Results are not filtered or reranked by us.
- **No cross-platform relevance.** Side by side, the rows are in each platform's own order. `fuse=rrf` merges by rank position only; a platform that returns weak results in a confident order still contributes its ranks.
- **Fusion rarely merges across platforms.** Most items carry a platform-specific URL (`key: "url"` but a URL only that platform has) or no URL at all, so `platforms` usually has one entry. Merging happens when several platforms link to the same outside page.
- **A handle is not an identity.** The creator card sends the same string to every platform; it does not verify that the accounts belong to the same person.

## Errors it can return

For the call as a whole (nothing is run or charged):

| Status | Type | When |
| --- | --- | --- |
| 422 | [`UNSUPPORTED_PLATFORM`](https://onekey.dev/docs/errors.md#unsupported-platform) | A requested platform has no endpoint in that role. |
| 422 | [`INVALID_PARAMS`](https://onekey.dev/docs/errors.md#invalid-params) | `query`, `handle` or `platforms` missing; more than 20 platforms; input over 200 characters; a reserved platform name; a bad `fuse` value, `fuse` on `/v1/creator/card`, or any `include` value. |
| 402 | [`INSUFFICIENT_CREDITS`](https://onekey.dev/docs/errors.md#insufficient-credits), [`KEY_BUDGET_EXCEEDED`](https://onekey.dev/docs/errors.md#key-budget-exceeded) | The worst-case total is above your balance or the key's limit. |
| 401 | [`UNAUTHORIZED`](https://onekey.dev/docs/errors.md#unauthorized) | Bad or missing key. |
| 429 | [`RATE_LIMITED`](https://onekey.dev/docs/errors.md#rate-limited) | Wait `Retry-After` seconds. |
| Any | The first leg's error | Every leg failed: the call takes the status and `error` of the first leg, most often [`NOT_FOUND`](https://onekey.dev/docs/errors.md#not-found) or [`UPSTREAM_ERROR`](https://onekey.dev/docs/errors.md#upstream-error). |

Inside a row, `status` and `error.type` can be anything a single call returns, most often [`NOT_FOUND`](https://onekey.dev/docs/errors.md#not-found) and the `UPSTREAM_*` types. Plus the [idempotency](https://onekey.dev/docs/idempotency.md) answers when you send an `Idempotency-Key`. See [Errors](https://onekey.dev/docs/errors.md) for the full list.
