Draft for review · Unreleased API · Not published
DRAFT DOCUMENTATION

Pactlyst.ai API docs

Score legal documents, get signed proof-of-scan receipts, and let AI assistants call the engine over MCP. This documentation describes an API that is still in development — the examples below show the draft interface, and anything marked planned may change before launch.

Base URL: https://djcmqtyenuvrtotmpfxl.supabase.co/functions/v1

On this page

  1. 5-minute quickstart
  2. Authentication
  3. POST /score-document
  4. Receipts & verification
  5. MCP server
  6. Idempotency
  7. Error codes
  8. Rate limits & quotas
  9. Privacy
  10. Pricing (planned)

5-minute quickstart

  1. Request an API key

    API keys aren’t self-serve yet. Request your key and we’ll email it as soon as Pactlyst.ai opens. Everything below assumes you have one — store it as an environment variable, e.g. PACTLYST_KEY.

  2. Score a document

    Send agreement text to score-document. You get back a 0–100 Pactlyst Score, a verdict, red flags, key terms, a plain-language explanation, and a signed attestation receipt.

    TERMINAL
    curl -X POST https://djcmqtyenuvrtotmpfxl.supabase.co/functions/v1/score-document \
      -H "Authorization: Bearer $PACTLYST_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "text": "Section 9 \u2014 Term. This agreement renews automatically for successive 12-month terms unless you give written notice at least 90 days before the renewal date.",
        "title": "Sample lease",
        "language": "Spanish"
      }'
  3. Verify the receipt

    Every score comes with a signed receipt. Anyone — your users, a counterparty, an auditor — can check it against the public attestation endpoint. No API key needed.

    TERMINAL
    curl -X POST https://djcmqtyenuvrtotmpfxl.supabase.co/functions/v1/attestation \
      -H "Content-Type: application/json" \
      -d '{
        "receipt": {
          "version": "pactlyst-attestation/v2",
          "score": 55,
          "verdict": "caution",
          "doc_sha256": "9f2c\u20264 hex chars\u2026",
          "document_version": "v3",
          "playbook_id": "pactlyst-standard",
          "playbook_version": "v1",
          "analysis_version": "gpt-4o-mini/prompt-v1",
          "findings_summary": {"high": 1, "medium": 2, "low": 1},
          "findings_sha256": "7d4e\u20264 hex chars\u2026",
          "limitations": [],
          "key_id": "key_abc123",
          "timestamp": "2026-10-01T22:00:00.000Z",
          "requesting_agent": "procurement-agent-7",
          "signature": "a1b2\u20264 hex chars\u2026"
        }
      }'
    
    # {"valid": true, "receipt": {"version": "pactlyst-attestation/v2", "score": 55, ...}}
    # {"valid": false, "reason": "signature_mismatch"}

Authentication

Authenticated endpoints expect your key as a Bearer token:

HEADER
Authorization: Bearer $PACTLYST_KEY
  • score-document and mcp require a key. Missing or unknown keys return 401 (missing_api_key / invalid_api_key); revoked keys return 403 (key_revoked).
  • attestation is public — verification needs no key, so receipts can be checked by anyone.
  • request-access is public — it only records key requests.

POST /score-document

Scores one agreement or clause. Request and response bodies are JSON (Content-Type: application/json).

Parameters

FieldTypeNotes
textstring, requiredThe agreement or clause text. Max 50,000 characters. Text that isn’t a legal document is rejected — never scored.
titlestring, optionalA label for the document, e.g. “Sample lease”.
languagestring, optionalExplanation language, e.g. "Spanish". Defaults to English.

Response fields (200)

FieldWhat it is
scoreInteger 0–100. Higher is better.
verdictsign | caution | dont_sign — computed server-side from the band rule below.
document_typeDetected document type, e.g. “Residential lease”.
summaryShort plain-language summary of the document.
flagsRed flags: { title, detail, severity: high | medium | low, quote? }. quote is the exact clause wording when available.
key_termsKey terms: { term, meaning, quote? }.
explanationPlain-language explanation of the score.
disclaimer“This score is information to help you understand a document — not legal advice. Pactlyst is not a lawyer. Verify anything important independently.”
receiptSigned attestation receipt — see Receipts & verification.
usage{ model, prompt_tokens, completion_tokens } — metering detail for the request.

The verdict band rule

The verdict is computed server-side from the score and the number of high-severity flags. The model’s own verdict is never used.

