Skip to main content
The Precipiq REST API is the foundation of the AI Consequences Ledger. Every endpoint lives under https://api.precipiq.dev/api/v1/ and returns a consistent JSON envelope so you can handle success and error paths the same way across your codebase.

Authentication

Every request requires an X-Precipiq-Key header. Keys come in two flavors:
  • pq_live_… — production keys that write to your live ledger
  • pq_test_… — sandbox keys for integration testing; data is isolated and never appears in production reports
curl -s https://api.precipiq.dev/api/v1/decisions \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME'
Missing or invalid keys return 401 with this body — the message is identical whether the header is absent or wrong, so an attacker cannot enumerate valid keys by response shape:
{
  "error": {
    "code": "unauthorized",
    "message": "invalid or missing api key"
  }
}

Response envelope

All successful responses share the same outer shape. The data field contains the endpoint-specific payload; meta carries tracing information you can include in support tickets.
{
  "data": { },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "timestamp": "2026-04-16T12:34:56.789012Z"
  }
}
Every response also sets an X-Request-ID header that mirrors meta.request_id. Include it when opening a support ticket. Error responses use a separate envelope:
{
  "error": {
    "code": "validation_error",
    "message": "confidence must be ≤ 1.0",
    "details": { }
  }
}
The optional details object contains field-level validation errors when code is validation_error.

Rate limits

Limits are applied per organization. Exceeding a limit returns 429 with a Retry-After value in the response.
BucketLimitEndpoints
Single ingestion100 req / sPOST /decisions, POST /financial-events, POST /links, DELETE /links/{id}
Batch ingestion10 req / sPOST /decisions/batch
Reads1,000 req / sGET /decisions, GET /links, GET /analytics/*, GET /decisions/chain/verify
WebSocket handshake30 req / min / IP/ws/v1/stream
Use the batch endpoint (POST /decisions/batch) when ingesting bursts of decisions. You get 10 large calls per second instead of 100 individual ones, and the server preserves hash-chain order inside each batch.

Endpoints at a glance

Browse all endpoints by tag in the interactive reference below, or jump straight to a group:
  • decisions/api/v1/decisions, /decisions/batch, /decisions/{id}, /decisions/chain/verify
  • financial-events/api/v1/financial-events, /financial-events/webhook/stripe
  • consequence-links/api/v1/links, /links/{id}, /links/{id}/confirm, /links/{id}/reject
  • analytics/api/v1/analytics/ai-pnl, /analytics/timeline, /analytics/liability
  • exports/api/v1/exports, /exports/{id}, /exports/{id}/download
  • websocket/ws/v1/stream

Common calls

Every example below uses the placeholder key pq_test_demo_key_REPLACE_ME — substitute your own key from the dashboard before running.

Ingest a single decision

POST /api/v1/decisions
curl -X POST https://api.precipiq.dev/api/v1/decisions \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -d '{
    "agent_id": "pricing-bot",
    "action_type": "discount_offer",
    "inputs":  {"customer_id": "cust_123", "tier": "gold"},
    "outputs": {"discount_pct": 15},
    "confidence": 0.82,
    "human_in_loop": false
  }'

Ingest a batch of decisions

POST /api/v1/decisions/batch — send up to 100 decisions in a single call.
curl -X POST https://api.precipiq.dev/api/v1/decisions/batch \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -d '{
    "decisions": [
      {"agent_id":"a","action_type":"t","inputs":{},"outputs":{},"confidence":0.9,"human_in_loop":false},
      {"agent_id":"a","action_type":"t","inputs":{},"outputs":{},"confidence":0.8,"human_in_loop":false}
    ]
  }'

List decisions with cursor pagination

GET /api/v1/decisions?agent_id=&action_type=&start=&end=&cursor=
curl
curl -s 'https://api.precipiq.dev/api/v1/decisions?agent_id=pricing-bot' \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME'
The response’s data.next_cursor is an opaque string. Pass it back verbatim as ?cursor=… to fetch the next page. Results are ordered newest first (timestamp DESC, id DESC), and the cursor guarantees no rows are skipped or duplicated across pages.

Verify the hash chain

GET /api/v1/decisions/chain/verify?start_date=&end_date=
curl
curl -s https://api.precipiq.dev/api/v1/decisions/chain/verify \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME'
Returns is_valid, records_checked, first_broken_link, and verification_timestamp. See Hash Chain for the semantics.

Ingest a financial event

POST /api/v1/financial-events
curl
curl -X POST https://api.precipiq.dev/api/v1/financial-events \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "internal",
    "event_type": "payment",
    "amount": "149.00",
    "currency": "USD",
    "external_id": "invoice_0042",
    "timestamp": "2026-04-16T12:35:02Z"
  }'
POST /api/v1/links
curl
curl -X POST https://api.precipiq.dev/api/v1/links \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -d '{
    "decision_id":         "d5e7a3b0-0000-0000-0000-000000000001",
    "financial_event_id":  "fev_abc",
    "correlation_strength": 1.0,
    "attribution_method":   "direct",
    "link_type":            "revenue",
    "notes":                "upsell offer accepted"
  }'
POST /api/v1/links/{id}/confirm and POST /api/v1/links/{id}/reject These endpoints are used when a human reviews a link with status ML_SUGGESTED. Confirming flips it to ML_INFERRED and nudges the Bayesian priors; rejecting soft-deletes it and nudges them the other way.
curl
curl -X POST https://api.precipiq.dev/api/v1/links/${LINK_ID}/confirm \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME'

Fetch the AI P&L

GET /api/v1/analytics/ai-pnl?start=&end=&agent_id=
curl
curl -s 'https://api.precipiq.dev/api/v1/analytics/ai-pnl?start=2026-04-01&end=2026-04-30' \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME'

Aggregate liability exposure

GET /api/v1/analytics/liability
curl
curl -s https://api.precipiq.dev/api/v1/analytics/liability \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME'

Create and download a forensic export

POST /api/v1/exportsGET /api/v1/exports/{id}GET /api/v1/exports/{id}/download Forensic exports are generated asynchronously. Start the job, poll until it completes, then download the signed bundle.
curl
# 1. Start the export.
EXPORT_ID=$(curl -s -X POST https://api.precipiq.dev/api/v1/exports \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' \
  -H 'Content-Type: application/json' \
  -d '{"export_type":"forensic","start_date":"2026-01-01T00:00:00Z","end_date":"2026-03-31T23:59:59Z"}' \
  | jq -r .data.export_id)

# 2. Poll until complete.
while true; do
  STATUS=$(curl -s "https://api.precipiq.dev/api/v1/exports/$EXPORT_ID" \
    -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' | jq -r .data.status)
  [ "$STATUS" = "complete" ] && break
  sleep 5
done

# 3. Download the signed bundle.
curl -s "https://api.precipiq.dev/api/v1/exports/$EXPORT_ID/download" \
  -H 'X-Precipiq-Key: pq_test_demo_key_REPLACE_ME' \
  -o precipiq-export.zip
The download URL in the response is a pre-signed link with a limited TTL. Download the file promptly after the export reaches complete status.