Testing in the sandbox
The sandbox lets you build and test an integration against the Veridion APIs without spending credits. It answers on the same URLs as production with generated, fake data, so moving to production means changing the key, not the code.
No credits spentSandbox calls never spend credits, and the sandbox behaves the same for every account.
How it works
- You exchange your sandbox key's client ID and client secret for an access token, exactly as you would with a production key.
- You call the usual base URL,
https://data.veridion.com, with that token. Veridion recognizes the sandbox key and sends the request to the sandbox instead of the real APIs. - The sandbox answers in the same shape as the real API, with fake data, and marks every response with the
X-Veridion-Sandbox: trueheader.
TipThe key alone decides where a request goes. No header, parameter or URL switches it: a sandbox key can't reach real data, and a production key can't reach the sandbox.
Sandbox and production
| Sandbox | Production | |
|---|---|---|
| Key | Sandbox key | Production key |
| Base URL | https://data.veridion.com | https://data.veridion.com |
| Data | Generated, fake | Real |
| Credits | None | Your account's credits |
| Rate limit | 20 requests per second, bursts up to 30 | Your account's rate limit, see Rate limits |
| Results per list query | Up to 200 per page and 10,000 per query, for every account | Your account's limits |
Calling the sandbox
Getting a sandbox key
A sandbox key is a client ID and client secret, like a production key. Your Veridion representative provides sandbox keys alongside your production credentials. If you manage your keys in your Veridion account, you can create sandbox keys yourself on the API keys page.
Generating a token
Use the sandbox key's client ID and secret with the OAuth 2.0 Client Credentials flow described in Authentication. The request is the same as for a production key:
curl -X POST https://auth.veridion.com/oauth2/token \
-u "your_sandbox_client_id:your_sandbox_client_secret" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&scope=api:use"Making a request
Send the token in the Authorization header, as in production:
curl -i -X POST https://data.veridion.com/match/v6/companies \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/json" \
-d '{
"identifiers": {
"commercial_names": ["Acme Robotics"],
"address_txt": "Berlin, Germany"
}
}'The response carries the sandbox header and a fake company. Headers and body are trimmed:
HTTP/1.1 200 OK
X-Veridion-Sandbox: true
Content-Type: application/json; charset=utf-8{
"resolution": {
"scenario": "inferred_resolution",
"summary": "The input required interpretation, and the result was selected as the most likely match based on consistent signals."
},
"count": 1,
"result": [
{
"match_details": {
"confidence_score": 0.83,
"matched_on": ["company_name"]
},
"veridion_id": "5OTBHGR573I4X5TF",
"company_name": "Clavorin Materials",
"registered_name": "Clavorin Materials Inc.",
"jurisdiction": "US-DE",
"year_founded": 1959
}
]
}Generated data
The same request returns the same company
The sandbox generates every response from the request itself. Send the same request again and you get the same response; change an input and you get a different company, just as stable. Any input works, so you don't need a list of test companies.
Built for testing the flow, not the dataGenerated companies don't reflect your input: matching
Acme Roboticsin Berlin can return a company with another name in another country. Search filters are validated as in production, so an invalid query gets the same400, but they don't narrow the results. Use the sandbox to test your integration's flow and error handling, and a production key to judge the data itself.
IDs work across every API
Sandbox IDs use the production format: 16 characters. A veridion_id from Match & Enrich or Search returns the same company from Firmographics, Location Intelligence, Corporate structure, ESG and Products & Services (coming soon), so you can test multi-step workflows end to end.
curl https://data.veridion.com/corporate-structure/v1/companies/5OTBHGR573I4X5TF/ultimate-parent \
-H "Authorization: Bearer your_access_token"{
"veridion_id": "5OTBHGR573I4X5TF",
"company_name": "Clavorin Materials",
"result": {
"ultimate_parent_veridion_id": "NM7ION2QMOLAX2PM",
"ultimate_parent_company_name": "Quorvex Foods GmbH",
"ultimate_parent_website_domain": "quorvexfoods.example.com",
"ultimate_parent_jurisdiction": "de"
}
}Location and building IDs work the same way. A location from a company's footprint is the same location when you fetch it by ID, it names the same company, and its building lists it.
Any well-formed ID gets a fake company, including a production Veridion ID: the sandbox never returns real data. An ID that isn't 16 characters gets a 400, as in production.
Lists and pagination
List endpoints paginate as described in Pagination: page_size (default 25, max 200), max_results (up to 10000), cursor, and the result_count, has_more and next_cursor response fields. Totals are realistic, and some companies have empty lists, as real ones do (for example, no products).
To continue a list, send the next_cursor value on its own; it keeps the page_size and max_results of the first call. Changing either while paging gets a 400 on Search and Products & Services (coming soon) and is ignored on Location Intelligence, as in production.
List sizes are the same for every account. In production your account's limits apply, so check them before relying on large pages.
Recognizing sandbox data
Sandbox data is fake on purpose and easy to spot:
- Every response from the sandbox carries the
X-Veridion-Sandbox: trueheader, errors included. A request rejected before it reaches the sandbox, such as a401for an invalid or expired token, doesn't carry it. - Company names are invented, for example
Clavorin Materials,Zorbix DynamicsorQuorvex Foods GmbH. - Websites, email addresses and social links use
example.comsubdomains, for examplehttps://www.clavorinmaterials.example.comand[email protected].
Phone numbers and registry identifiers such as LEI, EIN and VAT IDs follow real formats but are random, and can coincide with real ones. Don't use them to contact or look up anyone.
Magic test values
Put one of these values in a request to make the sandbox return a specific scenario. They let you test the paths that are hard to trigger on purpose, such as an empty result, a rate limit or a server error.
Magic values are case-insensitive and can appear anywhere in a field, so Acme test-no-match Ltd works too. Use one magic value per request.
| Value | Result |
|---|---|
test-no-match | Match & Enrich, Search, address resolution and locations in a geometry return no results (200, empty result). As an ID: 404. |
test-ambiguous | Match & Enrich returns 5 candidates, highest confidence_score first. |
test-esg-processing | ESG returns processing, then the result once you poll. See ESG processing. |
test-not-found | An ID lookup returns 404. ESG returns 200 with "status": "not_found". In Match & Enrich, Search and the location searches it acts like test-no-match. |
test-rate-limit | 429 Too Many Requests with Retry-After: 1. |
test-out-of-credits | 403 Forbidden with "message": "Allocated quota exceeded.", the error production returns when your account runs out of credits. |
test-server-error | 500 Internal Server Error, to test your retry logic. |
Where to put a magic value
| API | Field |
|---|---|
| Match & Enrich | Any value in identifiers, for example commercial_names |
| Search | Any value in query |
| Location Intelligence: resolve an address | address, company_name or company_id |
| Location Intelligence: locations in a geometry | geometry |
| Any endpoint with an ID in the path | The ID, for example /firmographics/v1/companies/test-not-found |
Not every value is an ID
test-ambiguous, andtest-esg-processingoutside ESG, are not valid IDs. In a path they get the same400as any other malformed ID.
Example: handling a rate limit
curl -i -X POST https://data.veridion.com/match/v6/companies \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/json" \
-d '{"identifiers": {"commercial_names": ["test-rate-limit"]}}'HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-Veridion-Sandbox: true{
"path": "/match/v6/companies",
"status": 429,
"error": "Too Many Requests",
"message": "Rate limit exceeded: 1 request per second, burst 1. Retry after 1 second."
}Errors use the same structure as in production. See API Response codes.
ESG processing
In production, ESG data for a company that hasn't been analyzed yet takes a while: the first call starts the analysis and returns a processing session that you poll. Use test-esg-processing as the veridion_id on any single-company ESG endpoint to test that flow.
-
Call the ESG endpoint. It returns
processingand a session ID:curl https://data.veridion.com/esg/v1/companies/test-esg-processing/scores \ -H "Authorization: Bearer your_access_token"{ "veridion_id": "test-esg-processing", "status": "processing", "active_processing_session": "72854137-337e-40fd-9608-47998d8e7466", "last_computed_at": null, "result": null } -
Poll the session:
curl https://data.veridion.com/esg/v1/processing/72854137-337e-40fd-9608-47998d8e7466 \ -H "Authorization: Bearer your_access_token"{ "veridion_id": "test-esg-processing", "module": "scores", "status": "complete", "result_count": 1 } -
Call the ESG endpoint again. It returns
"status": "complete"and the result.
After the result is served, the next call starts a new processing session, so you can run the test again. Each account has its own sessions. If polling a session returns 404, start again from step 1.
Available endpoints
The sandbox serves these endpoints on the same paths as production.
| API | Endpoints |
|---|---|
| Match & Enrich | POST /match/v6/companies |
| Firmographics | GET /firmographics/v1/companies/{veridion_id} |
| Search | POST /search/v5/companiesPOST /search/v5/companies/summaryModules: supplier_discovery, company_lookup, company_verification, segmentation |
| Location Intelligence | POST /location-intelligence/v1/locationsPOST /location-intelligence/v1/geometry/locationsGET /location-intelligence/v1/locations/{location_id}GET /location-intelligence/v1/buildings/{building_id}GET /location-intelligence/v1/buildings/{building_id}/locationsGET /location-intelligence/v1/companies/{veridion_id}/locationsGET /location-intelligence/v1/companies/{veridion_id}/locations/summary |
| Corporate structure | GET /corporate-structure/v1/companies/{veridion_id}/ultimate-parent |
| Products & Services (coming soon) | GET /product-intelligence/v1/companies/{veridion_id}/productsGET /product-intelligence/v1/companies/{veridion_id}/servicesGET /product-intelligence/v1/companies/{veridion_id}/summary |
| ESG | GET /esg/v1/companies/{veridion_id}/scoresGET /esg/v1/companies/{veridion_id}/newsGET /esg/v1/companies/{veridion_id}/commitmentsGET /esg/v1/processing/{processing_session_id} |
Limits
- Rate limit. 20 requests per second, with bursts up to 30, per account. All your sandbox keys and APIs share it. Above it, the sandbox returns
429 Too Many RequestswithRetry-After: 1. This limit only protects the service and isn't your production rate limit; to test how your integration handles that one, usetest-rate-limit. - Credits. None. To test running out of credits, use
test-out-of-credits. - Account limits. The sandbox works the same for every account. Your account's production credits and limits don't apply to it.
Moving to production
- Replace the sandbox client ID and secret with your production ones. The base URL, paths, requests and response shapes stay the same.
- Remove magic values from your test data. In production they are ordinary input.
- Check your account's credits and limits: production calls spend credits and follow your account's limits.

