Authenticate every request
The base URL is https://outcomatic.com/v1. Send your provisioned key in the Authorization: Bearer header. The key determines the tenant; requests cannot supply a different tenant or an arbitrary ERP destination. Keep the key on your server and out of browser code.
Pilot keys have an expiry and can be revoked. Your provisioning details include the existing supplier fixture, permitted spending limit, and daily run quota. Use synthetic invoice text for this staging pilot.
curl https://outcomatic.com/v1/contracts/invoice.create_draft@1.0.0 \
-H "Authorization: Bearer $OUTCOMATIC_API_KEY"Resources
| Operation | Result | Behavior |
|---|---|---|
| POST /v1/runs | 202 with a persisted run ID and Location header. | Requires Idempotency-Key. Acceptance starts durable processing; it does not confirm an ERP draft. |
| GET /v1/runs/{run_id} | The tenant-owned run, its status, and current result. | Poll this resource until the run completes or needs attention. |
| GET /v1/runs/{run_id}/receipt | The completed run’s result object. | Returns 409 receipt_not_ready while the run is not completed. |
| POST /v1/runs/{run_id}/reconcile | 202 for a read-only confirmation attempt. | Send no body. Available for uncertain or reconciling runs; an already completed run returns 200 without starting work. |
| GET /v1/contracts/invoice.create_draft@1.0.0 | The supported input fields and tenant spending ceiling. | Requires authentication, like every other pilot endpoint. |
One text invoice, one staging draft
The contract is invoice.create_draft@1.0.0 and the connection is erpai-staging. Supply labeled Supplier, Invoice, Date, Currency, and Total fields, followed by complete pipe-separated invoice rows. Each row has Description | Quantity | Unit price | Line total. The date must use YYYY-MM-DD and the currency must be USD.
The supplier must already exist and be active in the provisioned ERP.AI staging workspace. The printed supplier name must match that record. Quantities must be positive integers, amounts must be exact USD minor-unit values after extraction, and every line and invoice total must reconcile. The verifier compares extracted values with their complete source fields.
- One invoice with 1–20 lines; document_text is limited to 16,384 UTF-8 bytes and the JSON request to 65,536 bytes.
- supplier_id is a 24-character lowercase hexadecimal ERP record ID. max_total_minor is a positive integer in cents, within the tenant’s provisioned ceiling.
- The contract excludes nonzero tax, discounts, shipping, credits, fractional quantities, and extra document instructions. Unsupported input requires review.
- This pilot does not perform PDF uploads, OCR, purchase-order or goods-receipt matching, batch processing, or webhook delivery. Its only ERP mutation is a draft record; approval, posting, payment, supplier creation, and bank-detail changes are excluded.
Prepare the invoice request
Save this body as invoice.json. Replace the example supplier ID and supplier name with the fixture supplied for your pilot. A 20,000-cent ceiling permits an invoice of at most USD 200.00, subject to the tenant’s limit.
{
"contract": "invoice.create_draft@1.0.0",
"connection_id": "erpai-staging",
"input": {
"document_text": "Supplier: Example Components\nInvoice: DEMO-0042\nDate: 2026-10-09\nCurrency: USD\nDescription | Quantity | Unit price | Line total\nWidget | 2 | 50.00 | 100.00\nTotal: 100.00",
"supplier_id": "dddddddddddddddddddddddd",
"currency": "USD",
"max_total_minor": 20000
}
}Submit with a stable idempotency key
Choose one Idempotency-Key for the logical submission and keep it unchanged when retrying the same request. The key is an HTTP header, not a JSON field. It accepts 1–200 printable ASCII characters without spaces.
The same tenant, key, and normalized request return the original run. A changed request under that key returns 409 idempotency_conflict. Duplicate retries do not consume another daily run slot. A separate supplier-invoice claim also prevents different run keys from authorizing a second draft for the same invoice.
curl -X POST https://outcomatic.com/v1/runs \
-H "Authorization: Bearer $OUTCOMATIC_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pilot-invoice-DEMO-0042" \
--data-binary @invoice.jsonObserve acceptance separately from completion
POST returns 202 after the run is durably accepted. Preserve its id and follow the Location header or links.self with an authenticated GET. The run resource uses status for execution progress and result for the developing evidence record; result is initially null.
{
"id": "123e4567-e89b-42d3-a456-426614174000",
"status": "queued",
"contract": "invoice.create_draft@1.0.0",
"connection_id": "erpai-staging",
"created_at": "2026-10-09T12:00:00.000Z",
"updated_at": "2026-10-09T12:00:00.000Z",
"result": null,
"links": {
"self": "/v1/runs/123e4567-e89b-42d3-a456-426614174000",
"receipt": "/v1/runs/123e4567-e89b-42d3-a456-426614174000/receipt"
}
}Interpret the run status
| Status | Meaning | Next step |
|---|---|---|
| queued, routing, extracting, verifying | Processing the source and required checks. | Continue polling the existing run. |
| writing, reconciling | An ERP attempt or its confirmation is in progress. | Continue polling; do not submit a new write. |
| completed | The saved staging draft passed authoritative read-back. | Retrieve the receipt. |
| requires_review | The source, verification, or duplicate policy prevented completion. | Inspect result.error and result.verification.checks. |
| failed | Execution stopped before a confirmed business outcome. | Inspect result.error before deciding how to proceed. |
| uncertain | An ERP effect could not be confirmed or its saved fields differed. | Request read-only reconciliation of the same run. |
Retrieve the confirmation receipt
GET /v1/runs/{run_id}/receipt returns the result object only when status is completed. Completion requires checking the saved record’s identity, supplier, invoice fields, amounts, lines, source references, and draft status against the intended payload.
The receipt includes routing evidence, extraction attempts with reported usage, verification checks, and the confirmed record reference. Usage is null when the provider did not report it. The fields below illustrate part of a completed receipt; a draft confirmation does not establish approval, posting, or payment.
{
"run_id": "123e4567-e89b-42d3-a456-426614174000",
"contract": "invoice.create_draft@1.0.0",
"environment": "erpai-staging",
"verification": {
"state": "passed",
"version": "invoice-usd-draft/1.0.0",
"checks": [
{ "id": "invoice_arithmetic", "state": "passed", "detail": "The sum of line totals must equal the invoice total exactly; tax, discounts, and charges are outside this contract." }
]
},
"effect": {
"state": "confirmed",
"kind": "draft_bill",
"record_id": "123e4567e89b42d3a4564266",
"operation_key": "123e4567-e89b-42d3-a456-426614174000",
"draft_status": "draft"
}
}Resolve an uncertain write through read-back
For an uncertain or reconciling run, POST to its reconcile resource with no request body. This starts a read-only confirmation attempt using the original ERP record identity and immutable payload. It does not rerun extraction or create another draft.
Poll the original run after the 202 response. If the record becomes visible and matches, the run completes. A missing or mismatched record remains uncertain. If the run is already completed, the endpoint returns 200 with its current run resource and starts no additional work.
curl -X POST "https://outcomatic.com/v1/runs/$RUN_ID/reconcile" \
-H "Authorization: Bearer $OUTCOMATIC_API_KEY"Handle errors without changing operation identity
API errors use an error code, with fields for input-validation details. Keep the original idempotency key after a lost submission response. Once a run ID is known, use that run’s status and reconciliation resource to investigate an interrupted ERP operation.
| HTTP status | Typical cause | Handling |
|---|---|---|
| 400 / 415 / 422 | Invalid request, media type, fields, or declared spending limit. | Correct the request using the documented schema. |
| 401 / 403 | Missing, expired, or revoked key; disabled tenant; or unauthorized connection. | Check the provisioned key and tenant connection. |
| 404 | Unknown resource or a run outside the caller’s tenant. | Check the run ID and credentials. |
| 409 | Idempotency conflict, receipt not ready, or reconciliation not available for this status. | Inspect the error code and the existing run. |
| 413 | Request body exceeds the size limit. | Reduce the request to one supported text invoice. |
| 429 | Request rate or daily admission limit reached. | Honor Retry-After; retain the same submission key. |
| 503 | A required service or connection is unavailable. | Retry with the same key; inspect an existing run before taking further action. |
Missing a detail or found a problem?
Send a documentation question →