Docs
Team and Finance Control plans
Verify before the agent pays. Plans are for finance teams that want controls and audit evidence around agent payments. For pay-as-you-go, use a pack.
Plans
| Team | Finance Control | |
|---|---|---|
| Price | $199/mo or $1,990/yr | $399/mo or $3,990/yr |
| Included calls | 50,000 / month | 150,000 / month |
| Overage | $0.003 / call (opt-in) | $0.0025 / call (opt-in) |
| API keys | 5 | Unlimited |
| Policy sets / entities | 1 | Up to 5 |
| Receipt retention | 1 year | 7 years |
| Content history (opt-in) | Up to 365 days | Up to 365 days |
| Auditor export bundle | No | Yes |
| Support | Priority email (1 business day) |
In both plans
- 15-minute single-use pass tokens, bound to the exact invoice, amount and vendor
- Linked, tamper-evident audit receipts
- Policy rules: amount caps, vendor allowlist, second approval, required fields
- Rule-only decisions don't count against included calls
- Opt-in content history: keep a call's request and result for 30, 90 or 365 days, replay it with its signed receipt, delete it any time
- Hard stop at the limit by default. Overage is opt-in and capped at 2× included calls.
- Renews automatically each month or year until cancelled. Cancel anytime at /plans/cancel/ or in PayPal; access continues to the end of the paid period.
Subscribe
Use the form on pricing, or call the API. You do not need an API key first:
curl -s https://screwtape.ai/v1/plans/team/subscribe \
-H "Content-Type: application/json" \
-d '{"interval":"month","email":"you@company.com","accept_terms":true,"business_use":true}'email is optional; without it the PayPal email is used. When PayPal confirms the subscription, the plan account and its API key are created. The key is shown once at key_pickup_url (the page PayPal returns you to), for up to 48 hours. Screwtape does not email keys. To put the plan on a key you already have, send it as Authorization: Bearer $SCREWTAPE_API_KEY instead.
accept_terms confirms you accept the Terms, including automatic renewal until you cancel. business_use confirms the plan is for business use. Both are required.
The response has an approval_url. Approve the subscription on PayPal. The plan turns on when PayPal confirms it. Need more keys on a Team or Finance Control account? Email screwtapedev@gmail.com. plan is team or finance_control; interval is month or year.
Pass tokens
When a judge or duplicate check passes, a plan key can get a 15-minute, single-use pass token bound to the invoice id, amount, currency and vendor. The payment step calls POST /v1/pass/verify with the token and the payment it is about to make. A mismatch, a second use or an expired token is refused.
Limits and billing
- At the included calls, calls stop with a clear error unless overage is turned on for the account. Overage is capped at 2× included calls.
- Calls decided only by policy rules, with no model call, are receipted but not counted.
- If a renewal payment fails, the plan stays on for 7 days while PayPal retries.
- Plans renew automatically until cancelled. Cancel at any time at /plans/cancel/, with
POST /v1/plans/cancel, or in PayPal. Access continues to the end of the paid period.
Invoice decisions (decision_version 2)
Plan keys can ask POST /v1/judge (and POST /v1/duplicate) for an invoice decision instead of a pass or fail verdict. Send policy_id and decision_version 2. The policy must set rules.max_amount. Accounts created on or after 2026-12-23 get version 2 by default when they send a policy_id.
Send exactly one of invoice (structured fields), invoice_text (plain text) or agent_output. task is optional and defaults to "Check this invoice against the payment policy." Without decision_version 2, invoice, invoice_text and po return 400 invalid_request.
The response has decision (approve, needs_review, deny or retry), decision_source (rules, or rules+model when a model added triage), the rules that ran, review_id when a review was opened, and the usual reasons and receipt. deny and retry come from the rules alone and are not billed. approve and needs_review are billed as one normal call. needs_review opens a review for a person.
- invoice: vendor, invoice_number, po_number, currency (3 letters), issue_date (YYYY-MM-DD), line_items (description, qty, unit_price, amount), subtotal, tax, total. Amounts are numbers or decimal strings with up to 6 decimals. At most 2,000 line items; the whole body is at most 256 KB.
- po (optional): po_number, vendor, currency, total. Checked against the invoice.
curl -s https://screwtape.ai/v1/judge \
-H "Authorization: Bearer $SCREWTAPE_KEY" -H "Content-Type: application/json" \
-d '{"policy_id":"ap-default","decision_version":2,
"invoice":{"vendor":"Acme Ltd","invoice_number":"INV-1042","currency":"USD","issue_date":"2026-10-01",
"line_items":[{"description":"Support","qty":1,"unit_price":"1200.00","amount":"1200.00"}],
"subtotal":"1200.00","tax":"0","total":"1200.00"},
"po":{"po_number":"PO-77","vendor":"Acme Ltd","currency":"USD","total":"1200.00"}}'invoice_text: plain-text invoices
invoice_text is a string of at most 5,000 characters. The worker reads vendor, invoice number, currency, line items, subtotal, tax and total from it with fixed parsing rules. No model reads the text, and the text is not stored or signed: only its SHA-256 goes into the receipt. The response has extraction: "deterministic".
Longer text returns 413 with error.code payload_too_large and the message "invoice_text takes at most 5000 characters. Send larger invoices as structured invoice fields." For bigger invoices, send the structured invoice fields instead. They have no character limit (up to 2,000 line items and a 256 KB body) and are read exactly.
If the text does not reconcile (two different totals, line items that do not add up, or a missing vendor, currency or total), the decision is needs_review with error_type extraction_unreconciled. Text that cannot be read is never denied on that basis; a person reviews it. Text that reconciles goes through the policy like a structured invoice, so a total over max_amount is still denied.
curl -s https://screwtape.ai/v1/judge \
-H "Authorization: Bearer $SCREWTAPE_KEY" -H "Content-Type: application/json" \
-d '{"policy_id":"ap-default","decision_version":2,"invoice_text":"Acme Ltd\nInvoice INV-1042\nCurrency USD\nTotal 1200.00"}'Own model key (X-Model-Key)
On a needs_review decision, a policy with model_triage set asks a model for a short explanation. A model can never loosen a decision. You can have that triage run on your own model account by sending these headers with a decision_version 2 call that has a policy_id. Without both, X-Model-Key returns 400: "X-Model-Key works only with decision_version 2 and a policy_id."
Your key is used for that one request only. It is never stored, logged, signed or returned in a response. The receipt records only the provider host and the model id.
If your provider fails, times out (15 seconds) or returns something unusable, the decision stays the rules decision, needs_review, with decision_source rules. The call does not fall back to our model. An own-key call is billed as one normal call, the same as any approve or needs_review.
Own-key headers are not available over MCP. The MCP server ignores X-Model-* headers on every tool. Use the HTTP API.
- X-Model-Key (required for this feature): 8 to 512 printable characters.
- X-Model-Provider (optional): groq (default) or openai-compatible.
- X-Model-Base-URL: required for openai-compatible, and must be one of https://api.groq.com/openai/v1, https://api.openai.com/v1, https://api.together.xyz/v1, https://api.fireworks.ai/inference/v1, https://openrouter.ai/api/v1, https://api.mistral.ai/v1, https://api.deepseek.com/v1. groq uses https://api.groq.com/openai/v1.
- X-Model-Id (optional): 1 to 120 letters, digits, . _ : / or -. groq defaults to openai/gpt-oss-120b.
curl -s https://screwtape.ai/v1/judge \
-H "Authorization: Bearer $SCREWTAPE_KEY" -H "Content-Type: application/json" \
-H "X-Model-Key: $YOUR_GROQ_KEY" \
-d '{"policy_id":"ap-default","decision_version":2,"invoice":{...}}'Evidence and replay
Turn evidence on per policy with evidence: {"enabled": true, "retain_days": 90, "store_vendor_name": false}. retain_days is 1 to 400 (default 90). Each approve or needs_review then keeps one small record: the fields the rules read, the policy version and the rule results. It keeps no line descriptions, addresses or bank details, and the vendor is a keyed hash unless store_vendor_name is true. The record's SHA-256 is signed into the receipt as evidence_sha256. deny and retry keep no evidence.
Evidence counts toward the content history quota and is included in GET /v1/retention (export) and DELETE /v1/retention (erase). When the quota is full, evidence is skipped; the decision is never blocked.
POST /v1/receipts/{receipt_id}/replay re-runs the rules on the stored record. policy is original (the policy version used at the time, the default) or current. Optional document is the original body (for example {"invoice": {...}}) to prove it is the same document. The response has original, replayed, match, diffs, model_part ("recorded, not re-run" or "no model ran"), document_match and a signed replay_receipt. A model is never called again. Replay needs a plan key and is not billed.
DELETE /v1/receipts/{receipt_id}/evidence deletes the record and returns {"deleted": true}. The signed receipt is kept.
- 400 invalid_request: bad receipt id or body.
- 404 receipt_not_found, evidence_not_found (evidence was off, or the decision was deny or retry), policy_not_found.
- 410 evidence_deleted: deleted or expired; the receipt is kept.
- 409 evidence_tampered (record does not match the signed hash), document_mismatch, rules_version_unknown.
curl -s -X POST https://screwtape.ai/v1/receipts/$RECEIPT_ID/replay \
-H "Authorization: Bearer $SCREWTAPE_KEY" -H "Content-Type: application/json" \
-d '{"policy":"original"}'Questions: screwtapedev@gmail.com.
