TracePass
Passports

Mark a passport for deletion

**Step one of two.** Deleting a passport takes two steps: mark it for deletion here, then call `DELETE /api/v1/passports/{id}` (a never-published `draft` or `in_review` passport can be deleted directly). The delete is a soft delete: nothing is erased, but the passport disappears from the API and from every public surface. Scanning its QR code shows a page saying the passport has ended, and its machine-readable formats answer `410 Gone`.

POST/api/v1/passports/{id}/mark-for-deletion
Download OpenAPI 3.1
POST/api/v1/passports/{id}/mark-for-deletion

Mark a passport for deletion

**Step one of two.** Deleting a passport takes two steps: mark it for deletion here, then call `DELETE /api/v1/passports/{id}` (a never-published `draft` or `in_review` passport can be deleted directly). The delete is a soft delete: nothing is erased, but the passport disappears from the API and from every public surface. Scanning its QR code shows a page saying the passport has ended, and its machine-readable formats answer `410 Gone`.

A marked passport can no longer be edited, and marking a published passport frees its plan slot. A passport in any status except archived can be marked; marking it a second time answers `409 already_marked_for_deletion`. Fires the `passport.marked_for_deletion` webhook.

**Battery passports need a reason.** Under the Battery Regulation a battery passport ends only once the battery has been recycled (Art. 77(8)), so the request names why this one ends: `recycled`, `never_placed` (never placed on the market) or `duplicate_or_error`. Without one, a battery passport answers `400 reason_required`. For other categories `reason` is optional; when given, it must be one of the same three values.

**Refused while a newer passport links to it.** While a newer second-life battery passport in your account names this one as its predecessor, the mark answers `409 has_live_successor`; delete the newer passport first.

Deletion through the API needs a paid plan: on Free the mark answers `403 deletion_not_on_plan`. Counts as one v1 write. Honours `Idempotency-Key`. `POST /api/v1/passports/by-serial/{serial}/mark-for-deletion` is the by-serial alternate (it accepts the `?gtin=` disambiguator).

Path parameters

  • idrequired

    string (24 hex chars)

    Passport ID.

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

  • reason

    enum

    `recycled`, `never_placed` or `duplicate_or_error`. Required for battery passports, optional for other categories.

    e.g. recycled

Request

curl -sS -X POST \
  https://app.tracepass.eu/api/v1/passports/6650b2c3d4e5f6a7b8c9d0e1/mark-for-deletion \
  -H "Authorization: Bearer tp_REDACTED_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4f9c2a7e-1b3d-4c5e-8f60-7a8b9c0d1e2f" \
  -d '{ "reason": "recycled" }'

Response

{
  "_id": "6650b2c3d4e5f6a7b8c9d0e1",
  "status": "marked_for_deletion",
  "markedForDeletionAt": "2026-11-01T10:00:00.000Z",
  "markedForDeletionReason": "recycled"
}