VerdictRule
signScore ≥ 70 and zero high-severity flags
dont_signScore < 40 or 2+ high-severity flags
cautionEverything else
EXAMPLE RESPONSE
{
  "score": 55,
  "verdict": "caution",
  "document_type": "Residential lease",
  "summary": "A 12-month lease that renews automatically unless you give 90 days' notice.",
  "flags": [
    { "title": "Automatic renewal", "detail": "Renews for 12 months unless you give 90 days' written notice.", "severity": "high", "quote": "This agreement renews automatically for successive 12-month terms\u2026" }
  ],
  "key_terms": [
    { "term": "Renewal notice window", "meaning": "You must act 90 days before renewal or you're locked in for a year." }
  ],
  "explanation": "Auto-renewal with a 90-day notice window is easy to miss \u2014 calendar the deadline the day you sign.",
  "disclaimer": "This score is information to help you understand a document \u2014 not legal advice. Pactlyst is not a lawyer. Verify anything important independently.",
  "receipt": { "version": "pactlyst-attestation/v2", "score": 55, "verdict": "caution", "doc_sha256": "9f2c\u2026", "document_version": "v3", "playbook_id": "pactlyst-standard", "playbook_version": "v1", "analysis_version": "gpt-4o-mini/prompt-v1", "findings_summary": { "high": 1, "medium": 2, "low": 1 }, "findings_sha256": "7d4e\u2026", "limitations": [], "key_id": "key_abc123", "timestamp": "2026-10-01T22:00:00.000Z", "requesting_agent": "procurement-agent-7", "signature": "a1b2\u2026" },
  "usage": { "model": "gpt-4o-mini", "prompt_tokens": 1204, "completion_tokens": 386 }
}

Receipts & verification

Every score returns a signed attestation receipt — a review record that lets an organization verify what an AI agent checked before it acted: the document version reviewed, the rules or playbook applied, the analysis version, the findings and limitations, the time of review, and the agent or workflow that requested it. Receipts are verified statelessly with HMAC-SHA256 over the canonical (sorted-key) JSON of the payload:

Receipt fieldWhat it is
versionpactlyst-attestation/v2 (v1 receipts remain verifiable during the transition)
scoreThe 0–100 score
verdictsign | caution | dont_sign
doc_sha256SHA-256 of the scored document text
document_versionCaller-supplied revision label for the exact document revision reviewed (e.g. v3); unspecified when not given — never invented
playbook_idRules applied — default pactlyst-standard; custom enterprise playbook ids allowed
playbook_versionPlaybook version — default v1 (the current band methodology)
analysis_versionModel + prompt version that produced the analysis (e.g. gpt-4o-mini/prompt-v1)
findings_summaryFinding counts by severity, e.g. {high: 2, medium: 3, low: 1}
findings_sha256SHA-256 of the full findings payload — binds the findings to the receipt without putting finding text in it
limitationsExplicit analysis limitations for this review (e.g. machine-translated explanation, omitted unverifiable quotes); [] when none — the field is never omitted
key_idID of the API key that scored it
timestampISO-8601 time of review
requesting_agentIdentifier of the agent or workflow that requested the review; unspecified when not given — never invented
signatureHMAC-SHA256 of the payload

The signature proves this record was not altered. It does not prove the analysis was correct or that the contract was safe to sign.

Receipts stay small by design: they carry finding counts plus a hash of the findings — never full finding text and never document text. Any change to any payload field invalidates the signature. Verify with POST /attestation (public, no auth):

TERMINAL
curl -X POST https://djcmqtyenuvrtotmpfxl.supabase.co/functions/v1/attestation \
  -H "Content-Type: application/json" \
  -d '{ "receipt": { "version": "pactlyst-attestation/v2", "score": 55, "verdict": "caution", "doc_sha256": "9f2c\u2026", "document_version": "v3", "playbook_id": "pactlyst-standard", "playbook_version": "v1", "analysis_version": "gpt-4o-mini/prompt-v1", "findings_summary": {"high": 1, "medium": 2, "low": 1}, "findings_sha256": "7d4e\u2026", "limitations": [], "key_id": "key_abc123", "timestamp": "2026-10-01T22:00:00.000Z", "requesting_agent": "procurement-agent-7", "signature": "a1b2\u2026" } }'

# valid:   {"valid": true, "receipt": {"version": "pactlyst-attestation/v2", "score": 55, ...}}
# invalid: {"valid": false, "reason": "signature_mismatch"}

Verification reasons include signature_mismatch, unknown_version, bad_score, bad_verdict, bad_doc_hash, bad_document_version, bad_playbook, bad_analysis_version, bad_findings, bad_limitations, bad_requesting_agent, bad_key_id, bad_timestamp, bad_signature, and malformed_receipt.

MCP server

POST /mcp is a JSON-RPC 2.0 (streamable HTTP) endpoint so AI assistants can call Pactlyst natively. Same Bearer auth as score-document. Supported methods: initialize, tools/list, tools/call. Batching: send a JSON array of request objects and get back an array of responses — handy for scoring several documents in one round trip. Batches containing only notifications (no id) return 202 with an empty body.

Available tools

ToolArgumentsWhat it does
score_documenttext (required), title, language, document_version, playbook_id, playbook_version, requesting_agentScores a document — same engine as POST /score-document, returns score, verdict, flags, key terms, explanation, and a v2 receipt.
verify_receiptreceipt (required)Verifies an attestation receipt — same engine as POST /attestation.
TERMINAL — tools/call score_document
curl -X POST https://djcmqtyenuvrtotmpfxl.supabase.co/functions/v1/mcp \
  -H "Authorization: Bearer $PACTLYST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "score_document",
      "arguments": {
        "text": "Section 9 \u2014 Term. This agreement renews automatically for successive 12-month terms unless you give written notice at least 90 days before the renewal date."
      }
    }
  }'
