// for developers

Ripceipt API.
Drop-in for your stack.

One REST endpoint, AI vision under the hood, and predictable JSON on the way out. Typed SDKs for JS, Python, and Go. Signed webhooks. URI versioning so the schema stays put.

SDKs
JS · Python · Go
Versioning
/v1 stable
Pricing
From $5/mo
POST /v1/workspaces/:id/receipts
curl -X POST https://api.ripceipt.com/v1/receipts/upload \
  -H "Authorization: Bearer key_live_…" \
  -F "file=@receipt.jpg"
Returns predictable JSON200 OK

The kit

Everything you'd expect.
Nothing you wouldn't.

AI extraction in one POST.

Send a file, a URL, or a base64 blob. Vision models read the receipt, return structured fields, and tag every value with a self-reported confidence score so your downstream code knows what to trust.

// in your code
await receipts.create({
workspaceId: "ws_abc",
file,
retention: "delete_file",
});

Typed SDKs

Generated from the OpenAPI spec. Idiomatic per language. Auto-completion in every modern editor.

JSPYGO

Signed webhooks

HMAC-SHA256 with timestamp. Stripe-style verification. Replay protection built in. Retried with exponential backoff.

X-Receipts-Signature: v1=…

URI versioning

Versioned at /v1 from day one. We add fields and never break them. Breaking changes get /v2 and twelve months of notice.

/v1stable

Predictable JSON

Stable field order. ISO 8601 timestamps. Three-letter ISO 4217 currency. Confidence on every value.

Idiomatic errors

Typed error classes per language. Helpful messages. RFC 7807-style problem details on every 4xx and 5xx.

Quick start

Four steps from signup
to first receipt.

  1. 01

    Sign up and grab a key

    Create a workspace, then mint an API key from the dashboard. Keys are scoped to a workspace and can be rotated anytime.

    bashstep 01
    # Stored as env var
    export RIPCEIPT_KEY="key_live_…"
  2. 02

    Install the SDK

    Pick your language. Each SDK is generated from the same OpenAPI spec, so the shape of every method matches the REST endpoint exactly.

    bashstep 02
    npm install @ripceipt/sdk
    # or
    pip install ripceipt
    # or
    go get github.com/ripceipt-dev/ripceipt-go
  3. 03

    POST your first receipt

    A file, a URL, or a base64 string. The response is the structured receipt: line items, tax, payment, merchant, language, summary, and confidence.

    tsstep 03
    const receipt = await client.receipts.create({
      workspaceId: "ws_abc",
      file: fs.createReadStream("./receipt.jpg"),
    });
    
    console.log(receipt.total);   // 27.13
    console.log(receipt.items);   // [{ name, variant, … }]
  4. 04

    Listen for the webhook

    For async flows, register a webhook URL and verify the HMAC signature on each delivery. Retries with exponential backoff. Replay-safe via timestamps.

    tsstep 04
    // /webhooks/receipts
    import { verifyReceiptSignature } from "@ripceipt/sdk";
    
    export async function POST(req) {
      if (!verifyReceiptSignature(req)) {
        return new Response("bad sig", { status: 401 });
      }
      const { receipt } = await req.json();
      await db.receipts.insert(receipt);
      return new Response("ok");
    }

The schema

The receipt object,
in full.

One object, the same shape on every endpoint and every webhook. Add fields are backward-compatible additions only. Breaking changes get a new version.

Fieldsreceipt.v1
  • id

    string · prefixed (rcpt_…)

  • status

    enum · processing | completed | failed

  • language

    string · ISO 639-1 (e.g. en-US)

  • currency

    string · ISO 4217 (e.g. USD)

  • merchant

    object · name, address, phone

  • payment

    object · method, brand, last4

  • items

    array · name, variant, qty, price, tax_rate, confidence

  • subtotal · tax · total

    number · decimals from currency

  • summary

    string · plain-English paragraph

  • confidence

    integer · 1 to 99 (overall)

