Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.clevis.dev/llms.txt

Use this file to discover all available pages before exploring further.

The mock provider exposes magic trigger values that pick a deterministic outcome at intake. Use them to drive demos and tests through any path — happy, rejection, stuck, or slow — without timing flakiness.
These are dev/test affordances, not stable API behaviour. They are available on the mock provider while sandbox is in place.

Order of evaluation

Triggers are checked in order — first match wins:
1

X-Mock-Outcome header

If present and recognised, the header overrides everything else (including body triggers).
2

external_id prefix

MOCK_REJECT_INTAKE_, MOCK_REJECT_BANK_, MOCK_SLOW_, MOCK_STUCK_, MOCK_OK_.
3

amount suffix

.13 and .99 (after rounding to 2dp).
4

document_id

The literal value "00000000000" triggers a compliance-screening reject.
5

Default

Happy path: PENDING → PROCESSING → PAID.

external_id prefixes

PrefixOutcomestatus_codestatus_detail ends with
MOCK_OK_Happy path (explicit; same as default)"200"Payout received and queued.
MOCK_REJECT_INTAKE_Reject at intake — no PROCESSING step"300"Rejected at intake (mock trigger).
MOCK_REJECT_BANK_PENDING → PROCESSING → REJECTED"301"Beneficiary bank rejected the transfer (mock trigger).
MOCK_SLOW_Happy path forced to 30s per step"200"Payout received and queued.
MOCK_STUCK_Advances to PROCESSING and never settles"200"Stuck in processing (mock trigger).
MOCK_SLOW_ ignores any processing.step_seconds override and uses 30 seconds per step — useful for demoing a “watch it process” UI.

Examples

# Force a bank rejection
"external_id": "MOCK_REJECT_BANK_demo-001"

# Stuck in PROCESSING — for testing your "stale payout" UX
"external_id": "MOCK_STUCK_polling-demo"

# Watch it advance every 30s — for live demos
"external_id": "MOCK_SLOW_audience-demo"

Amount suffixes

The mock looks at the 2-decimal string form of amount (so 1000.13.13, but 1000.1300001 also rounds to .13 and triggers).
SuffixOutcomestatus_codestatus_detail ends with
.13PENDING → PROCESSING → REJECTED"302"Insufficient funds in payout account (mock trigger).
.99Reject at intake (no PROCESSING)"303"Amount exceeds per-payout limit (mock trigger).
# Demo "insufficient funds in payout account"
"amount": "1000.13"

# Demo "amount exceeds per-payout limit" (intake reject)
"amount": "1000000.99"

Document ID trigger

FieldValueOutcomestatus_codestatus_detail ends with
beneficiary.document_id"00000000000"Reject at intake"304"Beneficiary failed compliance screening (mock trigger).
"beneficiary": {
  "name": "Test User",
  "document_type": "CC",
  "document_id": "00000000000",   # compliance screen trigger
  ...
}

Header overrides

The X-Mock-Outcome header takes precedence over everything. Combine with X-Mock-Outcome-At: intake for REJECTED to skip the PROCESSING step.
Header valuesOutcome
X-Mock-Outcome: PAIDPENDING → PROCESSING → PAID
X-Mock-Outcome: REJECTEDPENDING → PROCESSING → REJECTED (bank reject)
X-Mock-Outcome: REJECTED + X-Mock-Outcome-At: intakeReject at intake (no PROCESSING)
X-Mock-Outcome: CANCELLEDPENDING → PROCESSING → CANCELLED
Unrecognised values are ignored (with a server-side warning log), and the mock falls back to body triggers.

Example

curl -X POST https://api.clevis.dev/v1/payouts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Mock-Outcome: REJECTED" \
  -H "X-Mock-Outcome-At: intake" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "100.00",
    "currency": "COP",
    "country": "CO",
    "external_id": "force-reject-001",
    "beneficiary": { ... }
  }'

Reading the trigger off the response

Every mock-triggered terminal outcome carries a status_detail ending in "(mock trigger)." — so your tests can assert on the trigger without hardcoding the message.
assert payout["status"] == "REJECTED"
assert payout["status_code"] == "301"
assert payout["status_detail"].endswith("(mock trigger).")

Tip: synchronous + magic trigger = great for unit tests

Combine processing.step_seconds: 0 with any trigger. The terminal state is already applied in the create response — no polling, no timer, no flakiness.
{
  "external_id": "MOCK_REJECT_BANK_test-001",
  "amount": "100.00",
  "currency": "COP",
  "country": "CO",
  "processing": { "step_seconds": 0 },
  "beneficiary": { ... }
}
The response comes back with status: "REJECTED" and status_code: "301" on the same line that creates the payout.