{
  "openapi": "3.1.0",
  "info": {
    "title": "ParseRail",
    "version": "1.0.0",
    "description": "**ParseRail provides the AI back-end for your product.**\n\nParse a document, extract fields, redact PII, analyze a contract, fight a chargeback, enrich a company — 39 production AI endpoints, the same capabilities behind the software we run in production. **One key, one wallet, one bill.** Pay only for the calls you make; failed calls are never charged.\n\nSign in, top up your wallet, and call any endpoint. Every panel is live: drop in your key and run it from the browser.\n\nSee **Quickstart** to make your first call, **SDKs & MCP** for the TypeScript / Python clients and the MCP server, or **Pricing & credits** for the full rate card. Task-first guides with copyable snippets live at [api.thecompound.tech/docs](https://api.thecompound.tech/docs).",
    "contact": {
      "name": "Compound Labs",
      "url": "https://thecompound.tech"
    }
  },
  "servers": [
    {
      "url": "https://api.thecompound.tech"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Quickstart",
      "description": "Sign up at [the dashboard](https://api.thecompound.tech/dashboard), mint a key, buy credits, and call any endpoint. There is no free tier — a call is refused until the wallet has a balance.\n\n```bash\ncurl https://api.thecompound.tech/v1/parse \\\n  -H \"Authorization: Bearer ksk_live_…\" \\\n  -d '{ \"fileUrl\": \"https://…/invoice.pdf\" }'\n```\n\nEvery successful response returns its result plus `usage: { credits, balanceRemaining }`. A failed call is never charged.\n\n**Dry run before you buy.** Add `-H \"ParseRail-Dry-Run: 1\"` to any call. ParseRail checks the key, the rate limit, the body and the balance. It returns 200 with `wouldCharge`, `balance` and `liveStatus`. No model runs and nothing is charged, so a new key with a zero balance works."
    },
    {
      "name": "Authentication",
      "description": "Every request authenticates with a bearer API key (`ksk_live_…`). Mint and revoke keys in the [dashboard](https://api.thecompound.tech/dashboard); the secret is shown once.\n\n```\nAuthorization: Bearer ksk_live_…\n```\n\nKeep keys server-side, store them in an env var (e.g. `PARSERAIL_API_KEY`), and revoke any time."
    },
    {
      "name": "SDKs & MCP",
      "description": "Call ParseRail from TypeScript, Python, or any MCP client.\n\n```bash\nnpm i parserail-api      # TypeScript / JavaScript\npip install parserail     # Python\nnpx -y parserail-mcp    # MCP server — native tools for Claude, Cursor, any MCP client\n```\n\n```ts\nimport { ParseRailCore } from \"parserail-api\";\nconst parserail = new ParseRailCore({ apiKey: process.env.PARSERAIL_API_KEY! });\nconst doc = await parserail.parse({ fileUrl });\nconsole.log(doc.totalAmount, doc.usage.balanceRemaining);\n```"
    },
    {
      "name": "Pricing & credits",
      "description": "Credits, not seats — **1 credit = $0.01**. Every endpoint burns at its own rate, you're only charged on success, and credits never expire.\n\n**No free tier** — an account starts at a zero balance and every call is refused with `402 insufficient_credits` until credits are bought. A dry run (`ParseRail-Dry-Run: 1`) works at a zero balance: it validates the call and quotes its cost without running a model. Nothing tops a wallet up automatically; credits arrive only from a pack, a plan, or auto-recharge.\n\n**Monthly plans** — a fresh bundle lands every billing period, at 1¢ a credit.\n\n- **Developer — $19/mo** — You get 1,900 credits every month at 1¢ a credit.\n- **Team — $25/mo** — You get 2,500 credits every month at 1¢ a credit. You can cap what each API key spends in a month.\n\n**Credit packs** — one-time top-ups for overflow.\n\n- **First pack — $5, one per account**: 500 credits\n- **Starter — $20**: 2,000 credits\n- **Growth — $100 (+5% bonus)**: 10,500 credits\n- **Scale — $500 (+10% bonus)**: 55,000 credits\n\n| Endpoint | Capability | Cost |\n| --- | --- | --- |\n| `POST /v1/parse` | Document parse | **$0.10/document** (10 cr) |\n| `POST /v1/extract` | Field extraction | **$0.04/call** (4 cr) |\n| `POST /v1/classify` | Classification | **$0.02/call** (2 cr) |\n| `POST /v1/summarize` | Summarize | **$0.03/call** (3 cr) |\n| `POST /v1/redact` | PII redaction | **$0.03/call** (3 cr) |\n| `POST /v1/sentiment` | Sentiment | **$0.02/call** (2 cr) |\n| `POST /v1/contract` | Contract analysis | **$0.12/contract** (12 cr) |\n| `POST /v1/chargeback` | Chargeback representment | **$0.15/dispute** (15 cr) |\n| `POST /v1/enrich` | Company enrichment | **$0.05/lookup** (5 cr) |\n| `POST /v1/invoice` | Invoice extraction | **$0.08/invoice** (8 cr) |\n| `POST /v1/receipt` | Receipt extraction | **$0.06/receipt** (6 cr) |\n| `POST /v1/statement` | Statement parsing | **$0.12/statement** (12 cr) |\n| `POST /v1/resume` | Resume parsing | **$0.08/resume** (8 cr) |\n| `POST /v1/tables` | Table extraction | **$0.08/document** (8 cr) |\n| `POST /v1/split` | Document splitting | **$0.10/bundle** (10 cr) |\n| `POST /v1/compare` | Document comparison | **$0.15/comparison** (15 cr) |\n| `POST /v1/structure` | Schema structuring | **$0.06/call** (6 cr) |\n| `POST /v1/normalize` | Record normalization | **$0.05/batch** (5 cr) |\n| `POST /v1/match` | Entity matching | **$0.08/run** (8 cr) |\n| `POST /v1/categorize` | Batch categorization | **$0.03/batch** (3 cr) |\n| `POST /v1/dunning` | Collections sequence | **$0.08/sequence** (8 cr) |\n| `POST /v1/po-match` | 3-way match | **$0.10/match** (10 cr) |\n| `POST /v1/quote` | Quote builder | **$0.08/quote** (8 cr) |\n| `POST /v1/fraud-flag` | Fraud triage | **$0.06/check** (6 cr) |\n| `POST /v1/reply` | Reply drafting | **$0.05/reply** (5 cr) |\n| `POST /v1/triage` | Ticket triage | **$0.03/ticket** (3 cr) |\n| `POST /v1/minutes` | Meeting minutes | **$0.06/transcript** (6 cr) |\n| `POST /v1/outreach` | Outreach sequence | **$0.06/sequence** (6 cr) |\n| `POST /v1/review-reply` | Review response | **$0.03/review** (3 cr) |\n| `POST /v1/moderate` | Content moderation | **$0.02/item** (2 cr) |\n| `POST /v1/rewrite` | Brand-voice rewrite | **$0.03/call** (3 cr) |\n| `POST /v1/product-copy` | Product copy | **$0.05/product** (5 cr) |\n| `POST /v1/describe` | Image description | **$0.03/image** (3 cr) |\n| `POST /v1/research` | Research brief | **$0.50/brief** (50 cr) |\n| `POST /v1/screen` | Lead screening | **$0.10/lead** (10 cr) |\n| `POST /v1/transcribe` | Transcription | **$0.10/recording** (10 cr) |\n| `POST /v1/memory` | Agent memory | **$0.02/operation** (2 cr) |\n| `POST /v1/image` | Image generation | **$0.10/image** (10 cr) |\n| `POST /v1/speak` | Text to speech | **$0.05/clip** (5 cr) |"
    },
    {
      "name": "Async & webhooks",
      "description": "A hundred-page contract doesn't fit in a request/response cycle. The The endpoints are `/v1/parse`, `/v1/contract`, `/v1/invoice`, `/v1/receipt`, `/v1/statement`, `/v1/resume`, `/v1/tables`, `/v1/split`, and `/v1/compare`. endpoints accept `async: true` and hand you a job instead of a result.\n\n```bash\ncurl https://api.thecompound.tech/v1/parse \\\n  -H \"Authorization: Bearer ksk_live_…\" \\\n  -d '{ \"fileUrl\": \"https://…/contract.pdf\", \"async\": true }'\n# 202 { \"jobId\": \"6f1d2c8e-…\", \"status\": \"queued\", \"requestId\": \"req_8c2a1f\" }\n```\n\n**Poll it**, or skip polling with a `callbackUrl`:\n\n```bash\ncurl https://api.thecompound.tech/v1/jobs/6f1d2c8e-… \\\n  -H \"Authorization: Bearer ksk_live_…\"\n# { \"status\": \"succeeded\", \"result\": { …, \"usage\": { … } } }\n```\n\nStatus is one of `queued`, `running`, `succeeded`, `failed`. The last two are terminal.\n\n**Billing is unchanged.** A job is charged when it succeeds, never on enqueue and never when it fails — so a job you see as `failed` cost you nothing.\n\n### Webhooks\n\nPass `callbackUrl` (a public https URL) and we POST the finished job to it:\n\n| Header | Value |\n| --- | --- |\n| `X-Compound-Event` | `job.completed` or `job.failed` — mirrors the terminal status |\n| `X-Compound-Job-Id` | the job's id |\n| `X-Compound-Request-Id` | the originating request id |\n| `X-Compound-Signature` | `sha256=<hex>` |\n\nThe signature is `HMAC-SHA256` over the **raw request body**, keyed with your account's webhook signing secret — find it on the [Webhooks page](https://api.thecompound.tech/dashboard/webhooks). It is yours alone; a signature that verifies could only have come from us.\n\n```ts\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\n\nfunction verify(rawBody: string, header: string, secret: string) {\n  const expected = createHmac(\"sha256\", secret).update(rawBody).digest(\"hex\");\n  const got = header.replace(/^sha256=/, \"\");\n  return got.length === expected.length &&\n    timingSafeEqual(Buffer.from(got), Buffer.from(expected));\n}\n```\n\nVerify before you trust the body, and compare in constant time.\n\n### What we guarantee\n\nA 202 commits the input and a credit reservation. Queued work survives a runner restart. If a claimed worker dies, the next configured maintenance pass fails its expired lease without billing or blindly repeating an uncertain model call. Maintenance runs every five minutes when its cron and secret are configured. Send an Idempotency-Key to replay the same result without another charge for 24 hours; changed bodies with that key return 409. Async input, including file bytes, is service-only and removed on completion or its 24-hour deadline.\n\nCallback attempts are signed and recorded. Non-2xx responses retry up to five times with backoff; no signing key means nothing is sent. Receivers must deduplicate the signed body deliveryId after connection loss; X-Compound-Delivery-Id echoes the same value. **Polling is the source of truth**. Redirects are not followed, and a callbackUrl that resolves to a private address is refused."
    },
    {
      "name": "Document parse",
      "description": "ParseRail converts any invoice, receipt, EOB, ERA, or COI, as a PDF or image, into structured, validated JSON."
    },
    {
      "name": "Field extraction",
      "description": "ParseRail extracts a field set you define from any block of text and returns typed values with confidence."
    },
    {
      "name": "Classification",
      "description": "ParseRail routes or tags text against your taxonomy and returns a label, a confidence value, and a one-line rationale."
    },
    {
      "name": "Summarize",
      "description": "ParseRail converts a meeting transcript, thread, or report into a tight summary, key points, and extracted action items."
    },
    {
      "name": "PII redaction",
      "description": "ParseRail detects and strips names, emails, phones, SSNs, cards, and PHI from text before you store or log it."
    },
    {
      "name": "Sentiment",
      "description": "ParseRail converts a review or support message into a sentiment score, a per-aspect breakdown, and the themes driving it."
    },
    {
      "name": "Contract analysis",
      "description": "ParseRail converts a contract into the parties, effective date, term, renewal, governing law, obligations, and flagged risk clauses."
    },
    {
      "name": "Chargeback representment",
      "description": "ParseRail converts dispute details into a representment narrative, an evidence checklist, the right reason code, and a win-likelihood."
    },
    {
      "name": "Company enrichment",
      "description": "ParseRail converts a domain or work email into a structured company profile with the name, description, industry, HQ, size, and links."
    },
    {
      "name": "Invoice extraction",
      "description": "ParseRail converts an invoice, whether PDF, photo, or text, into the vendor, dates, PO refs, tax, totals, and clean line items."
    },
    {
      "name": "Receipt extraction",
      "description": "ParseRail converts a receipt into the merchant, items, totals, payment method, and an expense category for expense flows."
    },
    {
      "name": "Statement parsing",
      "description": "ParseRail converts a bank or card statement into the account, period, balances, and every transaction as a normalized row."
    },
    {
      "name": "Resume parsing",
      "description": "ParseRail converts a resume or CV into a structured candidate profile with contact, skills, experience, education, and links."
    },
    {
      "name": "Table extraction",
      "description": "ParseRail extracts every table in a document, including scanned tables, as clean headers and rows for your spreadsheet or DB."
    },
    {
      "name": "Document splitting",
      "description": "ParseRail classifies and splits a multi-document scan bundle, identifying each document, its start and end, and its summary."
    },
    {
      "name": "Document comparison",
      "description": "ParseRail compares two versions of a contract or document and returns every material change, what it means, and the risk it carries."
    },
    {
      "name": "Schema structuring",
      "description": "ParseRail takes any messy input, including text, HTML, or an email, plus YOUR JSON schema, and returns output shaped to it. It validates the output against your required fields and property types, performs an automatic corrective retry, and returns a `valid` flag."
    },
    {
      "name": "Record normalization",
      "description": "ParseRail converts a batch of messy records into clean canonical rows and returns a change log of every fix, including casing, formats, and dedup-ready values."
    },
    {
      "name": "Entity matching",
      "description": "ParseRail compares two record sets and identifies rows that refer to the same real-world thing. It handles fuzzy names, typos, and aliases, and returns confidence and reasoning."
    },
    {
      "name": "Batch categorization",
      "description": "ParseRail categorizes up to a hundred products, transactions, or tickets against your taxonomy in one call. Each item includes a confidence."
    },
    {
      "name": "Collections sequence",
      "description": "ParseRail turns an overdue invoice into a ready-to-send collection sequence. The sequence escalates its pace and tone according to how late the invoice is."
    },
    {
      "name": "3-way match",
      "description": "ParseRail compares an invoice, purchase order, and receipt. It marks the documents as matched, partial, or mismatched, and flags and sizes every discrepancy."
    },
    {
      "name": "Quote builder",
      "description": "ParseRail turns a job description and your rates into an itemized quote. The quote includes professional wording, assumptions, and scope notes."
    },
    {
      "name": "Fraud triage",
      "description": "ParseRail evaluates an order or transaction in context and returns a risk score. It lists the signals driving the score and the checks worth running before you ship."
    },
    {
      "name": "Reply drafting",
      "description": "ParseRail turns a customer thread and your context into a ready-to-send reply. The reply uses the requested tone and includes an internal note for the agent."
    },
    {
      "name": "Ticket triage",
      "description": "ParseRail evaluates a support ticket and returns its priority, category, assigned team, sentiment, SLA risk, and a suggested first response."
    },
    {
      "name": "Meeting minutes",
      "description": "ParseRail turns a meeting transcript into clean minutes. The minutes include a summary, decisions made, action items with owners, and open questions."
    },
    {
      "name": "Outreach sequence",
      "description": "ParseRail turns an enriched lead and what you sell into a personalized outreach sequence. The sequence references what actually makes the lead a fit."
    },
    {
      "name": "Review response",
      "description": "ParseRail evaluates a customer review and returns a brand-safe public response, the issues to log, and whether human escalation is needed."
    },
    {
      "name": "Content moderation",
      "description": "ParseRail evaluates text or an image against YOUR policy and returns allow, review, or block with the categories and excerpts that drove the call."
    },
    {
      "name": "Brand-voice rewrite",
      "description": "ParseRail rewrites any copy in your brand voice. You describe the voice or paste a sample, and ParseRail returns the rewrite and what changed."
    },
    {
      "name": "Product copy",
      "description": "ParseRail turns specs and an audience into listing-ready titles, bullets, a description, and SEO keywords for each channel."
    },
    {
      "name": "Image description",
      "description": "ParseRail evaluates an image and returns accessible alt text, a caption, tags, and any text found inside it. One call supports accessibility and catalogs."
    },
    {
      "name": "Research brief",
      "description": "ParseRail researches a company or topic and returns a multi-source, citation-backed brief. The brief states what it is, what changed lately, and what matters. ParseRail performs the research on the web."
    },
    {
      "name": "Lead screening",
      "description": "ParseRail evaluates a lead against your ICP criteria and returns a web-grounded qualification verdict. The verdict includes evidence for and against."
    },
    {
      "name": "Transcription",
      "description": "ParseRail turns an audio recording into accurate text with speakers and paragraph timestamps. It supports meetings, calls, and voice notes."
    },
    {
      "name": "Agent memory",
      "description": "ParseRail stores, searches, and forgets memories for your agents in your own namespace. It provides semantic recall without a vector DB to run."
    },
    {
      "name": "Image generation",
      "description": "ParseRail turns a prompt into a production-ready image. It supports marketing visuals, product scenes, and consistent brand imagery."
    },
    {
      "name": "Text to speech",
      "description": "ParseRail turns text into natural speech audio ready to embed. It supports voice notes, IVR lines, and narration."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Guides",
      "tags": [
        "Quickstart",
        "Authentication",
        "SDKs & MCP",
        "Pricing & credits",
        "Async & webhooks"
      ]
    },
    {
      "name": "API Reference",
      "tags": [
        "Document parse",
        "Field extraction",
        "Classification",
        "Summarize",
        "PII redaction",
        "Sentiment",
        "Contract analysis",
        "Chargeback representment",
        "Company enrichment",
        "Invoice extraction",
        "Receipt extraction",
        "Statement parsing",
        "Resume parsing",
        "Table extraction",
        "Document splitting",
        "Document comparison",
        "Schema structuring",
        "Record normalization",
        "Entity matching",
        "Batch categorization",
        "Collections sequence",
        "3-way match",
        "Quote builder",
        "Fraud triage",
        "Reply drafting",
        "Ticket triage",
        "Meeting minutes",
        "Outreach sequence",
        "Review response",
        "Content moderation",
        "Brand-voice rewrite",
        "Product copy",
        "Image description",
        "Research brief",
        "Lead screening",
        "Transcription",
        "Agent memory",
        "Image generation",
        "Text to speech"
      ]
    }
  ],
  "paths": {
    "/v1/parse": {
      "post": {
        "operationId": "parse",
        "summary": "Document parse",
        "x-pricing": {
          "credits": 10,
          "usd": 0.1,
          "currency": "USD"
        },
        "description": "ParseRail converts any invoice, receipt, EOB, ERA, or COI, as a PDF or image, into structured, validated JSON.\n\nCost: 10 credits ($0.10) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Document parse"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "docType": {
                    "type": "string",
                    "maxLength": 64,
                    "description": "Optional hint, e.g. \"invoice\"."
                  },
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/invoice.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "docType",
                            "fields"
                          ],
                          "properties": {
                            "docType": {
                              "type": "string",
                              "description": "Provide the classified document type, e.g. \"invoice\"."
                            },
                            "party": {
                              "type": "string",
                              "description": "Primary party — vendor / payer / carrier."
                            },
                            "documentNumber": {
                              "type": "string"
                            },
                            "date": {
                              "type": "string",
                              "description": "Primary date, YYYY-MM-DD."
                            },
                            "totalAmount": {
                              "type": "number"
                            },
                            "lineItems": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "description",
                                  "amount"
                                ],
                                "properties": {
                                  "description": {
                                    "type": "string"
                                  },
                                  "amount": {
                                    "type": "number"
                                  }
                                }
                              }
                            },
                            "fields": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "label",
                                  "value",
                                  "confidence"
                                ],
                                "properties": {
                                  "label": {
                                    "type": "string"
                                  },
                                  "value": {
                                    "type": [
                                      "string",
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "description": "0–1."
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "docType": "invoice",
                  "party": "Acme Supplies Inc.",
                  "documentNumber": "INV-10428",
                  "date": "2026-06-30",
                  "totalAmount": 4820.5,
                  "lineItems": [
                    {
                      "description": "…",
                      "amount": 1200
                    }
                  ],
                  "fields": [
                    {
                      "label": "PO Number",
                      "value": "PO-88",
                      "confidence": 0.98
                    }
                  ],
                  "usage": {
                    "credits": 10,
                    "balanceRemaining": 1990
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/extract": {
      "post": {
        "operationId": "extract",
        "summary": "Field extraction",
        "x-pricing": {
          "credits": 4,
          "usd": 0.04,
          "currency": "USD"
        },
        "description": "ParseRail extracts a field set you define from any block of text and returns typed values with confidence.\n\nCost: 4 credits ($0.04) — charged only on success.",
        "tags": [
          "Field extraction"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "fields"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Provide the field names to pull out."
                  },
                  "instructions": {
                    "type": "string",
                    "description": "Optional extra guidance."
                  }
                }
              },
              "example": {
                "text": "Order 5561 ships Jul 8 to Denver, CO. Total $412.",
                "fields": [
                  "order number",
                  "ship date",
                  "destination",
                  "total"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "results"
                          ],
                          "properties": {
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "field",
                                  "value",
                                  "confidence"
                                ],
                                "properties": {
                                  "field": {
                                    "type": "string"
                                  },
                                  "value": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "description": "0–1."
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "results": [
                    {
                      "field": "order number",
                      "value": "5561",
                      "confidence": 0.99
                    },
                    {
                      "field": "ship date",
                      "value": "2026-07-08",
                      "confidence": 0.9
                    }
                  ],
                  "usage": {
                    "credits": 4,
                    "balanceRemaining": 1986
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/classify": {
      "post": {
        "operationId": "classify",
        "summary": "Classification",
        "x-pricing": {
          "credits": 2,
          "usd": 0.02,
          "currency": "USD"
        },
        "description": "ParseRail routes or tags text against your taxonomy and returns a label, a confidence value, and a one-line rationale.\n\nCost: 2 credits ($0.02) — charged only on success.",
        "tags": [
          "Classification"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "labels"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "labels": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 2,
                    "maxItems": 50
                  },
                  "multi": {
                    "type": "boolean",
                    "description": "Allow multiple labels.",
                    "default": false
                  },
                  "instructions": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "text": "My card was charged twice for one order.",
                "labels": [
                  "billing",
                  "shipping",
                  "technical",
                  "refund"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "label",
                            "confidence",
                            "rationale"
                          ],
                          "properties": {
                            "label": {
                              "type": "string"
                            },
                            "labels": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Provide all labels when multi is set."
                            },
                            "confidence": {
                              "type": "number",
                              "description": "0–1."
                            },
                            "rationale": {
                              "type": "string"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "label": "billing",
                  "confidence": 0.96,
                  "rationale": "Duplicate charge is a billing dispute.",
                  "usage": {
                    "credits": 2,
                    "balanceRemaining": 1984
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/summarize": {
      "post": {
        "operationId": "summarize",
        "summary": "Summarize",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail converts a meeting transcript, thread, or report into a tight summary, key points, and extracted action items.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "Summarize"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "length": {
                    "type": "string",
                    "enum": [
                      "brief",
                      "standard",
                      "detailed"
                    ],
                    "default": "standard"
                  },
                  "actionItems": {
                    "type": "boolean",
                    "default": true
                  }
                }
              },
              "example": {
                "text": "<meeting transcript…>",
                "length": "standard"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "summary",
                            "keyPoints",
                            "actionItems"
                          ],
                          "properties": {
                            "summary": {
                              "type": "string"
                            },
                            "keyPoints": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "actionItems": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "task"
                                ],
                                "properties": {
                                  "task": {
                                    "type": "string"
                                  },
                                  "owner": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "summary": "The team agreed to ship the billing fix on Friday.",
                  "keyPoints": [
                    "Billing bug root-caused",
                    "Launch moved to Fri"
                  ],
                  "actionItems": [
                    {
                      "task": "Deploy the fix",
                      "owner": "Priya"
                    }
                  ],
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1981
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/redact": {
      "post": {
        "operationId": "redact",
        "summary": "PII redaction",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail detects and strips names, emails, phones, SSNs, cards, and PHI from text before you store or log it.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "PII redaction"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Provide the entity types to redact, or omit them to redact all."
                  },
                  "placeholder": {
                    "type": "string",
                    "default": "[REDACTED]"
                  }
                }
              },
              "example": {
                "text": "Call Jane Doe at 415-555-0199 or jane@acme.com."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "redacted",
                            "entities",
                            "entityCount"
                          ],
                          "properties": {
                            "redacted": {
                              "type": "string"
                            },
                            "entities": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "type",
                                  "text"
                                ],
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "text": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "entityCount": {
                              "type": "integer"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "redacted": "Call [REDACTED] at [REDACTED] or [REDACTED].",
                  "entities": [
                    {
                      "type": "name",
                      "text": "Jane Doe"
                    },
                    {
                      "type": "phone",
                      "text": "415-555-0199"
                    },
                    {
                      "type": "email",
                      "text": "jane@acme.com"
                    }
                  ],
                  "entityCount": 3,
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1978
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sentiment": {
      "post": {
        "operationId": "sentiment",
        "summary": "Sentiment",
        "x-pricing": {
          "credits": 2,
          "usd": 0.02,
          "currency": "USD"
        },
        "description": "ParseRail converts a review or support message into a sentiment score, a per-aspect breakdown, and the themes driving it.\n\nCost: 2 credits ($0.02) — charged only on success.",
        "tags": [
          "Sentiment"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "aspects": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Optional aspects to break out."
                  }
                }
              },
              "example": {
                "text": "The customer likes the product, but support took days to reply.",
                "aspects": [
                  "product",
                  "support"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "sentiment",
                            "score",
                            "confidence",
                            "aspects",
                            "themes"
                          ],
                          "properties": {
                            "sentiment": {
                              "type": "string"
                            },
                            "score": {
                              "type": "number",
                              "description": "-1..1."
                            },
                            "confidence": {
                              "type": "number",
                              "description": "0–1."
                            },
                            "aspects": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "aspect",
                                  "sentiment",
                                  "score"
                                ],
                                "properties": {
                                  "aspect": {
                                    "type": "string"
                                  },
                                  "sentiment": {
                                    "type": "string"
                                  },
                                  "score": {
                                    "type": "number"
                                  }
                                }
                              }
                            },
                            "themes": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "sentiment": "neutral",
                  "score": 0.1,
                  "confidence": 0.88,
                  "aspects": [
                    {
                      "aspect": "product",
                      "sentiment": "positive",
                      "score": 0.8
                    },
                    {
                      "aspect": "support",
                      "sentiment": "negative",
                      "score": -0.6
                    }
                  ],
                  "themes": [
                    "slow support response"
                  ],
                  "usage": {
                    "credits": 2,
                    "balanceRemaining": 1976
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contract": {
      "post": {
        "operationId": "contract",
        "summary": "Contract analysis",
        "x-pricing": {
          "credits": 12,
          "usd": 0.12,
          "currency": "USD"
        },
        "description": "ParseRail converts a contract into the parties, effective date, term, renewal, governing law, obligations, and flagged risk clauses.\n\nCost: 12 credits ($0.12) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Contract analysis"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/msa.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "contractType",
                            "parties",
                            "obligations",
                            "riskFlags"
                          ],
                          "properties": {
                            "contractType": {
                              "type": "string"
                            },
                            "parties": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "name",
                                  "role"
                                ],
                                "properties": {
                                  "name": {
                                    "type": "string"
                                  },
                                  "role": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "effectiveDate": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "term": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "renewal": {
                              "type": [
                                "object",
                                "null"
                              ],
                              "required": [
                                "autoRenews"
                              ],
                              "properties": {
                                "autoRenews": {
                                  "type": "boolean"
                                },
                                "noticePeriod": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              }
                            },
                            "governingLaw": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "obligations": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "riskFlags": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "clause",
                                  "severity",
                                  "reason"
                                ],
                                "properties": {
                                  "clause": {
                                    "type": "string"
                                  },
                                  "severity": {
                                    "type": "string",
                                    "description": "low | medium | high."
                                  },
                                  "reason": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "contractType": "Master Services Agreement",
                  "parties": [
                    {
                      "name": "Acme Inc.",
                      "role": "Client"
                    },
                    {
                      "name": "Vendor LLC",
                      "role": "Provider"
                    }
                  ],
                  "effectiveDate": "2026-01-01",
                  "term": "12 months",
                  "renewal": {
                    "autoRenews": true,
                    "noticePeriod": "30 days"
                  },
                  "governingLaw": "Delaware",
                  "obligations": [
                    "Provider delivers monthly reports"
                  ],
                  "riskFlags": [
                    {
                      "clause": "Auto-renewal",
                      "severity": "medium",
                      "reason": "Renews unless cancelled 30d prior."
                    }
                  ],
                  "usage": {
                    "credits": 12,
                    "balanceRemaining": 1964
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chargeback": {
      "post": {
        "operationId": "chargeback",
        "summary": "Chargeback representment",
        "x-pricing": {
          "credits": 15,
          "usd": 0.15,
          "currency": "USD"
        },
        "description": "ParseRail converts dispute details into a representment narrative, an evidence checklist, the right reason code, and a win-likelihood.\n\nCost: 15 credits ($0.15) — charged only on success.",
        "tags": [
          "Chargeback representment"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason",
                  "transaction"
                ],
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "The cardholder's dispute reason."
                  },
                  "transaction": {
                    "type": "object",
                    "properties": {
                      "amount": {
                        "type": "number"
                      },
                      "currency": {
                        "type": "string",
                        "example": "USD"
                      },
                      "date": {
                        "type": "string",
                        "format": "date"
                      },
                      "descriptor": {
                        "type": "string"
                      }
                    }
                  },
                  "evidence": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "context": {
                    "type": "string"
                  },
                  "network": {
                    "type": "string",
                    "enum": [
                      "visa",
                      "mastercard",
                      "amex",
                      "discover"
                    ]
                  }
                }
              },
              "example": {
                "reason": "Cardholder claims product never arrived",
                "transaction": {
                  "amount": 129,
                  "currency": "USD",
                  "date": "2026-06-12",
                  "descriptor": "ACME STORE"
                },
                "evidence": [
                  "Tracking shows delivered 2026-06-15",
                  "Signed at door"
                ],
                "network": "visa"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "reasonCategory",
                            "recommendedAction",
                            "narrative",
                            "evidenceChecklist",
                            "winLikelihood",
                            "rationale"
                          ],
                          "properties": {
                            "reasonCategory": {
                              "type": "string"
                            },
                            "recommendedAction": {
                              "type": "string",
                              "description": "fight | accept."
                            },
                            "narrative": {
                              "type": "string"
                            },
                            "evidenceChecklist": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "item",
                                  "have"
                                ],
                                "properties": {
                                  "item": {
                                    "type": "string"
                                  },
                                  "have": {
                                    "type": "boolean"
                                  }
                                }
                              }
                            },
                            "winLikelihood": {
                              "type": "number",
                              "description": "0–1."
                            },
                            "rationale": {
                              "type": "string"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "reasonCategory": "product_not_received",
                  "recommendedAction": "fight",
                  "narrative": "The cardholder disputes non-receipt, and the case includes carrier tracking.",
                  "evidenceChecklist": [
                    {
                      "item": "Carrier tracking with delivery confirmation",
                      "have": true
                    }
                  ],
                  "winLikelihood": 0.82,
                  "rationale": "Delivery confirmation directly rebuts non-receipt.",
                  "usage": {
                    "credits": 15,
                    "balanceRemaining": 1949
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/enrich": {
      "post": {
        "operationId": "enrich",
        "summary": "Company enrichment",
        "x-pricing": {
          "credits": 5,
          "usd": 0.05,
          "currency": "USD"
        },
        "description": "ParseRail converts a domain or work email into a structured company profile with the name, description, industry, HQ, size, and links.\n\nCost: 5 credits ($0.05) — charged only on success.",
        "tags": [
          "Company enrichment"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Provide one of: domain or email.",
                "x-ts-input": "{ domain: string } | { email: string }",
                "properties": {
                  "domain": {
                    "type": "string",
                    "example": "stripe.com"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "example": "sam@stripe.com"
                  }
                }
              },
              "example": {
                "email": "sam@stripe.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "name",
                            "domain",
                            "grounded"
                          ],
                          "properties": {
                            "name": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "domain": {
                              "type": "string"
                            },
                            "description": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "industry": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "headquarters": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "employeeRange": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "founded": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "links": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "string"
                              }
                            },
                            "grounded": {
                              "type": "boolean",
                              "description": "Set this to True when web-grounded sources backed the profile."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "name": "Stripe",
                  "domain": "stripe.com",
                  "description": "Payments infrastructure for the internet.",
                  "industry": "Financial technology",
                  "headquarters": "South San Francisco, CA",
                  "employeeRange": "5001-10000",
                  "founded": 2010,
                  "links": {
                    "website": "https://stripe.com",
                    "linkedin": "…",
                    "twitter": "…"
                  },
                  "grounded": true,
                  "usage": {
                    "credits": 5,
                    "balanceRemaining": 1944
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/invoice": {
      "post": {
        "operationId": "invoice",
        "summary": "Invoice extraction",
        "x-pricing": {
          "credits": 8,
          "usd": 0.08,
          "currency": "USD"
        },
        "description": "ParseRail converts an invoice, whether PDF, photo, or text, into the vendor, dates, PO refs, tax, totals, and clean line items.\n\nCost: 8 credits ($0.08) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Invoice extraction"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/invoice.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "vendor",
                            "lineItems"
                          ],
                          "properties": {
                            "vendor": {
                              "type": "object",
                              "required": [
                                "name"
                              ],
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "address": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "taxId": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              }
                            },
                            "customer": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "invoiceNumber": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "poNumber": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "issueDate": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "YYYY-MM-DD."
                            },
                            "dueDate": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "YYYY-MM-DD."
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "ISO code, e.g. USD."
                            },
                            "subtotal": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "tax": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "total": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "paymentTerms": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "lineItems": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "description",
                                  "amount"
                                ],
                                "properties": {
                                  "description": {
                                    "type": "string"
                                  },
                                  "quantity": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "unitPrice": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "amount": {
                                    "type": "number"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "vendor": {
                    "name": "Acme Supplies Inc.",
                    "address": "123 Warehouse Rd, Columbus OH",
                    "taxId": null
                  },
                  "customer": "Northwind Coffee LLC",
                  "invoiceNumber": "INV-10428",
                  "poNumber": "PO-88",
                  "issueDate": "2026-06-30",
                  "dueDate": "2026-07-30",
                  "currency": "USD",
                  "subtotal": 1200,
                  "tax": 55.5,
                  "total": 1255.5,
                  "paymentTerms": "Net 30",
                  "lineItems": [
                    {
                      "description": "Widget A",
                      "quantity": 12,
                      "unitPrice": 100,
                      "amount": 1200
                    }
                  ],
                  "usage": {
                    "credits": 8,
                    "balanceRemaining": 1936
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/receipt": {
      "post": {
        "operationId": "receipt",
        "summary": "Receipt extraction",
        "x-pricing": {
          "credits": 6,
          "usd": 0.06,
          "currency": "USD"
        },
        "description": "ParseRail converts a receipt into the merchant, items, totals, payment method, and an expense category for expense flows.\n\nCost: 6 credits ($0.06) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Receipt extraction"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/receipt.jpg"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "merchant",
                            "category",
                            "items"
                          ],
                          "properties": {
                            "merchant": {
                              "type": "string"
                            },
                            "location": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "date": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "YYYY-MM-DD."
                            },
                            "time": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "HH:MM, 24h."
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "subtotal": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "tax": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "tip": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "total": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "paymentMethod": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "category": {
                              "type": "string",
                              "enum": [
                                "meals",
                                "travel",
                                "lodging",
                                "transport",
                                "office",
                                "software",
                                "utilities",
                                "entertainment",
                                "groceries",
                                "health",
                                "other"
                              ],
                              "description": "Expense category, ready to post."
                            },
                            "items": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "description",
                                  "amount"
                                ],
                                "properties": {
                                  "description": {
                                    "type": "string"
                                  },
                                  "quantity": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "amount": {
                                    "type": "number"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "merchant": "Blue Bottle Coffee",
                  "location": "315 Linden St, Oakland CA",
                  "date": "2026-07-02",
                  "time": "09:41",
                  "currency": "USD",
                  "subtotal": 10.25,
                  "tax": 0.95,
                  "tip": null,
                  "total": 11.2,
                  "paymentMethod": "visa ****4242",
                  "category": "meals",
                  "items": [
                    {
                      "description": "Latte 12oz",
                      "quantity": 1,
                      "amount": 5.75
                    },
                    {
                      "description": "Croissant",
                      "quantity": 1,
                      "amount": 4.5
                    }
                  ],
                  "usage": {
                    "credits": 6,
                    "balanceRemaining": 1930
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/statement": {
      "post": {
        "operationId": "statement",
        "summary": "Statement parsing",
        "x-pricing": {
          "credits": 12,
          "usd": 0.12,
          "currency": "USD"
        },
        "description": "ParseRail converts a bank or card statement into the account, period, balances, and every transaction as a normalized row.\n\nCost: 12 credits ($0.12) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Statement parsing"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/statement.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "transactions",
                            "transactionCount"
                          ],
                          "properties": {
                            "institution": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "accountHolder": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "accountNumberMasked": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "As printed, e.g. ****1234."
                            },
                            "periodStart": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "YYYY-MM-DD."
                            },
                            "periodEnd": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "YYYY-MM-DD."
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "openingBalance": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "closingBalance": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "transactions": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "description",
                                  "amount",
                                  "direction"
                                ],
                                "properties": {
                                  "date": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "YYYY-MM-DD."
                                  },
                                  "description": {
                                    "type": "string"
                                  },
                                  "amount": {
                                    "type": "number",
                                    "description": "Positive; see direction."
                                  },
                                  "direction": {
                                    "type": "string",
                                    "enum": [
                                      "debit",
                                      "credit"
                                    ]
                                  },
                                  "category": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "balance": {
                                    "type": [
                                      "number",
                                      "null"
                                    ],
                                    "description": "Running balance when printed."
                                  }
                                }
                              }
                            },
                            "transactionCount": {
                              "type": "integer"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "institution": "Chase",
                  "accountHolder": "Northwind Coffee LLC",
                  "accountNumberMasked": "****4821",
                  "periodStart": "2026-06-01",
                  "periodEnd": "2026-06-30",
                  "currency": "USD",
                  "openingBalance": 18240.11,
                  "closingBalance": 21694.6,
                  "transactions": [
                    {
                      "date": "2026-06-03",
                      "description": "STRIPE PAYOUT",
                      "amount": 4820.5,
                      "direction": "credit",
                      "category": "revenue",
                      "balance": 23060.61
                    },
                    {
                      "date": "2026-06-05",
                      "description": "WEWORK RENT",
                      "amount": 2100,
                      "direction": "debit",
                      "category": "rent",
                      "balance": 20960.61
                    }
                  ],
                  "transactionCount": 42,
                  "usage": {
                    "credits": 12,
                    "balanceRemaining": 1918
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/resume": {
      "post": {
        "operationId": "resume",
        "summary": "Resume parsing",
        "x-pricing": {
          "credits": 8,
          "usd": 0.08,
          "currency": "USD"
        },
        "description": "ParseRail converts a resume or CV into a structured candidate profile with contact, skills, experience, education, and links.\n\nCost: 8 credits ($0.08) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Resume parsing"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/resume.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "name",
                            "skills",
                            "experience",
                            "education"
                          ],
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "email": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "phone": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "location": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "headline": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "summary": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "yearsExperience": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "skills": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "experience": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "title",
                                  "company",
                                  "highlights"
                                ],
                                "properties": {
                                  "title": {
                                    "type": "string"
                                  },
                                  "company": {
                                    "type": "string"
                                  },
                                  "startDate": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "YYYY-MM or 'present'."
                                  },
                                  "endDate": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "highlights": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              }
                            },
                            "education": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "school"
                                ],
                                "properties": {
                                  "degree": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "school": {
                                    "type": "string"
                                  },
                                  "year": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "links": {
                              "type": "object",
                              "properties": {
                                "linkedin": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "github": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "website": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "name": "Maya Chen",
                  "email": "maya@…",
                  "phone": "+1 415 …",
                  "location": "Brooklyn, NY",
                  "headline": "Senior Backend Engineer",
                  "summary": "The backend engineer focuses on payments infrastructure.",
                  "yearsExperience": 8,
                  "skills": [
                    "Go",
                    "Postgres",
                    "Kafka",
                    "Kubernetes"
                  ],
                  "experience": [
                    {
                      "title": "Senior Backend Engineer",
                      "company": "Meridian Labs",
                      "startDate": "2023-02",
                      "endDate": "present",
                      "highlights": [
                        "Cut settlement latency 70%"
                      ]
                    }
                  ],
                  "education": [
                    {
                      "degree": "BS Computer Science",
                      "school": "UC Berkeley",
                      "year": "2018"
                    }
                  ],
                  "links": {
                    "linkedin": "https://linkedin.com/in/…",
                    "github": "https://github.com/…",
                    "website": null
                  },
                  "usage": {
                    "credits": 8,
                    "balanceRemaining": 1910
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tables": {
      "post": {
        "operationId": "tables",
        "summary": "Table extraction",
        "x-pricing": {
          "credits": 8,
          "usd": 0.08,
          "currency": "USD"
        },
        "description": "ParseRail extracts every table in a document, including scanned tables, as clean headers and rows for your spreadsheet or DB.\n\nCost: 8 credits ($0.08) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Table extraction"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/quarterly-report.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "tables",
                            "tableCount"
                          ],
                          "properties": {
                            "tables": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "headers",
                                  "rows"
                                ],
                                "properties": {
                                  "title": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "page": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "headers": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  "rows": {
                                    "type": "array",
                                    "items": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              }
                            },
                            "tableCount": {
                              "type": "integer"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "tables": [
                    {
                      "title": "Revenue by region",
                      "page": 4,
                      "headers": [
                        "Region",
                        "Q1",
                        "Q2"
                      ],
                      "rows": [
                        [
                          "North America",
                          "$1.2M",
                          "$1.4M"
                        ],
                        [
                          "EMEA",
                          "$800k",
                          "$950k"
                        ]
                      ]
                    }
                  ],
                  "tableCount": 3,
                  "usage": {
                    "credits": 8,
                    "balanceRemaining": 1902
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/split": {
      "post": {
        "operationId": "split",
        "summary": "Document splitting",
        "x-pricing": {
          "credits": 10,
          "usd": 0.1,
          "currency": "USD"
        },
        "description": "ParseRail classifies and splits a multi-document scan bundle, identifying each document, its start and end, and its summary.\n\nCost: 10 credits ($0.10) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Document splitting"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "type": "object",
                    "description": "Provide exactly one of: file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  }
                ],
                "x-doc-input": true,
                "properties": {
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "fileUrl": "https://…/scan-bundle.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "documents",
                            "documentCount"
                          ],
                          "properties": {
                            "documents": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "docType",
                                  "title",
                                  "pageStart",
                                  "pageEnd",
                                  "summary"
                                ],
                                "properties": {
                                  "docType": {
                                    "type": "string"
                                  },
                                  "title": {
                                    "type": "string"
                                  },
                                  "pageStart": {
                                    "type": "number"
                                  },
                                  "pageEnd": {
                                    "type": "number"
                                  },
                                  "party": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "date": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "YYYY-MM-DD."
                                  },
                                  "summary": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "documentCount": {
                              "type": "integer"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "documents": [
                    {
                      "docType": "invoice",
                      "title": "Acme Supplies invoice INV-10428",
                      "pageStart": 1,
                      "pageEnd": 2,
                      "party": "Acme Supplies Inc.",
                      "date": "2026-06-30",
                      "summary": "The invoice charges the buyer $1,255.50 for 12 Widget A units."
                    },
                    {
                      "docType": "coi",
                      "title": "Certificate of insurance",
                      "pageStart": 3,
                      "pageEnd": 3,
                      "party": "Hartford",
                      "date": "2026-01-15",
                      "summary": "GL certificate, $2M aggregate, expires 2027-01-15."
                    }
                  ],
                  "documentCount": 2,
                  "usage": {
                    "credits": 10,
                    "balanceRemaining": 1892
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/compare": {
      "post": {
        "operationId": "compare",
        "summary": "Document comparison",
        "x-pricing": {
          "credits": 15,
          "usd": 0.15,
          "currency": "USD"
        },
        "description": "ParseRail compares two versions of a contract or document and returns every material change, what it means, and the risk it carries.\n\nCost: 15 credits ($0.15) — charged only on success.\n\nAccepts `async: true` for long documents — see the **Async & webhooks** guide.",
        "tags": [
          "Document comparison"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "a",
                  "b"
                ],
                "x-ts-input": "{ a: DocumentInput; b: DocumentInput }",
                "properties": {
                  "a": {
                    "type": "object",
                    "description": "Provide the earlier version as a file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  },
                  "b": {
                    "type": "object",
                    "description": "Provide the later version as a file, fileUrl, or text.",
                    "properties": {
                      "file": {
                        "type": "object",
                        "description": "Inline document.",
                        "properties": {
                          "data": {
                            "type": "string",
                            "description": "Base64-encoded file bytes."
                          },
                          "mimeType": {
                            "type": "string",
                            "example": "application/pdf"
                          }
                        },
                        "required": [
                          "data",
                          "mimeType"
                        ]
                      },
                      "fileUrl": {
                        "type": "string",
                        "format": "uri",
                        "description": "Provide a public URL to a PDF or image."
                      },
                      "text": {
                        "type": "string",
                        "description": "Provide raw text if you already have it."
                      }
                    }
                  },
                  "async": {
                    "type": "boolean",
                    "default": false,
                    "description": "The endpoint processes the request outside the request/response cycle. It returns 202 with a `jobId` instead of the result. Poll `GET /v1/jobs/{id}`, or supply `callbackUrl`."
                  },
                  "callbackUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "The endpoint POSTs the finished job to a public https URL. The endpoint signs the request with your account's webhook secret, as described in the Async & webhooks guide. The endpoint ignores the URL unless `async` is true."
                  }
                }
              },
              "example": {
                "a": {
                  "fileUrl": "https://…/msa-2025.pdf"
                },
                "b": {
                  "fileUrl": "https://…/msa-2026.pdf"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "changes",
                            "changeCount",
                            "summary",
                            "riskNotes"
                          ],
                          "properties": {
                            "changes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "section",
                                  "change",
                                  "materiality",
                                  "note"
                                ],
                                "properties": {
                                  "section": {
                                    "type": "string"
                                  },
                                  "change": {
                                    "type": "string",
                                    "enum": [
                                      "added",
                                      "removed",
                                      "modified"
                                    ]
                                  },
                                  "before": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "after": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "materiality": {
                                    "type": "string",
                                    "enum": [
                                      "low",
                                      "medium",
                                      "high"
                                    ]
                                  },
                                  "note": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "changeCount": {
                              "type": "integer"
                            },
                            "summary": {
                              "type": "string"
                            },
                            "riskNotes": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "changes": [
                    {
                      "section": "Term & Renewal",
                      "change": "modified",
                      "before": "30 days' notice",
                      "after": "90 days' notice",
                      "materiality": "high",
                      "note": "The cancellation window tripled, so the exit is easy to miss."
                    }
                  ],
                  "changeCount": 6,
                  "summary": "The 2026 draft raises the fees you pay by 8% and tightens the renewal window…",
                  "riskNotes": [
                    "Notice period tripled to 90 days",
                    "Liability cap now excludes data breaches"
                  ],
                  "usage": {
                    "credits": 15,
                    "balanceRemaining": 1877
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted (`async: true`). The job is queued. Poll `GET /v1/jobs/{id}` or wait for the callback. Credits are charged when it succeeds, never on enqueue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobAccepted"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "status": "queued",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/structure": {
      "post": {
        "operationId": "structure",
        "summary": "Schema structuring",
        "x-pricing": {
          "credits": 6,
          "usd": 0.06,
          "currency": "USD"
        },
        "description": "ParseRail takes any messy input, including text, HTML, or an email, plus YOUR JSON schema, and returns output shaped to it. It validates the output against your required fields and property types, performs an automatic corrective retry, and returns a `valid` flag.\n\nCost: 6 credits ($0.06) — charged only on success.",
        "tags": [
          "Schema structuring"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "input",
                  "schema"
                ],
                "properties": {
                  "input": {
                    "type": "string",
                    "description": "Provide any messy input, including text, HTML, an email, or a JSON blob."
                  },
                  "schema": {
                    "type": "object",
                    "description": "Provide the JSON Schema that the output must conform to.",
                    "additionalProperties": true
                  },
                  "instructions": {
                    "type": "string",
                    "description": "Optional extra guidance."
                  }
                }
              },
              "example": {
                "input": "Dana Reyes sent a new order from dana@brightco.io for 3 large planters to 44 Vine St, Portland, OR by the 20th.",
                "schema": {
                  "type": "object",
                  "required": [
                    "customer",
                    "items"
                  ],
                  "properties": {
                    "customer": {
                      "type": "object"
                    },
                    "items": {
                      "type": "array"
                    },
                    "shipTo": {
                      "type": "string"
                    },
                    "deadline": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "data",
                            "valid"
                          ],
                          "properties": {
                            "data": {
                              "type": "object",
                              "additionalProperties": true,
                              "description": "Provide the output that conforms to your schema."
                            },
                            "valid": {
                              "type": "boolean",
                              "description": "Set this to True when every required field of your schema was satisfiable."
                            },
                            "notes": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "List anything the input could not support, including missing required fields and ambiguities."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "data": {
                    "customer": {
                      "name": "Dana Reyes",
                      "email": "dana@brightco.io"
                    },
                    "items": [
                      {
                        "product": "large planter",
                        "quantity": 3
                      }
                    ],
                    "shipTo": "44 Vine St, Portland OR",
                    "deadline": "2026-07-20"
                  },
                  "valid": true,
                  "notes": [],
                  "usage": {
                    "credits": 6,
                    "balanceRemaining": 1871
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/normalize": {
      "post": {
        "operationId": "normalize",
        "summary": "Record normalization",
        "x-pricing": {
          "credits": 5,
          "usd": 0.05,
          "currency": "USD"
        },
        "description": "ParseRail converts a batch of messy records into clean canonical rows and returns a change log of every fix, including casing, formats, and dedup-ready values.\n\nCost: 5 credits ($0.05) — charged only on success.",
        "tags": [
          "Record normalization"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "records"
                ],
                "properties": {
                  "records": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "maxItems": 500,
                    "description": "The messy records."
                  },
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Provide canonical field names to normalize into, or omit them to keep the input's fields."
                  },
                  "instructions": {
                    "type": "string",
                    "description": "House rules, e.g. \"US phone format, uppercase state codes\"."
                  }
                }
              },
              "example": {
                "records": [
                  {
                    "name": "SMITH, jon",
                    "phone": "415.555.0199",
                    "state": "california"
                  }
                ],
                "instructions": "US phone format, 2-letter state codes, Title Case names"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "records",
                            "changes"
                          ],
                          "properties": {
                            "records": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "additionalProperties": true
                              },
                              "description": "Return the cleaned records in the same order as the input."
                            },
                            "changes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "index",
                                  "field",
                                  "to"
                                ],
                                "properties": {
                                  "index": {
                                    "type": "integer",
                                    "description": "Input record index."
                                  },
                                  "field": {
                                    "type": "string"
                                  },
                                  "from": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "to": {
                                    "type": "string"
                                  },
                                  "reason": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "records": [
                    {
                      "name": "Jon Smith",
                      "phone": "(415) 555-0199",
                      "state": "CA"
                    }
                  ],
                  "changes": [
                    {
                      "index": 0,
                      "field": "state",
                      "from": "california",
                      "to": "CA",
                      "reason": "2-letter state code"
                    }
                  ],
                  "usage": {
                    "credits": 5,
                    "balanceRemaining": 1866
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/match": {
      "post": {
        "operationId": "match",
        "summary": "Entity matching",
        "x-pricing": {
          "credits": 8,
          "usd": 0.08,
          "currency": "USD"
        },
        "description": "ParseRail compares two record sets and identifies rows that refer to the same real-world thing. It handles fuzzy names, typos, and aliases, and returns confidence and reasoning.\n\nCost: 8 credits ($0.08) — charged only on success.",
        "tags": [
          "Entity matching"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "a",
                  "b"
                ],
                "properties": {
                  "a": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "maxItems": 200,
                    "description": "First record set."
                  },
                  "b": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "maxItems": 200,
                    "description": "Second record set."
                  },
                  "keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Fields that most identify an entity, e.g. [\"name\",\"email\"]."
                  }
                }
              },
              "example": {
                "a": [
                  {
                    "name": "Acme Supplies Inc",
                    "city": "Columbus"
                  }
                ],
                "b": [
                  {
                    "vendor": "ACME SUPPLY, INC.",
                    "location": "Columbus, OH"
                  }
                ],
                "keys": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "matches",
                            "unmatchedA",
                            "unmatchedB"
                          ],
                          "properties": {
                            "matches": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "aIndex",
                                  "bIndex",
                                  "confidence"
                                ],
                                "properties": {
                                  "aIndex": {
                                    "type": "integer"
                                  },
                                  "bIndex": {
                                    "type": "integer"
                                  },
                                  "confidence": {
                                    "type": "number",
                                    "description": "0–1."
                                  },
                                  "reason": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "unmatchedA": {
                              "type": "array",
                              "items": {
                                "type": "integer"
                              }
                            },
                            "unmatchedB": {
                              "type": "array",
                              "items": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "matches": [
                    {
                      "aIndex": 0,
                      "bIndex": 0,
                      "confidence": 0.94,
                      "reason": "Same entity: name variant + same city."
                    }
                  ],
                  "unmatchedA": [],
                  "unmatchedB": [],
                  "usage": {
                    "credits": 8,
                    "balanceRemaining": 1858
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/categorize": {
      "post": {
        "operationId": "categorize",
        "summary": "Batch categorization",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail categorizes up to a hundred products, transactions, or tickets against your taxonomy in one call. Each item includes a confidence.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "Batch categorization"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items",
                  "taxonomy"
                ],
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 100,
                    "description": "The things to categorize."
                  },
                  "taxonomy": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 2,
                    "maxItems": 100,
                    "description": "Your categories."
                  },
                  "multi": {
                    "type": "boolean",
                    "description": "Allow multiple categories per item.",
                    "default": false
                  },
                  "instructions": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "items": [
                  "AWS invoice June",
                  "Uber to airport",
                  "Figma annual"
                ],
                "taxonomy": [
                  "software",
                  "travel",
                  "office",
                  "other"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "results"
                          ],
                          "properties": {
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "index",
                                  "category",
                                  "confidence"
                                ],
                                "properties": {
                                  "index": {
                                    "type": "integer",
                                    "description": "Input item index."
                                  },
                                  "category": {
                                    "type": "string"
                                  },
                                  "categories": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "Provide all categories when multi is set."
                                  },
                                  "confidence": {
                                    "type": "number"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "results": [
                    {
                      "index": 0,
                      "category": "software",
                      "confidence": 0.97
                    },
                    {
                      "index": 1,
                      "category": "travel",
                      "confidence": 0.98
                    },
                    {
                      "index": 2,
                      "category": "software",
                      "confidence": 0.96
                    }
                  ],
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1855
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/dunning": {
      "post": {
        "operationId": "dunning",
        "summary": "Collections sequence",
        "x-pricing": {
          "credits": 8,
          "usd": 0.08,
          "currency": "USD"
        },
        "description": "ParseRail turns an overdue invoice into a ready-to-send collection sequence. The sequence escalates its pace and tone according to how late the invoice is.\n\nCost: 8 credits ($0.08) — charged only on success.",
        "tags": [
          "Collections sequence"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "invoice",
                  "customer"
                ],
                "properties": {
                  "invoice": {
                    "type": "object",
                    "required": [
                      "amount"
                    ],
                    "properties": {
                      "number": {
                        "type": "string"
                      },
                      "amount": {
                        "type": "number"
                      },
                      "currency": {
                        "type": "string"
                      },
                      "dueDate": {
                        "type": "string",
                        "description": "YYYY-MM-DD."
                      },
                      "daysOverdue": {
                        "type": "integer"
                      }
                    }
                  },
                  "customer": {
                    "type": "object",
                    "required": [
                      "name"
                    ],
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "history": {
                        "type": "string",
                        "description": "Payment history / relationship context."
                      }
                    }
                  },
                  "tone": {
                    "type": "string",
                    "enum": [
                      "friendly",
                      "firm",
                      "final"
                    ],
                    "description": "Where to start the escalation."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms"
                    ],
                    "default": "email"
                  },
                  "steps": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5,
                    "default": 3
                  }
                }
              },
              "example": {
                "invoice": {
                  "number": "INV-10428",
                  "amount": 1255.5,
                  "dueDate": "2026-06-15",
                  "daysOverdue": 23
                },
                "customer": {
                  "name": "Northwind Coffee",
                  "history": "Usually pays on time; second late invoice this year."
                },
                "steps": 3
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "sequence",
                            "escalationAdvice"
                          ],
                          "properties": {
                            "sequence": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "day",
                                  "channel",
                                  "message"
                                ],
                                "properties": {
                                  "day": {
                                    "type": "integer",
                                    "description": "Days from now to send."
                                  },
                                  "channel": {
                                    "type": "string",
                                    "enum": [
                                      "email",
                                      "sms"
                                    ]
                                  },
                                  "subject": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "message": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "escalationAdvice": {
                              "type": "string",
                              "description": "State what to do if the sequence completes unpaid."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "sequence": [
                    {
                      "day": 0,
                      "channel": "email",
                      "subject": "Invoice INV-10428 — friendly nudge",
                      "message": "Hi Northwind team…"
                    },
                    {
                      "day": 7,
                      "channel": "email",
                      "subject": "Invoice INV-10428 is 30 days past due",
                      "message": "…"
                    }
                  ],
                  "escalationAdvice": "If unpaid after step 3, move to a payment plan offer before collections because history suggests goodwill.",
                  "usage": {
                    "credits": 8,
                    "balanceRemaining": 1847
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/po-match": {
      "post": {
        "operationId": "po-match",
        "summary": "3-way match",
        "x-pricing": {
          "credits": 10,
          "usd": 0.1,
          "currency": "USD"
        },
        "description": "ParseRail compares an invoice, purchase order, and receipt. It marks the documents as matched, partial, or mismatched, and flags and sizes every discrepancy.\n\nCost: 10 credits ($0.10) — charged only on success.",
        "tags": [
          "3-way match"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "invoice",
                  "purchaseOrder"
                ],
                "properties": {
                  "invoice": {
                    "type": "string",
                    "description": "The invoice — structured JSON (e.g. /v1/invoice output) or raw text."
                  },
                  "purchaseOrder": {
                    "type": "string",
                    "description": "Provide the PO as structured JSON or raw text."
                  },
                  "receipt": {
                    "type": "string",
                    "description": "Provide an optional goods receipt or delivery note for a 3-way match."
                  },
                  "tolerancePct": {
                    "type": "number",
                    "description": "Set the price variance tolerance in percent. The default is 2."
                  }
                }
              },
              "example": {
                "invoice": "{…/v1/invoice output…}",
                "purchaseOrder": "PO-88: 12x Widget A @ $95, ship to Columbus",
                "receipt": "GRN: 12 Widget A received 2026-06-28"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "status",
                            "discrepancies",
                            "recommendation"
                          ],
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": [
                                "matched",
                                "partial",
                                "mismatched"
                              ]
                            },
                            "discrepancies": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "field",
                                  "severity",
                                  "note"
                                ],
                                "properties": {
                                  "field": {
                                    "type": "string"
                                  },
                                  "invoice": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "purchaseOrder": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "receipt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "severity": {
                                    "type": "string",
                                    "enum": [
                                      "low",
                                      "medium",
                                      "high"
                                    ]
                                  },
                                  "note": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "recommendation": {
                              "type": "string",
                              "description": "Return approve | hold | reject with the reason."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "status": "partial",
                  "discrepancies": [
                    {
                      "field": "unitPrice",
                      "invoice": "$100.00",
                      "purchaseOrder": "$95.00",
                      "receipt": null,
                      "severity": "high",
                      "note": "5.3% over PO price — beyond 2% tolerance."
                    }
                  ],
                  "recommendation": "The invoice is on hold because quantities match but the unit price exceeds the PO. Request a corrected invoice.",
                  "usage": {
                    "credits": 10,
                    "balanceRemaining": 1837
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/quote": {
      "post": {
        "operationId": "quote",
        "summary": "Quote builder",
        "x-pricing": {
          "credits": 8,
          "usd": 0.08,
          "currency": "USD"
        },
        "description": "ParseRail turns a job description and your rates into an itemized quote. The quote includes professional wording, assumptions, and scope notes.\n\nCost: 8 credits ($0.08) — charged only on success.",
        "tags": [
          "Quote builder"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "job"
                ],
                "properties": {
                  "job": {
                    "type": "string",
                    "description": "Provide what the customer needs in plain words."
                  },
                  "rates": {
                    "type": "string",
                    "description": "Provide your rate card or pricing rules in any format."
                  },
                  "pastQuotes": {
                    "type": "string",
                    "description": "Add optional examples of quotes you have sent."
                  },
                  "currency": {
                    "type": "string",
                    "default": "USD"
                  }
                }
              },
              "example": {
                "job": "The work covers repainting a 2-bedroom apartment, including walls and trim, before the tenant moves in Aug 1.",
                "rates": "$65/hr labor, materials at cost +10%"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "lineItems",
                            "total",
                            "assumptions"
                          ],
                          "properties": {
                            "lineItems": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "description",
                                  "amount"
                                ],
                                "properties": {
                                  "description": {
                                    "type": "string"
                                  },
                                  "quantity": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "unitPrice": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "amount": {
                                    "type": "number"
                                  }
                                }
                              }
                            },
                            "subtotal": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "tax": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "total": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "assumptions": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "scopeNotes": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "What's explicitly out of scope."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "lineItems": [
                    {
                      "description": "Prep + painting labor (2BR walls & trim)",
                      "quantity": 26,
                      "unitPrice": 65,
                      "amount": 1690
                    },
                    {
                      "description": "Paint & materials (est.)",
                      "quantity": null,
                      "unitPrice": null,
                      "amount": 420
                    }
                  ],
                  "subtotal": 2110,
                  "tax": null,
                  "total": 2110,
                  "currency": "USD",
                  "assumptions": [
                    "Standard 8-ft ceilings",
                    "Two coats",
                    "Unit empty during work"
                  ],
                  "scopeNotes": "Ceilings and cabinet interiors excluded.",
                  "usage": {
                    "credits": 8,
                    "balanceRemaining": 1829
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/fraud-flag": {
      "post": {
        "operationId": "fraud-flag",
        "summary": "Fraud triage",
        "x-pricing": {
          "credits": 6,
          "usd": 0.06,
          "currency": "USD"
        },
        "description": "ParseRail evaluates an order or transaction in context and returns a risk score. It lists the signals driving the score and the checks worth running before you ship.\n\nCost: 6 credits ($0.06) — charged only on success.",
        "tags": [
          "Fraud triage"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "order"
                ],
                "properties": {
                  "order": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Provide the order/transaction data you have: amount, email, addresses, IP, device, history, and anything else available."
                  },
                  "context": {
                    "type": "string",
                    "description": "Store context such as typical order size and known patterns."
                  }
                }
              },
              "example": {
                "order": {
                  "amount": 950,
                  "email": "qq1998x@tempmail.dev",
                  "shippingCity": "Miami",
                  "billingCity": "Portland",
                  "ip": "203.0.113.9",
                  "accountAgeDays": 0,
                  "expedited": true
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "riskScore",
                            "riskLevel",
                            "signals",
                            "recommendation"
                          ],
                          "properties": {
                            "riskScore": {
                              "type": "number",
                              "description": "0–1."
                            },
                            "riskLevel": {
                              "type": "string",
                              "enum": [
                                "low",
                                "medium",
                                "high"
                              ]
                            },
                            "signals": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "signal",
                                  "weight",
                                  "note"
                                ],
                                "properties": {
                                  "signal": {
                                    "type": "string"
                                  },
                                  "weight": {
                                    "type": "string",
                                    "enum": [
                                      "low",
                                      "medium",
                                      "high"
                                    ]
                                  },
                                  "note": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "recommendedChecks": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "recommendation": {
                              "type": "string",
                              "enum": [
                                "allow",
                                "review",
                                "block"
                              ]
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "riskScore": 0.82,
                  "riskLevel": "high",
                  "signals": [
                    {
                      "signal": "Disposable email domain",
                      "weight": "high",
                      "note": "tempmail.dev is a throwaway provider."
                    },
                    {
                      "signal": "Billing/shipping mismatch + rush shipping",
                      "weight": "medium",
                      "note": "Classic resale pattern on a new account."
                    }
                  ],
                  "recommendedChecks": [
                    "3DS challenge",
                    "Verify phone",
                    "Match IP geolocation to billing"
                  ],
                  "recommendation": "review",
                  "usage": {
                    "credits": 6,
                    "balanceRemaining": 1823
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/reply": {
      "post": {
        "operationId": "reply",
        "summary": "Reply drafting",
        "x-pricing": {
          "credits": 5,
          "usd": 0.05,
          "currency": "USD"
        },
        "description": "ParseRail turns a customer thread and your context into a ready-to-send reply. The reply uses the requested tone and includes an internal note for the agent.\n\nCost: 5 credits ($0.05) — charged only on success.",
        "tags": [
          "Reply drafting"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "thread"
                ],
                "properties": {
                  "thread": {
                    "type": "string",
                    "description": "Provide the email/ticket thread with the newest message last."
                  },
                  "context": {
                    "type": "string",
                    "description": "Provide the policies, KB extracts, and account facts that the reply may use."
                  },
                  "tone": {
                    "type": "string",
                    "enum": [
                      "professional",
                      "friendly",
                      "apologetic",
                      "firm"
                    ],
                    "default": "professional"
                  },
                  "goal": {
                    "type": "string",
                    "description": "State what the reply should achieve, e.g. \"offer refund, keep them\"."
                  },
                  "senderName": {
                    "type": "string",
                    "description": "Sign-off name."
                  }
                }
              },
              "example": {
                "thread": "Customer: I was charged twice for order 5561 and support hasn't replied in 3 days.",
                "context": "Duplicate charge confirmed in Stripe; refund takes 5-10 days.",
                "tone": "apologetic",
                "goal": "Refund the duplicate, keep the customer",
                "senderName": "Sam"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "reply"
                          ],
                          "properties": {
                            "reply": {
                              "type": "string",
                              "description": "Ready to send."
                            },
                            "subject": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "internalNote": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Provide caveats and things for the human agent to verify."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "reply": "Hi, you're right, and I'm sorry about the silence. I refunded the duplicate charge just now.",
                  "subject": "Re: Double charge on order 5561 — refunded",
                  "internalNote": "Refund issued; check why the retry fired twice on this order.",
                  "usage": {
                    "credits": 5,
                    "balanceRemaining": 1818
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/triage": {
      "post": {
        "operationId": "triage",
        "summary": "Ticket triage",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail evaluates a support ticket and returns its priority, category, assigned team, sentiment, SLA risk, and a suggested first response.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "Ticket triage"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ticket"
                ],
                "properties": {
                  "ticket": {
                    "type": "string",
                    "description": "The ticket text (subject + body)."
                  },
                  "categories": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Provide your category set, or omit it for sensible defaults."
                  },
                  "teams": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Routable teams."
                  }
                }
              },
              "example": {
                "ticket": "Subject: URGENT site down\nOur checkout has been erroring for 2 hours, we're losing sales.",
                "categories": [
                  "bug",
                  "billing",
                  "how-to"
                ],
                "teams": [
                  "payments",
                  "platform",
                  "support"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "priority",
                            "category",
                            "sentiment",
                            "slaRisk",
                            "summary"
                          ],
                          "properties": {
                            "priority": {
                              "type": "string",
                              "enum": [
                                "urgent",
                                "high",
                                "normal",
                                "low"
                              ]
                            },
                            "category": {
                              "type": "string"
                            },
                            "team": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "sentiment": {
                              "type": "string"
                            },
                            "slaRisk": {
                              "type": "boolean",
                              "description": "Set this to True when the case smells like churn/escalation."
                            },
                            "summary": {
                              "type": "string",
                              "description": "Provide one line for the queue view."
                            },
                            "suggestedFirstResponse": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "priority": "urgent",
                  "category": "bug",
                  "team": "payments",
                  "sentiment": "frustrated",
                  "slaRisk": true,
                  "summary": "Checkout erroring 2h in production — revenue impact.",
                  "suggestedFirstResponse": "Acknowledge the outage, confirm that engineers are engaged, and promise updates every 30 minutes.",
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1815
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/minutes": {
      "post": {
        "operationId": "minutes",
        "summary": "Meeting minutes",
        "x-pricing": {
          "credits": 6,
          "usd": 0.06,
          "currency": "USD"
        },
        "description": "ParseRail turns a meeting transcript into clean minutes. The minutes include a summary, decisions made, action items with owners, and open questions.\n\nCost: 6 credits ($0.06) — charged only on success.",
        "tags": [
          "Meeting minutes"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "transcript"
                ],
                "properties": {
                  "transcript": {
                    "type": "string",
                    "description": "The meeting transcript."
                  },
                  "attendees": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "transcript": "<45-minute product sync transcript…>",
                "attendees": [
                  "Priya",
                  "Marco",
                  "Dana"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "title",
                            "summary",
                            "decisions",
                            "actionItems",
                            "openQuestions"
                          ],
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "summary": {
                              "type": "string"
                            },
                            "decisions": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "actionItems": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "task"
                                ],
                                "properties": {
                                  "task": {
                                    "type": "string"
                                  },
                                  "owner": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "due": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "openQuestions": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "title": "Product sync — launch readiness",
                  "summary": "The launch moves to Friday, behind the payment fix.",
                  "decisions": [
                    "Launch Friday, not Thursday"
                  ],
                  "actionItems": [
                    {
                      "task": "Deploy duplicate-charge fix",
                      "owner": "Priya",
                      "due": "2026-07-10"
                    }
                  ],
                  "openQuestions": [
                    "Does the churn dashboard need the new events?"
                  ],
                  "usage": {
                    "credits": 6,
                    "balanceRemaining": 1809
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/outreach": {
      "post": {
        "operationId": "outreach",
        "summary": "Outreach sequence",
        "x-pricing": {
          "credits": 6,
          "usd": 0.06,
          "currency": "USD"
        },
        "description": "ParseRail turns an enriched lead and what you sell into a personalized outreach sequence. The sequence references what actually makes the lead a fit.\n\nCost: 6 credits ($0.06) — charged only on success.",
        "tags": [
          "Outreach sequence"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "lead",
                  "product"
                ],
                "properties": {
                  "lead": {
                    "type": "string",
                    "description": "Provide who you're writing to: an enriched profile (e.g. /v1/enrich output) or notes."
                  },
                  "product": {
                    "type": "string",
                    "description": "Describe what you sell and its value proposition."
                  },
                  "sender": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "role": {
                        "type": "string"
                      },
                      "company": {
                        "type": "string"
                      }
                    }
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "linkedin"
                    ],
                    "default": "email"
                  },
                  "steps": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5,
                    "default": 3
                  }
                }
              },
              "example": {
                "lead": "{…/v1/enrich output for brightco.io…}",
                "product": "Verbatim meeting notes generated automatically",
                "sender": {
                  "name": "Isaiah",
                  "role": "Founder",
                  "company": "Compound Labs"
                },
                "steps": 2
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "sequence",
                            "personalizationPoints"
                          ],
                          "properties": {
                            "sequence": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "day",
                                  "message"
                                ],
                                "properties": {
                                  "day": {
                                    "type": "integer"
                                  },
                                  "subject": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "message": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "personalizationPoints": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Provide the lead-specific facts that the copy uses."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "sequence": [
                    {
                      "day": 0,
                      "subject": "Notes for BrightCo's client calls",
                      "message": "Hi Dana. BrightCo runs 20+ client calls a week…"
                    },
                    {
                      "day": 4,
                      "subject": null,
                      "message": "Bumping this — one line…"
                    }
                  ],
                  "personalizationPoints": [
                    "Agency model = heavy client-call volume",
                    "Recent hiring spree in account management"
                  ],
                  "usage": {
                    "credits": 6,
                    "balanceRemaining": 1803
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/review-reply": {
      "post": {
        "operationId": "review-reply",
        "summary": "Review response",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail evaluates a customer review and returns a brand-safe public response, the issues to log, and whether human escalation is needed.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "Review response"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "review"
                ],
                "properties": {
                  "review": {
                    "type": "string",
                    "description": "The customer review text."
                  },
                  "rating": {
                    "type": "number",
                    "description": "Star rating if known."
                  },
                  "business": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "voice": {
                        "type": "string",
                        "description": "Brand voice notes."
                      }
                    }
                  },
                  "resolution": {
                    "type": "string",
                    "description": "State what you can offer, e.g. \"replacement or refund\"."
                  }
                }
              },
              "example": {
                "review": "Two stars. The product is fine, but delivery took three weeks and nobody answered my emails.",
                "rating": 2,
                "business": {
                  "name": "Loomworks",
                  "voice": "warm, direct, no corporate speak"
                },
                "resolution": "free shipping on next order"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "reply",
                            "sentiment",
                            "issues",
                            "escalate"
                          ],
                          "properties": {
                            "reply": {
                              "type": "string",
                              "description": "Public response, brand-safe."
                            },
                            "sentiment": {
                              "type": "string"
                            },
                            "issues": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Product/ops issues worth logging."
                            },
                            "escalate": {
                              "type": "boolean",
                              "description": "Set this to True when a human should take over."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "reply": "We caused that. Three weeks is too long, and the lack of replies made it worse…",
                  "sentiment": "negative",
                  "issues": [
                    "Shipping delay (3 weeks)",
                    "Support unresponsive via email"
                  ],
                  "escalate": false,
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1800
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/moderate": {
      "post": {
        "operationId": "moderate",
        "summary": "Content moderation",
        "x-pricing": {
          "credits": 2,
          "usd": 0.02,
          "currency": "USD"
        },
        "description": "ParseRail evaluates text or an image against YOUR policy and returns allow, review, or block with the categories and excerpts that drove the call.\n\nCost: 2 credits ($0.02) — charged only on success.",
        "tags": [
          "Content moderation"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Provide text and/or an image.",
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "image": {
                    "type": "object",
                    "properties": {
                      "data": {
                        "type": "string",
                        "description": "Base64."
                      },
                      "mimeType": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "data",
                      "mimeType"
                    ]
                  },
                  "imageUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "policy": {
                    "type": "string",
                    "description": "Provide YOUR rules in plain words, e.g. \"no medical claims, no competitor names\". These rules add to the safety baseline."
                  }
                }
              },
              "example": {
                "text": "This supplement claims to cure anxiety in 3 days and guarantees the result. DM me for a discount code.",
                "policy": "No medical claims. No off-platform solicitation."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "flagged",
                            "decision",
                            "categories",
                            "rationale"
                          ],
                          "properties": {
                            "flagged": {
                              "type": "boolean"
                            },
                            "decision": {
                              "type": "string",
                              "enum": [
                                "allow",
                                "review",
                                "block"
                              ]
                            },
                            "categories": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "category",
                                  "severity"
                                ],
                                "properties": {
                                  "category": {
                                    "type": "string"
                                  },
                                  "severity": {
                                    "type": "string",
                                    "enum": [
                                      "low",
                                      "medium",
                                      "high"
                                    ]
                                  },
                                  "excerpt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "The offending span, when text."
                                  }
                                }
                              }
                            },
                            "rationale": {
                              "type": "string"
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "flagged": true,
                  "decision": "block",
                  "categories": [
                    {
                      "category": "medical claim",
                      "severity": "high",
                      "excerpt": "cures anxiety in 3 days, guaranteed"
                    },
                    {
                      "category": "off-platform solicitation",
                      "severity": "medium",
                      "excerpt": "DM me for a discount code"
                    }
                  ],
                  "rationale": "The direct cure claim violates the medical-claims rule. The DM solicitation violates platform policy.",
                  "usage": {
                    "credits": 2,
                    "balanceRemaining": 1798
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/rewrite": {
      "post": {
        "operationId": "rewrite",
        "summary": "Brand-voice rewrite",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail rewrites any copy in your brand voice. You describe the voice or paste a sample, and ParseRail returns the rewrite and what changed.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "Brand-voice rewrite"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "voice": {
                    "type": "string",
                    "description": "Describe the voice or paste a sample of it."
                  },
                  "goal": {
                    "type": "string",
                    "description": "e.g. \"tighter, more confident\"."
                  },
                  "audience": {
                    "type": "string"
                  },
                  "length": {
                    "type": "string",
                    "enum": [
                      "shorter",
                      "same",
                      "longer"
                    ],
                    "default": "same"
                  }
                }
              },
              "example": {
                "text": "The new feature is available to all users.",
                "voice": "Confident, plain-spoken, a little wry. Short sentences.",
                "goal": "sound human",
                "length": "same"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "rewritten",
                            "changes"
                          ],
                          "properties": {
                            "rewritten": {
                              "type": "string"
                            },
                            "changes": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "What was changed and why."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "rewritten": "It's live. Every account has the new feature as of today. Go try it.",
                  "changes": [
                    "Dropped the press-release opener",
                    "Active voice, shorter sentences"
                  ],
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1795
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/product-copy": {
      "post": {
        "operationId": "product-copy",
        "summary": "Product copy",
        "x-pricing": {
          "credits": 5,
          "usd": 0.05,
          "currency": "USD"
        },
        "description": "ParseRail turns specs and an audience into listing-ready titles, bullets, a description, and SEO keywords for each channel.\n\nCost: 5 credits ($0.05) — charged only on success.",
        "tags": [
          "Product copy"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product"
                ],
                "properties": {
                  "product": {
                    "type": "object",
                    "required": [
                      "name"
                    ],
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "features": {
                        "type": "string",
                        "description": "Specs / features, any format."
                      },
                      "audience": {
                        "type": "string"
                      },
                      "keywords": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "amazon",
                      "shopify",
                      "generic"
                    ],
                    "default": "generic"
                  }
                }
              },
              "example": {
                "product": {
                  "name": "Meridian standing desk",
                  "features": "The product has dual motors, a 48x30 bamboo top, memory presets and a 300lb capacity.",
                  "audience": "home-office workers",
                  "keywords": [
                    "standing desk",
                    "adjustable desk"
                  ]
                },
                "channel": "shopify"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "titles",
                            "bullets",
                            "description",
                            "seoKeywords"
                          ],
                          "properties": {
                            "titles": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Ranked title options."
                            },
                            "bullets": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "description": {
                              "type": "string"
                            },
                            "seoKeywords": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "titles": [
                    "Meridian Standing Desk with dual motors, a bamboo top and four memory heights"
                  ],
                  "bullets": [
                    "Dual motors lift 300 lbs without the wobble",
                    "48\"×30\" solid bamboo top"
                  ],
                  "description": "The Meridian desk needs no attention during use…",
                  "seoKeywords": [
                    "standing desk",
                    "adjustable height desk",
                    "bamboo standing desk"
                  ],
                  "usage": {
                    "credits": 5,
                    "balanceRemaining": 1790
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/describe": {
      "post": {
        "operationId": "describe",
        "summary": "Image description",
        "x-pricing": {
          "credits": 3,
          "usd": 0.03,
          "currency": "USD"
        },
        "description": "ParseRail evaluates an image and returns accessible alt text, a caption, tags, and any text found inside it. One call supports accessibility and catalogs.\n\nCost: 3 credits ($0.03) — charged only on success.",
        "tags": [
          "Image description"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Provide image or imageUrl.",
                "properties": {
                  "image": {
                    "type": "object",
                    "properties": {
                      "data": {
                        "type": "string",
                        "description": "Base64."
                      },
                      "mimeType": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "data",
                      "mimeType"
                    ]
                  },
                  "imageUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "purpose": {
                    "type": "string",
                    "enum": [
                      "alt",
                      "caption",
                      "product",
                      "detailed"
                    ],
                    "default": "alt"
                  }
                }
              },
              "example": {
                "imageUrl": "https://…/product-shot.jpg",
                "purpose": "product"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "altText",
                            "caption",
                            "tags"
                          ],
                          "properties": {
                            "altText": {
                              "type": "string",
                              "description": "Concise, accessibility-grade."
                            },
                            "caption": {
                              "type": "string"
                            },
                            "detailed": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Long-form description when purpose=detailed."
                            },
                            "tags": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "embeddedText": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "Return any text found inside the image."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "altText": "Matte-black standing desk with a bamboo top in a sunlit home office",
                  "caption": "The Meridian desk at full height in morning light",
                  "detailed": null,
                  "tags": [
                    "standing desk",
                    "bamboo",
                    "home office"
                  ],
                  "embeddedText": null,
                  "usage": {
                    "credits": 3,
                    "balanceRemaining": 1787
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/research": {
      "post": {
        "operationId": "research",
        "summary": "Research brief",
        "x-pricing": {
          "credits": 50,
          "usd": 0.5,
          "currency": "USD"
        },
        "description": "ParseRail researches a company or topic and returns a multi-source, citation-backed brief. The brief states what it is, what changed lately, and what matters. ParseRail performs the research on the web.\n\nCost: 50 credits ($0.50) — charged only on success.",
        "tags": [
          "Research brief"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string",
                    "description": "Name the company, topic, or question to research."
                  },
                  "focus": {
                    "type": "string",
                    "description": "State what matters to you, e.g. \"pricing changes and funding\"."
                  },
                  "depth": {
                    "type": "string",
                    "enum": [
                      "standard",
                      "deep"
                    ],
                    "default": "standard",
                    "description": "deep reads more sources."
                  }
                }
              },
              "example": {
                "query": "brightco.io",
                "focus": "funding, pricing changes, hiring signals"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "brief",
                            "findings",
                            "sources"
                          ],
                          "properties": {
                            "brief": {
                              "type": "string",
                              "description": "Return the synthesized answer in a few paragraphs."
                            },
                            "findings": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "finding",
                                  "sourceIndexes"
                                ],
                                "properties": {
                                  "finding": {
                                    "type": "string"
                                  },
                                  "sourceIndexes": {
                                    "type": "array",
                                    "items": {
                                      "type": "integer"
                                    },
                                    "description": "Indexes into sources[]."
                                  }
                                }
                              }
                            },
                            "sources": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "url",
                                  "title"
                                ],
                                "properties": {
                                  "url": {
                                    "type": "string"
                                  },
                                  "title": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "brief": "BrightCo is a 40-person client-services platform that raised an $8M Series A in March…",
                  "findings": [
                    {
                      "finding": "BrightCo raised an $8M Series A led by Foundry in March 2026",
                      "sourceIndexes": [
                        0,
                        2
                      ]
                    },
                    {
                      "finding": "BrightCo moved its pricing page from seats to usage tiers in May.",
                      "sourceIndexes": [
                        1
                      ]
                    }
                  ],
                  "sources": [
                    {
                      "url": "https://techcrunch.com/…",
                      "title": "BrightCo raised $8M…"
                    },
                    {
                      "url": "https://brightco.io/pricing",
                      "title": "BrightCo pricing"
                    }
                  ],
                  "usage": {
                    "credits": 50,
                    "balanceRemaining": 1737
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/screen": {
      "post": {
        "operationId": "screen",
        "summary": "Lead screening",
        "x-pricing": {
          "credits": 10,
          "usd": 0.1,
          "currency": "USD"
        },
        "description": "ParseRail evaluates a lead against your ICP criteria and returns a web-grounded qualification verdict. The verdict includes evidence for and against.\n\nCost: 10 credits ($0.10) — charged only on success.",
        "tags": [
          "Lead screening"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "lead",
                  "criteria"
                ],
                "properties": {
                  "lead": {
                    "type": "string",
                    "description": "Provide the company domain, name, or a pasted profile."
                  },
                  "criteria": {
                    "type": "string",
                    "description": "State your ICP in plain words, e.g. \"B2B SaaS, 20-200 employees, US, sells to finance teams\"."
                  }
                }
              },
              "example": {
                "lead": "brightco.io",
                "criteria": "The target is a US-based B2B SaaS company or agency with 20-200 people that runs client meetings at volume."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "verdict",
                            "score",
                            "evidenceFor",
                            "evidenceAgainst"
                          ],
                          "properties": {
                            "verdict": {
                              "type": "string",
                              "enum": [
                                "qualified",
                                "maybe",
                                "disqualified"
                              ]
                            },
                            "score": {
                              "type": "number",
                              "description": "0–1 fit."
                            },
                            "evidenceFor": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "evidenceAgainst": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "profile": {
                              "type": "object",
                              "additionalProperties": true,
                              "description": "State what we learned about the lead."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "verdict": "qualified",
                  "score": 0.86,
                  "evidenceFor": [
                    "~40 employees (LinkedIn)",
                    "US HQ, Denver",
                    "Agency model — client calls are the core motion"
                  ],
                  "evidenceAgainst": [
                    "BrightCo recently switched tooling and may be locked into a contract."
                  ],
                  "profile": {
                    "name": "BrightCo",
                    "employees": "~40",
                    "hq": "Denver, CO"
                  },
                  "usage": {
                    "credits": 10,
                    "balanceRemaining": 1727
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/transcribe": {
      "post": {
        "operationId": "transcribe",
        "summary": "Transcription",
        "x-pricing": {
          "credits": 10,
          "usd": 0.1,
          "currency": "USD"
        },
        "deprecated": true,
        "description": "ParseRail turns an audio recording into accurate text with speakers and paragraph timestamps. It supports meetings, calls, and voice notes.\n\nCost: 10 credits ($0.10) — charged only on success.\n\n**Paused since 2026-08-19.** Calls return `503 inference_unavailable` and are never charged. Audio transcription needs a multimodal provider that we can run under a no-training agreement. Every other endpoint already runs under those terms. ParseRail has paused audio transcription instead of serving it under terms that would contradict our privacy commitment.",
        "tags": [
          "Transcription"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Provide audio { data, mimeType } or audioUrl.",
                "properties": {
                  "audio": {
                    "type": "object",
                    "properties": {
                      "data": {
                        "type": "string",
                        "description": "Base64 audio."
                      },
                      "mimeType": {
                        "type": "string",
                        "example": "audio/mp3"
                      }
                    },
                    "required": [
                      "data",
                      "mimeType"
                    ]
                  },
                  "audioUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "diarize": {
                    "type": "boolean",
                    "default": true,
                    "description": "Label speakers."
                  },
                  "language": {
                    "type": "string",
                    "description": "BCP-47 hint, e.g. \"en\"."
                  }
                }
              },
              "example": {
                "audioUrl": "https://…/standup.mp3",
                "diarize": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "text",
                            "segments"
                          ],
                          "properties": {
                            "text": {
                              "type": "string",
                              "description": "The full transcript."
                            },
                            "segments": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "text"
                                ],
                                "properties": {
                                  "speaker": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "e.g. \"Speaker 1\"."
                                  },
                                  "start": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "MM:SS."
                                  },
                                  "text": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "language": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "text": "Alright, quick standup. Priya, want to start? …",
                  "segments": [
                    {
                      "speaker": "Speaker 1",
                      "start": "00:00",
                      "text": "Alright, quick standup. Priya, want to start?"
                    },
                    {
                      "speaker": "Speaker 2",
                      "start": "00:04",
                      "text": "Sure. The duplicate-charge fix is reviewed…"
                    }
                  ],
                  "language": "en",
                  "usage": {
                    "credits": 10,
                    "balanceRemaining": 1717
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/memory": {
      "post": {
        "operationId": "memory",
        "summary": "Agent memory",
        "x-pricing": {
          "credits": 2,
          "usd": 0.02,
          "currency": "USD"
        },
        "description": "ParseRail stores, searches, and forgets memories for your agents in your own namespace. It provides semantic recall without a vector DB to run.\n\nCost: 2 credits ($0.02) — charged only on success.",
        "tags": [
          "Agent memory"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "op"
                ],
                "properties": {
                  "op": {
                    "type": "string",
                    "enum": [
                      "store",
                      "search",
                      "forget"
                    ],
                    "description": "The operation."
                  },
                  "namespace": {
                    "type": "string",
                    "description": "Provide your partition key, such as an agent id or a user id. It defaults to \"default\"."
                  },
                  "content": {
                    "type": "string",
                    "description": "store: the memory text."
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "For store:, provide attached metadata; recall returns it."
                  },
                  "query": {
                    "type": "string",
                    "description": "search: what to recall."
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 25,
                    "default": 5,
                    "description": "search: max results."
                  },
                  "id": {
                    "type": "string",
                    "description": "For forget:, provide the memory id, or omit it with namespace to wipe it."
                  }
                }
              },
              "example": {
                "op": "search",
                "namespace": "agent-42",
                "query": "what does the customer prefer for delivery?",
                "limit": 3
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "op"
                          ],
                          "properties": {
                            "op": {
                              "type": "string",
                              "enum": [
                                "store",
                                "search",
                                "forget"
                              ]
                            },
                            "id": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "description": "store: the new memory's id."
                            },
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "required": [
                                  "id",
                                  "content",
                                  "score"
                                ],
                                "properties": {
                                  "id": {
                                    "type": "string"
                                  },
                                  "content": {
                                    "type": "string"
                                  },
                                  "score": {
                                    "type": "number",
                                    "description": "Semantic similarity 0–1."
                                  },
                                  "metadata": {
                                    "type": "object",
                                    "additionalProperties": true
                                  },
                                  "createdAt": {
                                    "type": "string"
                                  }
                                }
                              },
                              "description": "search: the recalled memories."
                            },
                            "deleted": {
                              "type": [
                                "integer",
                                "null"
                              ],
                              "description": "forget: how many were removed."
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "op": "search",
                  "results": [
                    {
                      "id": "mem_8f3a…",
                      "content": "The customer prefers evening deliveries after 6pm and requires no signature.",
                      "score": 0.91,
                      "metadata": {
                        "source": "ticket-5561"
                      },
                      "createdAt": "2026-07-01T18:22:00Z"
                    }
                  ],
                  "usage": {
                    "credits": 2,
                    "balanceRemaining": 1715
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/image": {
      "post": {
        "operationId": "image",
        "summary": "Image generation",
        "x-pricing": {
          "credits": 10,
          "usd": 0.1,
          "currency": "USD"
        },
        "description": "ParseRail turns a prompt into a production-ready image. It supports marketing visuals, product scenes, and consistent brand imagery.\n\nCost: 10 credits ($0.10) — charged only on success.",
        "tags": [
          "Image generation"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "description": "What to generate."
                  },
                  "style": {
                    "type": "string",
                    "description": "Provide style notes, e.g. \"editorial photography, warm light\"."
                  },
                  "aspectRatio": {
                    "type": "string",
                    "enum": [
                      "1:1",
                      "16:9",
                      "9:16",
                      "4:3",
                      "3:4"
                    ],
                    "default": "1:1"
                  }
                }
              },
              "example": {
                "prompt": "A minimal hero image of a bamboo standing desk in warm morning light",
                "style": "editorial photography",
                "aspectRatio": "16:9"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "image",
                            "mimeType"
                          ],
                          "properties": {
                            "image": {
                              "type": "string",
                              "description": "Base64 image bytes."
                            },
                            "mimeType": {
                              "type": "string",
                              "example": "image/png"
                            },
                            "revisedPrompt": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "image": "<base64…>",
                  "mimeType": "image/png",
                  "revisedPrompt": null,
                  "usage": {
                    "credits": 10,
                    "balanceRemaining": 1705
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/speak": {
      "post": {
        "operationId": "speak",
        "summary": "Text to speech",
        "x-pricing": {
          "credits": 5,
          "usd": 0.05,
          "currency": "USD"
        },
        "description": "ParseRail turns text into natural speech audio ready to embed. It supports voice notes, IVR lines, and narration.\n\nCost: 5 credits ($0.05) — charged only on success.",
        "tags": [
          "Text to speech"
        ],
        "parameters": [
          {
            "name": "ParseRail-Dry-Run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            },
            "description": "Send `1` to dry-run the call. ParseRail runs auth, the throttle, body validation and the balance precheck. It returns 200 with the cost and the status a live call would get. No model runs and nothing is charged, so a key with a zero balance works. Dry runs count against the per-key rate limit."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Key for one logical operation. Same body replays the result for 24 hours; a different body with the same key returns 409.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[!-~]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "voice": {
                    "type": "string",
                    "description": "Provide a voice name, or omit it for the default narrator."
                  },
                  "pace": {
                    "type": "string",
                    "enum": [
                      "slow",
                      "normal",
                      "fast"
                    ],
                    "default": "normal"
                  }
                }
              },
              "example": {
                "text": "Your order has shipped and will arrive Thursday.",
                "pace": "normal"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call succeeded. The response contains result fields and a usage envelope. With `ParseRail-Dry-Run: 1` the body is a DryRun object instead.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "allOf": [
                        {
                          "type": "object",
                          "required": [
                            "audio",
                            "mimeType"
                          ],
                          "properties": {
                            "audio": {
                              "type": "string",
                              "description": "Base64 audio bytes."
                            },
                            "mimeType": {
                              "type": "string",
                              "example": "audio/wav"
                            },
                            "durationSec": {
                              "type": [
                                "number",
                                "null"
                              ]
                            }
                          }
                        },
                        {
                          "type": "object",
                          "required": [
                            "usage"
                          ],
                          "properties": {
                            "usage": {
                              "$ref": "#/components/schemas/Usage"
                            }
                          }
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/DryRun"
                    }
                  ]
                },
                "example": {
                  "audio": "<base64…>",
                  "mimeType": "audio/wav",
                  "durationSec": 3.4,
                  "usage": {
                    "credits": 5,
                    "balanceRemaining": 1700
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "`insufficient_credits`: the balance cannot cover the call. `spend_cap_reached`: the key has reached its monthly cap. Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "summary": "Poll an async job",
        "description": "This endpoint reports the status of a job created with `async: true` and its result once finished. The endpoint is scoped to your account. You can read only your own jobs. The endpoint never charges credits.",
        "tags": [
          "Async & webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The `jobId` returned by the 202."
          }
        ],
        "responses": {
          "200": {
            "description": "The job's current state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                },
                "example": {
                  "jobId": "6f1d2c8e-3a5b-4c11-9f0e-2b7d5a9c1e42",
                  "endpoint": "parse",
                  "status": "succeeded",
                  "result": {
                    "fields": {
                      "total": "1240.00"
                    },
                    "usage": {
                      "credits": 5,
                      "balanceRemaining": 1995
                    }
                  },
                  "createdAt": "2026-07-09T18:00:00.000Z",
                  "updatedAt": "2026-07-09T18:00:12.000Z",
                  "requestId": "req_8c2a1f"
                }
              }
            }
          },
          "400": {
            "description": "No such job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your API key, e.g. `Authorization: Bearer ksk_live_…`. Mint one in the dashboard."
      }
    },
    "schemas": {
      "Usage": {
        "type": "object",
        "properties": {
          "credits": {
            "type": "integer",
            "description": "Credits burned by this call."
          },
          "balanceRemaining": {
            "type": "integer",
            "description": "Wallet balance after the charge."
          }
        },
        "required": [
          "credits",
          "balanceRemaining"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "unauthorized",
                  "rate_limited",
                  "insufficient_credits",
                  "spend_cap_reached",
                  "unprocessable",
                  "inference_unavailable"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        }
      },
      "JobAccepted": {
        "type": "object",
        "required": [
          "jobId",
          "status",
          "requestId"
        ],
        "properties": {
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued"
            ]
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "Job": {
        "type": "object",
        "required": [
          "jobId",
          "endpoint",
          "status",
          "createdAt",
          "updatedAt",
          "requestId"
        ],
        "properties": {
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "endpoint": {
            "type": "string",
            "description": "The job runs with this endpoint key."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed"
            ],
            "description": "Terminal states are `succeeded` and `failed`."
          },
          "result": {
            "type": "object",
            "additionalProperties": true,
            "description": "This field is present only when `status` is `succeeded`. It contains the same body the sync call would have returned, including `usage`."
          },
          "error": {
            "type": "string",
            "description": "This field is present only when `status` is `failed`. No credits were charged."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "DryRun": {
        "type": "object",
        "description": "A dry run: auth, the per-key throttle, body validation and the balance precheck ran. No model ran and nothing was charged.",
        "properties": {
          "dryRun": {
            "type": "boolean",
            "const": true
          },
          "valid": {
            "type": "boolean",
            "const": true,
            "description": "The body passed validation. An invalid body returns 400 instead."
          },
          "endpoint": {
            "type": "string"
          },
          "wouldCharge": {
            "type": "integer",
            "description": "Credits a successful live call would charge."
          },
          "balance": {
            "type": "integer",
            "description": "Your wallet balance now."
          },
          "liveStatus": {
            "type": "integer",
            "enum": [
              200,
              202,
              402
            ],
            "description": "The status a live call with this body would get: 402 when the balance or the key's monthly cap cannot cover it, 202 for `async: true`, else 200."
          },
          "keyCapRemaining": {
            "type": "integer",
            "description": "Present when the key carries a monthly cap: credits left under it this month."
          },
          "usage": {
            "$ref": "#/components/schemas/Usage"
          },
          "requestId": {
            "type": "string"
          }
        },
        "required": [
          "dryRun",
          "valid",
          "endpoint",
          "wouldCharge",
          "balance",
          "liveStatus",
          "usage",
          "requestId"
        ]
      }
    }
  }
}