From e59505bf25d5646edf8d30c8eb8434c300058d3b Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Mon, 24 Aug 2026 11:11:00 -0500 Subject: [PATCH 1/3] docs(credits): state what a credit is worth, and announce the unit change The credits page explained what is billed and how to check a balance but never said what a credit is worth, so an integer like 9244 had no meaning without asking someone. Adds that (1 credit = $0.01) and a note on the planned move to micro-dollars: what changes for a consumer (every figure is multiplied by 10,000), what does not (dollar value, prices, field names), and the practical advice to format balances as currency rather than printing the integer, since a raw count is only readable while a credit happens to be worth a cent. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_017fSvwazBitPfsTQvVqpi8q --- credits.mdx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/credits.mdx b/credits.mdx index b2b366c..2d6a8bb 100644 --- a/credits.mdx +++ b/credits.mdx @@ -21,6 +21,24 @@ Failed calls (4xx / 5xx) do **not** deduct credits. Deduction happens only after --- +## What a credit is worth + +**1 credit = $0.01.** Credit amounts returned by the API are integers, so a `remaining_credits` of `9244` is $92.44. + +Endpoint pricing is quoted in credits throughout these docs. Where an endpoint passes a provider's cost through — [music generation](/api-reference/music/generate) is the clearest case — the credit figure is that cost, not a marked-up one. + + +**A change to this unit is planned.** A credit will become **$0.000001** — a micro-dollar, six decimal places — so that per-call pricing can match provider pricing exactly rather than rounding to the nearest cent. At the current unit the smallest chargeable amount is a cent, which for a provider billing $0.002 per second means one credit buys five seconds and anything cheaper cannot be priced honestly. + +**What changes:** every credit figure the API returns is multiplied by 10,000. A $92.44 balance reads `9244` today and `92,440,000` afterwards. + +**What does not change:** the dollar value of your balance, what anything costs, and every field name in every response. + +If you display credit counts to your own users, format them as currency rather than printing the integer — a raw count is only readable while a credit happens to be worth a cent. Divide by the unit above. + + +--- + ## Check your balance ```bash From 7a981e88784a9b0aece30745ef65a16753a4e0ba Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Wed, 26 Aug 2026 20:39:27 -0500 Subject: [PATCH 2/3] docs(credits): balances and prices are US dollars; the ledger unit is integer micro-dollars Replaces the 'planned change' note with the unit as it will be after the rescale (recoupable/app#2000): 1,000,000 = $1.00, the same 6-decimal unit as USDC. Balance and 402 examples are in that unit, endpoint prices are quoted in USD, and the top-up openapi descriptions say the same. Dollar signs are escaped so MDX does not read them as inline math. --- api-reference/openapi/accounts.json | 4 +-- credits.mdx | 44 +++++++++++------------------ 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/api-reference/openapi/accounts.json b/api-reference/openapi/accounts.json index 6c15fd7..ab6a14b 100644 --- a/api-reference/openapi/accounts.json +++ b/api-reference/openapi/accounts.json @@ -1097,7 +1097,7 @@ }, "/api/credits/sessions": { "post": { - "description": "Top up credits on the authenticated account.\n\n**One credit equals one US cent (\\$0.01).** The customer is charged `credits` plus a Stripe processing fee (US card pricing: 2.9% + \\$0.30) \u2014 e.g. `credits: 10000` charges \\$103.30 total (\\$100.00 credits + \\$3.30 fee).\n\n**Two outcomes, distinguished by response shape:**\n\n- **Auto-charged** \u2014 if the account has a card on file (from a prior subscription or top-up), the card is charged immediately and the response is `{ paymentIntentId, creditsPurchased, totalCents }`. Credits land in the account's balance asynchronously via Stripe webhook (typically within seconds). No human interaction required.\n\n- **Checkout required** \u2014 if no card is on file, or the saved card requires 3-D Secure authentication, the response is `{ id, url }` with a hosted Stripe Checkout URL. Redirect to that URL; credits land on successful payment.\n\nClients should discriminate on the presence of `url` (Checkout) vs `paymentIntentId` (auto-charged). Cards entered through the Checkout fallback are saved for future top-ups, so a customer's second top-up typically auto-charges.", + "description": "Top up credits on the authenticated account.\n\n**Credits are integer micro-dollars (1,000,000 = \\$1.00, the same 6-decimal unit as USDC).** The customer is charged the USD value of `credits` plus a Stripe processing fee (US card pricing: 2.9% + \\$0.30) \u2014 e.g. `credits: 100000000` charges \\$103.30 total (\\$100.00 credits + \\$3.30 fee).\n\n**Two outcomes, distinguished by response shape:**\n\n- **Auto-charged** \u2014 if the account has a card on file (from a prior subscription or top-up), the card is charged immediately and the response is `{ paymentIntentId, creditsPurchased, totalCents }`. Credits land in the account's balance asynchronously via Stripe webhook (typically within seconds). No human interaction required.\n\n- **Checkout required** \u2014 if no card is on file, or the saved card requires 3-D Secure authentication, the response is `{ id, url }` with a hosted Stripe Checkout URL. Redirect to that URL; credits land on successful payment.\n\nClients should discriminate on the presence of `url` (Checkout) vs `paymentIntentId` (auto-charged). Cards entered through the Checkout fallback are saved for future top-ups, so a customer's second top-up typically auto-charges.", "security": [ { "apiKeyAuth": [] @@ -4643,7 +4643,7 @@ "credits": { "type": "integer", "minimum": 1, - "description": "The number of credits to purchase. One credit equals one US cent (\\$0.01), so the value of the credits in USD is `credits / 100`. Example: `250` is \\$2.50 worth of credits (the customer is also charged a Stripe processing fee on top).", + "description": "The number of credits to purchase, in integer micro-dollars (1,000,000 = \\$1.00), so the value in USD is `credits / 1000000`. Example: `2500000` is \\$2.50 worth of credits (the customer is also charged a Stripe processing fee on top).", "example": 250 }, "accountId": { diff --git a/credits.mdx b/credits.mdx index 2d6a8bb..75694a5 100644 --- a/credits.mdx +++ b/credits.mdx @@ -14,7 +14,7 @@ Some Recoup endpoints are billed in **credits** — primarily endpoints that hit | **Research** ([`/api/research/*`](/api-reference/research/search)) | Yes | Each successful call deducts credits. Costs vary by endpoint and parameters (e.g. [`enrich`](/api-reference/research/enrich) charges by processor tier; [`extract`](/api-reference/research/extract) charges by URL count). | | **Content generation** ([`/api/image/generate`](/api-reference/image/generation)) | Yes | Image generation is priced per call. | | **AI Chat — streaming** ([`POST /api/chat`](/api-reference/chat/workflow)) | Yes | Variable cost based on model token usage, with a per-request minimum. | -| **Social scrape** ([`/api/socials/{id}/scrape`](/api-reference/social/scrape), [`/api/artist/socials/scrape`](/api-reference/artist/socials-scrape)) | Yes | 5 credits, plus 1 credit per post requested via `posts` — per social profile scraped. | +| **Social scrape** ([`/api/socials/{id}/scrape`](/api-reference/social/scrape), [`/api/artist/socials/scrape`](/api-reference/artist/socials-scrape)) | Yes | \$0.05, plus \$0.01 per post requested via `posts` — per social profile scraped. | | **Everything else** | Free at the API layer | [Artist CRUD](/api-reference/artists/list), [sandboxes](/api-reference/sandboxes/list), [sessions](/api-reference/sessions/get), [scheduled tasks](/api-reference/tasks/get), [account/org management](/api-reference/accounts/id), [agent signup](/api-reference/agents/signup), [Spotify proxies](/api-reference/spotify/search), etc. Subscription gating may still apply. | Failed calls (4xx / 5xx) do **not** deduct credits. Deduction happens only after the upstream call succeeds. @@ -23,19 +23,7 @@ Failed calls (4xx / 5xx) do **not** deduct credits. Deduction happens only after ## What a credit is worth -**1 credit = $0.01.** Credit amounts returned by the API are integers, so a `remaining_credits` of `9244` is $92.44. - -Endpoint pricing is quoted in credits throughout these docs. Where an endpoint passes a provider's cost through — [music generation](/api-reference/music/generate) is the clearest case — the credit figure is that cost, not a marked-up one. - - -**A change to this unit is planned.** A credit will become **$0.000001** — a micro-dollar, six decimal places — so that per-call pricing can match provider pricing exactly rather than rounding to the nearest cent. At the current unit the smallest chargeable amount is a cent, which for a provider billing $0.002 per second means one credit buys five seconds and anything cheaper cannot be priced honestly. - -**What changes:** every credit figure the API returns is multiplied by 10,000. A $92.44 balance reads `9244` today and `92,440,000` afterwards. - -**What does not change:** the dollar value of your balance, what anything costs, and every field name in every response. - -If you display credit counts to your own users, format them as currency rather than printing the integer — a raw count is only readable while a credit happens to be worth a cent. Divide by the unit above. - +**Balances and prices are US dollars.** The ledger stores amounts as integer micro-dollars, the same 6-decimal unit as USDC: `1,000,000 = \$1.00`, so it can carry sub-cent charges (a \$0.002/s provider rate prices exactly). Every credit field the API returns is that integer; divide by 1,000,000 to display it as currency. Example: [`GET /api/accounts/{id}/credits`](/api-reference/accounts/credits-get). --- @@ -51,9 +39,9 @@ Response shape: ```json { "account_id": "acc_…", - "remaining_credits": 9244, - "total_credits": 9999, - "used_credits": 755, + "remaining_credits": 92440000, + "total_credits": 99990000, + "used_credits": 7550000, "is_pro": true, "timestamp": "2026-04-24T17:50:43.475" } @@ -67,7 +55,7 @@ Response shape: Recoup has two tiers. Both refill on a monthly cycle. -| Tier | How you get it | Monthly credits | +| Tier | How you get it | Monthly allowance | |------|---------------|----------------| | **Free** | Default for every new account | Monthly allowance refills automatically | | **Pro** | Stripe subscription via the chat dashboard | Substantially higher monthly allowance | @@ -104,7 +92,7 @@ You can purchase credits any time via [`POST /api/credits/sessions`](/api-refere curl -sS -X POST https://api.recoupable.dev/api/credits/sessions \ -H "x-api-key: $RECOUP_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"credits": 100, "successUrl": "https://chat.recoupable.dev/credits/success"}' + -d '{"credits": 1000000, "successUrl": "https://chat.recoupable.dev/credits/success"}' ``` Full request/response schema at [Create Credits Top-Up Session](/api-reference/credits/sessions-create). @@ -157,8 +145,8 @@ When the gate comes up short, billed endpoints return **HTTP 402** with a unifie ```json { "error": "insufficient_credits", - "remaining_credits": 12, - "required_credits": 100, + "remaining_credits": 120000, + "required_credits": 1000000, "billingUrl": "https://app.recoupable.dev" } ``` @@ -185,11 +173,11 @@ Current as of this revision of the page. The authoritative source is the per-end | Endpoint | Cost | |----------|------| -| [`POST /api/chat`](/api-reference/chat/workflow) (streaming) | ≥1 credit per turn — variable based on model token usage | -| [`GET /api/research/*`](/api-reference/research/search) (artist & non-artist research) | 5 credits per call | -| [`POST /api/research/people`](/api-reference/research/people) | 5 credits per call | -| [`POST /api/research/web`](/api-reference/research/web) | 1 credit per call | -| [`POST /api/research/extract`](/api-reference/research/extract) | 5 credits × number of URLs | -| [`POST /api/research/enrich`](/api-reference/research/enrich) | 5 / 10 / 25 credits (base / core / ultra processor) | -| [`POST /api/research/deep`](/api-reference/research/deep) | 25 credits per call | +| [`POST /api/chat`](/api-reference/chat/workflow) (streaming) | Variable, priced from the model's token usage; see `required_credits` on a 402 | +| [`GET /api/research/*`](/api-reference/research/search) (artist & non-artist research) | \$0.05 per call | +| [`POST /api/research/people`](/api-reference/research/people) | \$0.05 per call | +| [`POST /api/research/web`](/api-reference/research/web) | \$0.01 per call | +| [`POST /api/research/extract`](/api-reference/research/extract) | \$0.05 × number of URLs | +| [`POST /api/research/enrich`](/api-reference/research/enrich) | \$0.05 / \$0.10 / \$0.25 (base / core / ultra processor) | +| [`POST /api/research/deep`](/api-reference/research/deep) | \$0.25 per call | | [`POST /api/image/generate`](/api-reference/image/generation) | Per-call price; see endpoint reference | From ea8205b97451d84b8c41ea4013e525e5ba63d573 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Wed, 26 Aug 2026 20:39:45 -0500 Subject: [PATCH 3/3] docs(credits): plain dollar inside the code span (escapes render literally there) --- credits.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/credits.mdx b/credits.mdx index 75694a5..862683f 100644 --- a/credits.mdx +++ b/credits.mdx @@ -23,7 +23,7 @@ Failed calls (4xx / 5xx) do **not** deduct credits. Deduction happens only after ## What a credit is worth -**Balances and prices are US dollars.** The ledger stores amounts as integer micro-dollars, the same 6-decimal unit as USDC: `1,000,000 = \$1.00`, so it can carry sub-cent charges (a \$0.002/s provider rate prices exactly). Every credit field the API returns is that integer; divide by 1,000,000 to display it as currency. Example: [`GET /api/accounts/{id}/credits`](/api-reference/accounts/credits-get). +**Balances and prices are US dollars.** The ledger stores amounts as integer micro-dollars, the same 6-decimal unit as USDC: `1,000,000 = $1.00`, so it can carry sub-cent charges (a \$0.002/s provider rate prices exactly). Every credit field the API returns is that integer; divide by 1,000,000 to display it as currency. Example: [`GET /api/accounts/{id}/credits`](/api-reference/accounts/credits-get). ---