--- title: "Usage & billing" description: "What counts against your quota, what's free, and how to track spend per API key." --- You're billed for what supermemory processes, not what it stores. Tokens are counted once, at ingestion — searches, profile reads, and memory injection don't draw them down. Start by checking where you stand: ```typescript TypeScript const res = await fetch("https://api.supermemory.ai/v3/auth/billing/usage", { headers: { Authorization: `Bearer ${process.env.SUPERMEMORY_API_KEY}` }, }); const { items, periodStart, periodEnd } = await res.json(); ``` ```python Python import requests res = requests.get( "https://api.supermemory.ai/v3/auth/billing/usage", headers={"Authorization": f"Bearer {SUPERMEMORY_API_KEY}"}, ) usage = res.json() ``` ```bash cURL curl "https://api.supermemory.ai/v3/auth/billing/usage" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" ``` You get back each meter with its usage and limit, plus your current billing period: ```json { "items": [ { "name": "sm tokens text", "used": 184203, "limit": 1000000, "unit": "tokens" }, { "name": "sm search queries", "used": 4210, "limit": 100000, "unit": "queries" } ], "periodStart": "2026-07-01T00:00:00.000Z", "periodEnd": "2026-08-01T00:00:00.000Z" } ``` {/* CONFIRM: billing usage response shape and exact meter names */} One thing to know up front: scoped API keys can **not** read billing endpoints — they return a 403. Use an unscoped key, or check the billing page in the console instead. {/* CONFIRM: scoped-key 403 on billing endpoints */} ## What "tokens processed" counts Every document you add — via the API, a connector, MCP, or any other door — goes through the ingestion pipeline. The tokens of the **extracted content** are what's metered. Not your raw upload size, not the embeddings, not the memories derived from it: the token count of the text supermemory pulled out of your document. Two meters exist: - **Text tokens** — plain text, tweets, markdown. - **Rich content tokens** — PDFs, images, files, web pages. Anything that needs extraction before it's text. Rich content costs more per token than plain text, because extraction does more work. {/* CONFIRM: text vs rich meter split and relative pricing */} If you can send markdown instead of a PDF of the same content, send markdown — it's also what the [ingestion guide](/patterns/ingestion) recommends for quality reasons. Updates are billed on the **delta**. When you update a document (or re-add one with the same `customId`), you're charged only for the token count *increase* over what that document already cost. Re-processing unchanged content bills zero. So appending a session to an existing conversation document charges you for the new turns, not the whole history again — this is why [ingesting full conversations under one `customId`](/patterns/ingestion) is cheaper than adding every turn as its own document. {/* CONFIRM: delta billing on updates and customId re-adds */} And the reads are not on this meter at all: - **Search** is metered per query, not per token — and priced low enough that it's effectively free at any realistic volume. Ingestion is where your money goes. - **Profile reads** don't consume tokens. A `client.profile({ containerTag })` call isn't metered; add a `q` and it counts as one search query. - **Memory injection** — the AI SDK wrapper putting a profile or search results into your prompt — is a profile/search read under the hood, so it follows the same rules. It never consumes ingestion tokens. {/* CONFIRM: injection billing — verified in code (read paths only hit the search-query meter), confirm this is the publishable statement */} - **Storage is free.** A document you ingested in January costs nothing to keep in July. ## Deleting documents does not restore quota The meter counts processing, and the processing already happened. Deleting a document removes its content, chunks, and derived memories — but the tokens it consumed stay consumed. Your quota is a record of work done, not a measure of what's currently stored. Your quota refreshes at the start of each billing period. Unused quota doesn't roll over. {/* CONFIRM: monthly refresh cadence + no-rollover on all plans */} If you're near the limit, deleting old documents won't buy you headroom — upgrading or waiting for the reset will. ## Model your costs The mental math is short: 1. **Ingestion is the cost driver.** Estimate the tokens in what you'll send — that's most of your bill. 2. **Search is ~free.** Query as much as you want; per-query pricing is negligible next to ingestion. 3. **Profiles are cheap to use.** A profile fits in roughly a 1k-token budget and its shape is stable between updates, so it's prompt-cache-friendly on the LLM side too. 4. **Send conversations, not turns.** One document per session with a `customId` beats one document per message — better memories *and* delta billing. ## Cut costs with `taskType: "superrag"` If a set of documents only needs to be searchable — you'll never want derived memories, a graph, or profile contributions from it — ingest it with `taskType: "superrag"`. That runs the retrieval-only pipeline (extract, chunk, embed) and skips memory derivation, at about 5x cheaper per token than the default `"memory"` task type. {/* CONFIRM: taskType param name and "superrag"/"memory" values */} A support-docs corpus is the typical case: ```typescript TypeScript const res = await fetch("https://api.supermemory.ai/v3/documents", { method: "POST", headers: { Authorization: `Bearer ${process.env.SUPERMEMORY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ content: "https://help.acme.dev/articles/refund-policy", containerTag: "acme_help_center", taskType: "superrag", }), }); ``` ```python Python import requests requests.post( "https://api.supermemory.ai/v3/documents", headers={"Authorization": f"Bearer {SUPERMEMORY_API_KEY}"}, json={ "content": "https://help.acme.dev/articles/refund-policy", "containerTag": "acme_help_center", "taskType": "superrag", }, ) ``` ```bash cURL curl -X POST "https://api.supermemory.ai/v3/documents" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "https://help.acme.dev/articles/refund-policy", "containerTag": "acme_help_center", "taskType": "superrag" }' ``` Use `"memory"` (the default) for anything about your users — conversations, preferences, facts you want the engine to reason over. Use `"superrag"` for reference material you only retrieve. The examples above use raw `POST /v3/documents` because the TS SDK typings don't include `taskType` yet. Documents ingested with `"superrag"` show up in [document search](/search) but don't produce memories, so they won't appear in memory search results or [profiles](/concepts/user-profiles). ## Track usage per API key If you run one key per environment — or per tenant — you can see exactly which key spent what. `GET /v3/analytics/usage` breaks usage down by key, including tokens: ```typescript TypeScript const res = await fetch( "https://api.supermemory.ai/v3/analytics/usage?period=30d", { headers: { Authorization: `Bearer ${process.env.SUPERMEMORY_API_KEY}` } }, ); const { byKey } = await res.json(); ``` ```python Python import requests res = requests.get( "https://api.supermemory.ai/v3/analytics/usage", params={"period": "30d"}, headers={"Authorization": f"Bearer {SUPERMEMORY_API_KEY}"}, ) by_key = res.json()["byKey"] ``` ```bash cURL curl "https://api.supermemory.ai/v3/analytics/usage?period=30d" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" ``` Each entry in `byKey` carries the token total for that key: ```json { "byKey": [ { "keyId": "key_prod_4f8a", "keyName": "Production API", "count": 23410, "tokensUsed": 1284203, "avgDuration": 98.7, "lastUsed": "2026-07-15T14:35:00Z" } ], "usage": [ { "type": "add", "count": 1523, "avgDuration": 245.5 }, { "type": "search", "count": 3421, "avgDuration": 89.2 } ] } ``` The endpoint also accepts `from`/`to` (ISO 8601) instead of `period`, and paginates with `page` and `limit`. {/* CONFIRM: analytics usage response fields and query params */} The same family has `/v3/analytics/errors` and `/v3/analytics/logs` for error breakdowns and request-level logs. ## Handle running out When a meter is exhausted, writes start returning `402` with a body that names the meter: ```json { "error": "Text tokens limit reached", "details": "You've run out of credits. Top up to continue." } ``` {/* CONFIRM: 402 status and exact body shape */} Catch the `402` in your ingestion path and queue the writes — reads keep working, so your app degrades to "remembers everything up to now" rather than breaking. Whether usage past the included quota bills as overage or hard-blocks depends on your plan and its overage setting. {/* CONFIRM: overage defaults and availability by plan */} ## Manage invoices, downgrades, and cancellation Invoices, payment methods, plan changes, and cancellation all live in the console's billing settings. {/* CONFIRM: exact console navigation path */} Only org admins can manage billing. When you downgrade or cancel, your data is not deleted — you keep read access, and ingestion is governed by the lower plan's quota from the next billing period. {/* CONFIRM: plan-downgrade data behavior — verify data retention and any limits enforcement on existing over-quota data */} That's the whole meter: pay when supermemory processes, read for ~free, and delete for hygiene — not refunds. ## Where next - [Ingestion best practices](/patterns/ingestion) — the patterns that make ingestion cheaper *and* produce better memories - [Errors and limits](/errors-and-limits) — rate limits, the 429 shape, and backoff - [User profiles](/concepts/user-profiles) — what that ~1k-token budget buys you - [Security](/trust/security) — scoped keys, deletion mechanics, and compliance