Test mode
Every account has test keys (ac_test_…) next to its live keys (ac_live_…). Call the same URLs with a test key to build and test your integration without cost and without touching real data.
What a test key does
Section titled “What a test key does”- It is never charged. A test call costs nothing and needs no credit. The
AccountCloud-Chargedheader is always0.0000. - It never reaches a real source. An operation answers a test key from fixed test values (below), so you can trigger every outcome, the errors included.
- It has its own data. What you create with a test key is only visible to test keys, and test webhooks go only to your test endpoints.
- It shows in your request log, marked as test.
- It has lower limits: 60 requests per minute per key and 10,000 per day per account.
- The input is checked for real. A request that a live key would get a
422for gets the same422with a test key.
Operations without a test mode
Section titled “Operations without a test mode”An operation that has no test values yet answers a test key with 501:
{ "type": "https://docs.accountcloud.io/errors/test_mode_not_supported", "title": "Not available in test mode", "status": 501, "detail": "This operation has no test mode yet, so it cannot be called with a test key. Use a live key, or see the test mode guide for the operations that support it.", "code": "test_mode_not_supported", "operation": "vat.rates", "request_id": "req_01jbxk3v6c9m2q8r4t5w7y0z1a"}Provider test environments
Section titled “Provider test environments”Some operations can pass test calls on to the test environment of their source instead of the fixed values. We switch that per operation; the table below says where it is possible.
Test values per operation
Section titled “Test values per operation”address.format
Section titled “address.format”POST /v1/address/format
Writes an address as the lines its country prints it on.
A test key gets the same answers as a live key: this operation reads only our own reference data.
| Input | Result |
|---|---|
address: {"country": "NL", "street": "Hoofdstraat", "house_number": "12", "postal_code": "1234ab", "city": "Amsterdam"}, from_country: NL |
lines: ["Hoofdstraat 12", "1234 AB Amsterdam"] |
The same with from_country: BE |
The same lines, plus the country line Netherlands |
address.forms
Section titled “address.forms”GET /v1/address/forms, GET /v1/address/forms/{country}
The address form of a country: its fields, which are required, the postcode pattern and the subdivisions.
A test key gets the same answers as a live key: this operation reads only our own reference data.
| Input | Result |
|---|---|
Any of the 34 supported countries, such as NL, BE or ES |
The real form of that country |
A country outside them, such as US |
404 with country_not_supported |
address.validate
Section titled “address.validate”POST /v1/address/validate
Checks an address against the form of its country and returns it normalised.
A test key gets the same answers as a live key: this operation reads only our own reference data.
| Input | Result |
|---|---|
address: {"country": "NL", "street": "Hoofdstraat", "house_number": "12", "postal_code": "1234ab", "city": "Amsterdam"} |
valid: true, with postal_code normalised to 1234 AB |
The same with "postal_code": "12345" |
valid: false, with the error postcode_invalid on postal_code |
| An address in a country outside the 34 supported ones | 422 with validation_failed on address.country |
company.profile
Section titled “company.profile”GET /v1/companies/{country}/{number}
Fixed test companies for NL and BE, with every outcome. The checks on the country, the number and freshness are the real ones, and so is the rule on who may see NL data: an account without access gets 403 with register_restricted, also with a test key.
Can pass test calls on to the test environment of kvk.
| Input | When | Result |
|---|---|---|
NL 69599084 |
freshness auto or cached |
The test company Test EMZ Dagobert (Eenmanszaak), from our copy (source.freshness: cached, 3 days old) |
NL 69599084 |
freshness: live |
The same company, fetched now (source.freshness: live) |
NL 68750110 |
freshness auto or live |
The test company Test BV Donald (Besloten vennootschap), fetched now (source.freshness: live) |
NL 68750110 |
freshness: cached |
404 with company_not_cached |
NL 00000000 |
404 with company_not_found. With a live key this costs what the KvK charges us for the lookup |
|
NL 99999999 |
503 with provider_unavailable |
|
NL, any other 8 digits |
404 with company_not_found, or company_not_cached with freshness: cached |
|
BE 0123456749 |
The test company Testbedrijf NV, from the daily copy of the KBO (source.freshness: cached) |
|
BE, any other enterprise number |
404 with company_not_found |
|
BE with freshness=live |
422 with validation_failed on freshness: the KBO is never asked live |
|
NL 1234 |
422 with validation_failed on number |
|
DE (or any country other than NL and BE) |
404 with country_not_supported |
company.search
Section titled “company.search”GET /v1/companies
Finds the test companies of company.profile. The checks on country, q and limit are the real ones, and so is the rule on who may see NL data.
Can pass test calls on to the test environment of kvk.
| Input | Result |
|---|---|
country=NL, a q that contains test |
Test EMZ Dagobert (69599084) and Test BV Donald (68750110) |
country=NL, q is one of those numbers |
That company |
country=BE, a q that contains test, or the start of 0123456749 |
Testbedrijf NV (0123456749) |
q=unavailable |
503 with provider_unavailable |
| Anything else | An empty list |
ocr.extract
Section titled “ocr.extract”POST /v1/documents
A test document is checked like a live one (size, file type, password, pages), then gets a fixed result that depends on its file name, with the same statuses and webhooks as a live document. Nothing is read and nothing is charged: charge.amount is 0.0000, and charge.live_amount shows what it would cost live. Sending the same test file twice gives duplicate_of. Test documents are deleted after 24 hours.
The result changes over time, as it would live, with the same webhooks to your test endpoints.
| Input | When | Result |
|---|---|---|
| any other file name | processing: automatic |
After ~3 s completed, with the fixed invoice of Testleverancier B.V. (two lines, 21% and 9%) |
receipt.* (for example receipt.jpg) |
processing: automatic |
After ~3 s completed, with a fixed receipt (9% only) |
unbalanced.pdf |
processing: automatic |
After ~3 s completed, with the warning totals_do_not_reconcile |
slow.pdf |
processing: automatic |
60 s extracting, then completed (to test polling) |
fail.pdf |
processing: automatic |
After ~3 s failed, with failure.code extraction_failed |
ocr.feedback
Section titled “ocr.feedback”POST /v1/documents/{document}/feedback
A report on a test document is checked and stored as live, but the document never goes to the training set: training is always stats_only.
A test key gets the same answers as a live key: this operation reads only our own reference data.
ocr.read
Section titled “ocr.read”DELETE /v1/documents/{document}, GET /v1/documents, GET /v1/documents/{document}
Reading, listing and deleting work as live, on your test documents only. A test key never sees a live document, and the other way round.
A test key gets the same answers as a live key: this operation reads only our own reference data.
ubl.generate
Section titled “ubl.generate”GET /v1/documents/{document}/ubl
The UBL of a completed test document is made from its fixed result, with your own_party as the buyer, or Testafnemer B.V. when you sent none.
A test key gets the same answers as a live key: this operation reads only our own reference data.
ubl.validate
Section titled “ubl.validate”POST /v1/ubl/validate
The validation is the real one, with a test key too.
A test key gets the same answers as a live key: this operation reads only our own reference data.
ubl.verified
Section titled “ubl.verified”POST /v1/documents
A verified test document goes through the same statuses and webhooks as a live one, but no processor looks at it: after a minute it is approved, with a fixed UBL that passes the validation, or rejected, depending on its file name. Nothing is charged.
The result changes over time, as it would live, with the same webhooks to your test endpoints.
| Input | When | Result |
|---|---|---|
| any other file name | processing: verified |
extracting → awaiting_review (with document.extracted) → after 1 minute completed, with a fixed UBL that passes the validation |
reject.pdf |
processing: verified |
After 1 minute rejected, with rejection.reason not_an_invoice |
duplicate.pdf |
processing: verified |
After 1 minute rejected, with rejection.reason duplicate |
vat.validate
Section titled “vat.validate”GET /v1/vat-numbers/{vat_number}
Fixed VAT numbers, without asking VIES. The checks on the country and the format are the real ones: a number in the wrong format is valid: false with format_valid: false, as it is live.
| Input | Result |
|---|---|
NL999999990B01 |
valid: true, Testbedrijf B.V., with the consultation number WAPITEST00000001 |
BE0123456749 |
valid: true, Testbedrijf NV, with the consultation number WAPITEST00000001 |
NL999999991B01 |
valid: false |
DE999999999 |
503 with provider_unavailable: the register of the member state does not answer |
| Any other number in the right format | valid: false |
NL123 |
valid: false, format_valid: false, and nothing is charged |
GB123456789 (outside the EU) |
404 with country_not_supported |
123456789 (no country code) |
422 with validation_failed on vat_number |