Developers · Getting started

Test keys and dry runs

Build and test an integration against your real master data without storing anything: test keys, the X-DPP-Dry-Run header and the dry-run response.

Version
v1.0.0
Base URL
https://dppapi-production.up.railway.app/v1
Format
JSON · OpenAPI 3.1
FeedbackLast updated
On this pageTwo kinds of key

There is no separate sandbox to drift out of date. A test key works against your real organisation and real master data, validates every write exactly as production would, and stores nothing.

Two kinds of key

Live keyTest key
Prefixdpp_live_…dpp_test_…
ReadsYour dataYour data
WritesStoredDry run: validated, never stored
Rate limit600 requests / minute60 requests / minute
X-DPP-Mode response headerlivetest
WebhooksSent for real changesNever sent
UsageCountedNever counted

Create either kind in the app under Organisation → API keys. Both carry the same read / write scopes, and both need a plan that includes API access (Connected).

What a dry run checks

Everything a real write would check, in the same order: authentication and scope, the request schema, that every referenced id (a model, a passport) exists in your organisation, and the business rules. A request that would fail live fails the same way in a dry run.

A request that would succeed answers 200 with a body that says so, and nothing is written — no model, no passport, no event, no audit entry, no webhook:

Dry-run a batch with a test key
curl -X POST "https://dppapi-production.up.railway.app/v1/items/batch" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-d '{"modelId": "cm1q8x2k40003l70f9a8s7d6e","count": 100,"serialPrefix": "C48-2027-","placeOfManufacture": "Stuttgart, Germany"}'
200 OK · X-DPP-Mode: test · X-DPP-Dry-Run: true
{"dry_run": true,"valid": true,"operation": "POST /items/batch","mode": "test","checks": ["authentication", "scope", "plan", "schema", "ownership"],"message": "Validated only. Nothing was stored, no webhook was sent, and no usage was counted."}

dry_run, valid and operation are always present; the response also carries the header X-DPP-Dry-Run: true. Where the outcome depends on rules that can be checked without writing, the answer says what would happen:

OperationExtra in the dry-run answer
POST /modelscompleteness: whether the new model would be complete, and the model-level fields it would still owe.
POST /passports/{id}/publishwould_publish and blockers.
POST /passports/publishresults: per id, would_publish and blockers, or error: "not_found".

An id that is not in your organisation answers 404 with not_found, exactly as the real write would refuse it; an invalid body answers 400 with details.

One dry run with a live key

A live key can dry-run a single write by adding X-DPP-Dry-Run: true. Use it for a pre-flight check in production — "would this batch publish?" — without a second key.

Pre-flight a publish
curl -X POST "https://dppapi-production.up.railway.app/v1/passports/publish" \-H "Authorization: Bearer $DPP_API_KEY" \-H "Content-Type: application/json" \-H "X-DPP-Dry-Run: true" \-d '{"ids": ["cm1q8y0bq0006l70fx9y8z7w6"]}'

Know which mode you are in

Every response carries X-DPP-Mode: live or X-DPP-Mode: test, and GET /me reports the key. Assert it at start-up so a test key can never be deployed to production by mistake — a job that "succeeds" in test mode has created nothing.

Start-up assertion
const res = await fetch('https://dppapi-production.up.railway.app/v1/me', {headers: { Authorization: `Bearer ${process.env.DPP_API_KEY}` },});if (process.env.NODE_ENV === 'production' && res.headers.get('x-dpp-mode') !== 'live') {throw new Error('Refusing to start: production must use a live DPP key.');}

A testing strategy that works

  1. 1Develop against a test key. Your code sees real models and passports, and nothing you send can create or change one.
  2. 2Run CI with a test key. Contract tests exercise every write path; failures surface as the same 400/404/422 errors production would give.
  3. 3Pre-flight in production with X-DPP-Dry-Run: true before a large batch or publish.
  4. 4Go live by swapping the key. No code changes, no base-URL change.

Cookie preferences

You choose which cookies are used. You can change your choice at any time with “Cookie settings” in the footer. Privacy policy

Necessary

Always on

Needed for the site to work: your light/dark theme and this cookie choice are stored in your browser. They do not track you.

Analytics

Google Analytics 4 measures how pages are used through statistics, which helps us improve the site. If you accept, it sets cookies and measures your visit in full. If you decline, it sets no cookies, but Google may still receive technical data such as the page viewed, your browser type and IP address.

_ga, _ga_* · up to 2 years · Google