Sample response200 OK
{
  "id": "rcpt_2yK3pQ",
  "status": "completed",
  "language": "en-US",
  "currency": "USD",
  "merchant": {
    "name": "Brew & Butter",
    "address": "128 Palm St"
  },
  "payment": {
    "method": "card",
    "brand": "visa",
    "last4": "4242"
  },
  "items": [
    {
      "id": "item_01",
      "name": "Oat milk latte",
      "variant": "Large",
      "category": "Drinks",
      "quantity": 1,
      "price": 5.50,
      "tax_rate": 0.085,
      "confidence": 96
    }
  ],
  "subtotal": 25.00,
  "tax": 2.13,
  "total": 27.13,
  "summary": "Five drinks and pastries from a coffee shop, paid by card.",
  "confidence": 94
}

Webhooks

Async by default,
signed by HMAC.

Fire-and-forget the upload, listen for the result. Stripe-style signatures, timestamps for replay protection, automatic retries with exponential backoff, and a delivery log for debugging.

  1. Step 01
    POST /receipts
    Your code or dashboard
  2. Step 02
    AI extraction
    Vision model reads it
  3. Step 03
    Webhook fires
    HMAC-signed POST
  4. Step 04
    Your handler
    Verify & store
Verifying the signature (Node.js)HMAC-SHA256 · v1
// Verify the HMAC signature on every delivery
import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyReceiptSignature(req: Request, secret: string) {
  const sig = req.headers.get("x-receipts-signature") ?? "";
  const ts  = req.headers.get("x-receipts-timestamp") ?? "";

  // Reject anything older than 5 minutes (replay protection)
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const body = await req.text();
  const expected = createHmac("sha256", secret)
    .update(`${ts}.${body}`)
    .digest("hex");

  return timingSafeEqual(
    Buffer.from(sig.replace("v1=", "")),
    Buffer.from(expected),
  );
}

Launch pricing

Plans that scale
with how much you extract.

Per-receipt cost drops as you scale, and a hard cap means you'll never wake up to a surprise bill.

Scale

$0/month
Receipts
10,000
Per receipt
Most popular

Starter

$5/month
Receipts
100
Per receipt
$0.05

Growth

$25/month
Receipts
1,000
Per receipt
$0.025
  • REST API and signed webhooks
  • CSV, JSON, and XML export
  • All retention modes
  • Hard caps, no surprise bills
Compare every tier

FAQ

The questions
we hear from devs.

Sync or async?
Both. The API can return the structured data on the same response when extraction completes quickly, or you can fire-and-forget and listen for the signed webhook. Pick whichever fits your stack — the JSON shape is identical.
How do you handle retries?
Webhooks retry with exponential backoff on any non-2xx response. Each delivery includes a delivery id you can use to dedupe. Failed deliveries surface in the dashboard's delivery log with the response body for debugging.
Are there rate limits?
Yes, per workspace, scaled to your plan tier. The API returns 429 with a Retry-After header when you exceed them. Your dashboard shows current usage in real time. Hard plan caps return 402 instead.
How big can files be?
Single images up to typical phone-photo sizes. PDFs scale by page count. Multi-page documents queue and complete asynchronously via webhook. Hard limits and exact sizes live in the API docs because they evolve.
How do I test in development?
Live and test API keys are separate. Test keys use the same endpoints with sample receipts and don't count against your plan. Webhook signatures use a separate test secret so you can verify locally without rotating prod credentials.
What model is under the hood?
Modern vision-language models. We don't publish the specific provider because the model is a configurable component — what stays stable is the schema and the API surface. Upgrades roll out behind feature flags so accuracy improves without shape changes.
Do you have OpenAPI / SDKs?
Yes. The OpenAPI 3.1 spec is published at api.ripceipt.com/openapi.json. Our typed SDKs for JS/TS, Python, and Go are generated from it, so the method shapes match the REST endpoints exactly.
How is the schema versioned?
URI versioning at /v1. We add fields as backward-compatible additions only — no field renames, no type changes. Breaking changes get a new /v2 with at least twelve months of notice and an overlap period.
Does it work as a tool for AI agents?
Yes — it's designed for it. The single-POST endpoint maps cleanly to a function-calling tool: drop the OpenAPI schema into Claude Code, the Anthropic Agent SDK, MoltBot pipelines, OpenAI tool-calls, or LangChain. Confidence scores per field give the agent something to branch on. See /for/agents for the full pattern.

// ready when you are

Mint a key.
Make the call.

Five dollars a month gets you fifty receipts, the full API, signed webhooks, all three retention modes, and a hard cap so you never wake up to a surprise bill.