/api/v1/registry/upload-fileBuild an EU DPP Registry upload file for battery passports
Builds the XML file the economic operator uploads on the EU DPP Registry website (DPP Registration → upload a file) for the **battery** passports you name, up to 100 per call. Registration is the operator's own act under its own EU Login; TracePass prepares the file and never submits it.
**Only passports that would pass go in.** The Registry fails the whole file on one bad entry, so every other passport comes back in `excluded` with its `reason`: `not_found`, `not_battery`, `not_published`, `registered_in_production`, `registration_in_progress` (being sent to an EN 18222 registry), `readiness_blocked` (the blocking findings are in `details`), `invalid_upi`, `duplicate_upi` (the same address as another passport in the file) or `over_limit` (past 100). `included` lists the passports in the file, each with its address.
Each included passport's address is frozen on the passport (`registryUpi`) and the preparation recorded (`registrationPreparedVia: "file"`). Save `xml` under `filename` and upload it unchanged: the name uses only the characters the Registry accepts. A preparation is not a registration: record the Registry's answer for each passport with `POST /api/v1/passports/{id}/registration`.
The response is JSON rather than raw XML, so it replays under `Idempotency-Key` and carries the exclusions. **Paid plans only** (`402` on Free). OAuth callers must act for an admin or owner. Counts one v1 write per passport included.
Headers
- Authorizationrequired
string
`Bearer <token>` — either a `tp_` API key (Developer → API Keys; simplest, for server-to-server) or an OAuth 2.0 access token (Developer → OAuth Apps; for user-authorized apps, scoped + revocable). The Authentication page has the full OAuth flow and scope list.
e.g. Bearer tp_REDACTED_xxxxxxxxxxxx
- Idempotency-Key
string
UUID v4.
Body fields
- passportIdsrequired
string[] (24 hex chars each, 1–100)
The passports to put in the file. Passports that would not pass are returned in `excluded` rather than failing the call.
e.g. ["6650b2c3d4e5f6a7b8c9d0e1", "6650b2c3d4e5f6a7b8c9d0e2"]
Request
curl -sS -X POST \
https://app.tracepass.eu/api/v1/registry/upload-file \
-H "Authorization: Bearer tp_REDACTED_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5a8d2f17-9c4e-4b3a-8e61-0f2c7d9b4e35" \
-d '{ "passportIds": ["6650b2c3d4e5f6a7b8c9d0e1", "6650b2c3d4e5f6a7b8c9d0e2"] }'Response
{
"xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n…",
"filename": "acme-batteries-dpp-registry-batch-2026-11-06.xml",
"included": [
{
"id": "6650b2c3d4e5f6a7b8c9d0e1",
"upi": "https://id.tracepass.eu/01/04012345000016/21/A1B2C3"
}
],
"excluded": [
{
"id": "6650b2c3d4e5f6a7b8c9d0e2",
"reason": "readiness_blocked",
"details": [
"Required field \"Battery Carbon Footprint — Total\" has no value."
]
}
]
}