TERMINAL — tools/call verify_receipt
curl -X POST https://djcmqtyenuvrtotmpfxl.supabase.co/functions/v1/mcp \
  -H "Authorization: Bearer $PACTLYST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "verify_receipt",
      "arguments": {
        "receipt": { "version": "pactlyst-attestation/v2", "score": 55, "verdict": "caution", "doc_sha256": "9f2c\u2026", "document_version": "v3", "playbook_id": "pactlyst-standard", "playbook_version": "v1", "analysis_version": "gpt-4o-mini/prompt-v1", "findings_summary": {"high": 1, "medium": 2, "low": 1}, "findings_sha256": "7d4e\u2026", "limitations": [], "key_id": "key_abc123", "timestamp": "2026-10-01T22:00:00.000Z", "requesting_agent": "procurement-agent-7", "signature": "a1b2\u2026" }
      }
    }
  }'

JSON-RPC error codes follow the standard set: -32700 parse error, -32600 invalid request, -32601 method not found, -32602 invalid params (including unknown tools), -32603 internal error, and -32001 for auth failures (surfaced at HTTP 401/403).

Idempotency

POST /score-document accepts an Idempotency-Key header (1–64 characters, [A-Za-z0-9-_]). Send the same key with the same request and the first completed result is replayed — no re-score, no double-metering. If a duplicate arrives while the original is still scoring, you get 409 idempotency_in_progress; retry with the same key instead of generating a new one.

HEADER
Idempotency-Key: lease-2026-10-01-a91f

Error codes

Errors are JSON: { "error": "<code>", "message": "..." }. The message is human-readable; switch on error.

score-document

HTTPCodeMeaning
401missing_api_keyNo Authorization header / no key sent
401invalid_api_keyThe key is not recognized
403key_revokedThis key has been revoked
405method_not_allowedUse POST
409idempotency_in_progressA request with this Idempotency-Key is still scoring
413text_too_largeText exceeds 50,000 characters
415invalid_content_typeSend JSON with Content-Type: application/json
400invalid_jsonRequest body is not valid JSON
400missing_textThe text field is required
400empty_textThe text field is empty
422not_a_documentThe text isn’t a legal document — never scored
429rate_limitedOver 60 requests/minute — slow down and retry in a minute
429quota_exceededMonthly scoring quota for this key is used up
502scoring_failedThe scoring engine didn’t respond — retry
503scoring_not_configuredScoring isn’t configured on the server yet
500internal_errorSomething went wrong — retry

attestation

HTTPCodeMeaning
405method_not_allowedUse POST
415invalid_content_typeSend JSON
400invalid_jsonRequest body is not valid JSON
400missing_receiptThe receipt object is required
200(valid: false + reason)Receipt is structurally fine but fails checks — see reasons above
500internal_errorSomething went wrong

mcp

HTTPCodeMeaning
401-32001 (missing or invalid API key)Auth failure at the HTTP layer
403-32001 (API key revoked)Auth failure at the HTTP layer
405method_not_allowedUse POST
400/415-32700 (parse error)Bad JSON or wrong Content-Type
200-32600 / -32601 / -32602 / -32603Invalid request / method not found / invalid params (incl. unknown tool) / internal error
202(empty body)Batch contained only notifications

request-access

HTTPCodeMeaning
405method_not_allowedUse POST
415invalid_content_typeSend JSON
400invalid_jsonRequest body is not valid JSON
400invalid_emailA valid email address is required
429rate_limitedMore than 3 requests from this email in the last hour
500internal_errorSomething went wrong

Rate limits & quotas

  • 60 requests per minute per key on score-document and mcp — over the line returns 429 rate_limited.
  • Monthly quota per key — each successful score counts against the key’s monthly quota; when it’s used up you get 429 quota_exceeded.
  • 50,000 characters max per score-document request — longer texts return 413 text_too_large.
  • 3 requests per hour per email on request-access — anti-spam, returns 429 rate_limited.

Privacy

  • Document text is never stored and never logged. It’s held in memory only for the duration of the scoring call.
  • Only metadata is recorded: key ID, request status, input character count, and token counts (in api_usage).
  • Attestation receipts contain only a SHA-256 hash of the document — never the text itself.
  • The idempotency cache keeps only score, verdict, and receipt — never document text or model prose.

Pricing

Planned pricing — subject to change before launch. All prices are test-mode only: nothing is being charged.
PlanPriceWhat’s included
Free$0 — 5 scans / monthNo card required
Pay-as-you-go$2.00 / scanNo commitment — billed per scored document
Pro$49 / month50 scans included; overage $1.50 / scan
EnterpriseCustomVolume pricing, custom playbooks, SLA

A “scan” is one successful score-document call (or one score_document MCP tool call). Replays served from an Idempotency-Key don’t count as new scans.