Skip to content

The sandbox API

This is the API both tests ran against, in one screen: the wire convention, the lifecycle, webhooks, and the error model. The typed contract is /openapi.json; generate a client from it rather than transcribing field names.

  • Base URL: https://partifact-mock.thanhvuttv.workers.dev
  • Every call: POST <base>/api/2026-01/<dotted.method> with a JSON body. The method is the last path segment, e.g. .../api/2026-01/repairer.jobs.get. It is RPC over POST, date-versioned (2026-01), not REST resources.
  • Two headers on every call (except the install call):
    • Authorization: Bearer <api_key>
    • Partly-Integration-ID: <integration_id>

Your first call, reading the seeded demo job with pre-loaded repairer credentials, no install needed:

Terminal window
curl -s https://partifact-mock.thanhvuttv.workers.dev/api/2026-01/repairer.jobs.get \
-H "Authorization: Bearer partifact_demo_repairer_3f8a1c0d9e2b4a67b1c2" \
-H "Partly-Integration-ID: 0c000000-0000-4000-8000-000000000001" \
-H "Content-Type: application/json" \
-d '{"identity":{"external":"CCC-2026-04817"}}'

A real integration provisions itself rather than using hand-pasted keys. The install call, integrations.insert, is the one method that takes no auth headers; it exchanges an OAuth grant for the api_key + integration_id every other call needs. (The sandbox also pre-loads ready-to-use repairer and supplier credentials, so you can skip the dance while exploring.) Full flow: Authentication.

The ordered path from a vehicle to a settled invoice, wire method by wire method:

StepWire methodResult
Prepare the vehicletier1.preparenormalized vehicle
Find the repairer sitebusinesses.listsite id
List work providersrepairer.work-providers.listprovider ids
Open a repair jobrepairer.jobs.insertjob
Identify partsrepairer.jobs.parts.insertparts on the job
Get a basketrepairer.jobs.baskets.latest.get{ offers, suppliers }
Place the order extensionrepairer.procurements.insertorder_requested
Confirm the ordersupplier.procurements.confirmorder_confirmed ← terminal public state
Reconcile the invoice extensionrepairer.procurements.invoices.listitemized invoice

Re-read state any time with repairer.jobs.get and repairer.procurements.get. To watch an agent drive this lifecycle as named tools, see the Procurement MCP.

Two of these steps go beyond the public contract, and the basket deliberately carries no currency field; both are explained on Real vs. simulated.

State changes emit HMAC-SHA256-signed webhooks: an 8-field envelope (message_id, event type, timestamp, payload, and so on), a base64 signature in the partly-hmac-sha256 header, and a 5-minute replay window. Verifying the signature is the single most security-sensitive thing an integrator does. The paste-ready TypeScript and Python recipe is part of the contract docs the agent reads.

Each method declares its own type-tagged union of errors, and the variant object is the response body. There is no shared { code, message } envelope. The HTTP status is added for realism; the body’s type is the signal. (The Procurement MCP enriches these into { code, message, retryable } for agents, but the wire model is type-tagged.) The auth rejections are demonstrated live on Authentication; the full per-method union is in the typed /openapi.json.

Built for agents. Prefer these over scraping HTML:

To operate the lifecycle without writing HTTP, use the Procurement MCP; to query this contract as tools, the Docs MCP.