DocsGet started

Test mode

A test key returns a fixture document instead of parsing the file you send. It is free, it does not touch your allowance, and it can return any error code on demand.

Send a request#

Take an sb_test_ key from the console. Same endpoint, same host, same headers. Send any PDF: it is checked for size and type and then discarded unread.

# Any PDF will do. It is validated and then discarded.
curl -X POST https://statementbear.com/api/v1/documents \
  -H "Authorization: Bearer $STATEMENTBEAR_TEST_KEY" \
  -H "Content-Type: application/pdf" \
  --data-binary @anything.pdf

# Ask for a specific document, or force an error.
curl -X POST https://statementbear.com/api/v1/documents \
  -H "Authorization: Bearer $STATEMENTBEAR_TEST_KEY" \
  -H "X-Test-Scenario: credit_card" \
  -H "Content-Type: application/pdf" \
  --data-binary @anything.pdf

Scenarios#

Send X-Test-Scenario to choose what comes back. Omit it for bank.

ScenarioReturnsWhat it is
bank200A single current account, reconciled. The default when no header is sent.
credit_card200A card statement. Its credits are the repayment and a refund, so it is what to test your income filter against.
multi_account200A checking and a savings account on one document, with a transfer printed on both sides.
unreconciled200A document whose figures did not reconcile. Exercises your manual review path.
not_a_bank_statement422The file was readable and is not a statement.
parse_failed500Our error. Retry it.
trial_exhausted402The free allowance is spent and no card is on file.
monthly_cap_reached402The monthly document ceiling was hit.
canceled402Billing for the account was cancelled.
too_many_concurrent_requests429Too many documents in flight. Exercises your backoff.
file_too_large413Over the size limit, without uploading 20MB to find out.

An unknown value returns 400 unknown_test_scenario and the message lists every valid one.

Telling a fixture apart#

Every document carries livemode. It is false on a fixture and true on a real parse. Store it with whatever you parsed for.

200 OK, from a test key
{
  "id": "doc_test_9c41f0a2b8e37c94",
  "object": "document",
  "livemode": false,
  "currency": "GBP",
  "issuer": { "name": "Monzo", "domain": "monzo.com" },
  "accounts": [ ... ],
  "verification": { "reconciled": true, "issues": [] },
  "usage": { "documents": 1 }
}

A fixture's id starts doc_test_. Everything else about a scenario is the same on every call, so it is safe to assert on in a snapshot test.

What is the same#

  • Authentication, including 401 for a missing or revoked key.
  • The size, type and content checks on your upload. A mislabelled PNG still returns 415.
  • Idempotency-Key, including replays, Idempotent-Replayed: true and the 409 after 24 hours.
  • The response envelope, the error codes and every header.
  • The usage log in your console, so a test call shows up like any other.

What is different#

  • The file you send is never read. The response is a fixture.
  • Nothing is billed. X-Billable-Documents is always 0.
  • Your free allowance and monthly cap are untouched.
  • Test keys keep working when billing is cancelled.
  • Concurrency is not limited. Up to 120 test requests per minute instead.

Idempotency keys#

An idempotency key is scoped to the mode that used it. The same string can be used once in test and once for real, and neither replays the other.

Going live#

  1. Swap sb_test_ for sb_live_ in your secret store.
  2. Remove X-Test-Scenario. A live key sends it back as 400 test_scenario_on_live_key, and nothing is parsed or charged.
  3. Check that whatever you store records livemode.
  4. Work through the rest of Going live.
Something wrong or missing on this page? [email protected]