Passports
A passport — a digital product passport (DPP) — is one product data record at a level of an ontology. Every passport has a globally unique id, a path within its ontology, property values, and a publish_status that is either set explicitly or inherited from its ancestors — except released, which a passport only ever has explicitly. Passports are addressed two ways: by their universal id, or by their path.
New to the model? Read the Data model first — it explains levels, the Singular/Series/Many types, paths (TPPMP), and how publish status is inherited. This page assumes those concepts.
The passport model
- Name
object- Type
- string
- Description
Always
passport.
- Name
id- Type
- string
- Description
Unique, universal identifier, e.g.
pass_3e9a1c5b7d2f4083. Resolves any passport at any depth viaGET /v1/passports/:id.
- Name
ontology- Type
- string
- Description
The id of the ontology this passport belongs to. Nullable.
- Name
parent- Type
- string
- Description
The parent passport's id.
nullfor the root.
- Name
level- Type
- string
- Description
The level key this passport sits at (e.g.
A,B). Nullable.
- Name
path- Type
- string
- Description
The passport's position within the ontology: the level key alone for the root (
A), otherwiseLEVEL:snowflake[/snowflake]. The snowflake segments are bare — nopass_prefix — and apathread off one response is a valid?path=argument on the next. Encoded as the TPPMP sort key, e.g.B:3e9a1c5b7d2f4083. Nullable.
- Name
friendly_id- Type
- string
- Description
Optional human-readable alias, unique within the parent. Nullable.
- Name
ontology_version- Type
- integer
- Description
The ontology version this passport is pinned to — the one it was created under. Reads render against this version's levels, and writes validate against its property definitions.
- Name
publish_status- Type
- string
- Description
The explicit status:
released,draft, orarchived.nullmeans it inherits from the parent chain — butreleasedis never inherited.
- Name
publish_status_resolved- Type
- string
- Description
The effective status after inheritance, on every read:
released,draft, orarchived, nevernull. A passport with no explicit status under a released ancestor resolves todraft.
- Name
release_number- Type
- integer
- Description
How many times the passport has been released,
0if never. It survives an un-release, so a re-release is number 2.
- Name
values- Type
- object
- Description
Property values keyed by the ontology's property ids, each wrapped in a
valueenvelope (see below). Always a JSON object —{}when the passport has no values yet, never[]— so the field's type never changes with its contents.
- Name
metadata- Type
- object
- Description
Caller-owned metadata bag. Always present,
{}when empty.
- Name
created_at- Type
- string
- Description
ISO 8601 timestamp of creation.
- Name
updated_at- Type
- string
- Description
ISO 8601 timestamp of the last update.
The pin is what a write is validated against. A property added in a later
ontology version is rejected on an older-pinned passport. Creation surfaces
are the exception — creating a passport or starting an import
validates against latest_version and pins the new passport to it, so a level
added in a new version is immediately creatable under a parent still pinned to
an old one.
Values
Writes take a flat map of property id → value; reads wrap every property in an envelope:
values on a read
{
"values": {
"property_capacity": { "value": 78.4 },
"property_serial": { "value": "KES-EVP-24-0917", "language": "en", "is_fallback": false }
}
}
Translatable types — short_text, long_text, tags, and file — carry language and is_fallback beside value; see Translated values. On a full read, a file or image value carries a short-lived download link inside value, next to its filename, extension, and size; list rows and the PATCH response return the stored file reference without a link.
There is no chart property type: charts are a section of the ontology's composition that plots ordinary numeric values.
Full reads
GET /v1/passports/:id and the find endpoint return the full shape, which adds:
- Name
discoverable_levels- Type
- array
- Description
The adjacent level keys the public passport traverses to from this one — its
singularandmanychildren, plus its parent unless it is the root.
- Name
discovery_chain- Type
- array
- Description
Every level key reachable from this one, in depth order — the traversal used to assemble the full passport.
- Name
granularity- Type
- object
- Description
Which passports this one reports as to the EU registry — see below.
List rows, and the response to a PATCH that changed something, omit these three fields.
Reported granularity
- Name
tier- Type
- string
- Description
The tier this passport's level reports as —
model,batch, oritem— ornullwhen the level is internal only.
- Name
model, batch, item- Type
- string
- Description
For each tier, the id of the nearest passport — this one or an ancestor — at the level marked
is_corefor that tier.nullwhen there is none on the way up, which includes every tier below this passport: resolution is upward only, and "every item in this batch" is a list query.
Levels declare their granularity and is_core on the ontology. If the EV Battery Pack ontology reported its product line as model, its packs as batch, and its cells as item, each level its tier's core, a cell would read:
granularity on a cell
{
"granularity": {
"tier": "item",
"model": "pass_5f0c8b3a6d1e4072",
"batch": "pass_3e9a1c5b7d2f4083",
"item": "pass_9c4e7a1d5b3f2064"
}
}
The block resolves against the ontology version the passport is pinned to. Resolving it costs one read per level, which is why list rows don't carry it.
List passports at a path
Lists — or searches — the passports under a path within an ontology. Paths start with the level key: B lists the passports at level B; deeper paths address a specific branch. Returns a paginated list of passports without the full-read fields. Requires passports:read.
Required attributes
- Name
path- Type
- string
- Description
The path to list under, e.g.
B, or a branch such asC:3e9a1c5b7d2f4083.
Optional attributes
- Name
search- Type
- string
- Description
Case-insensitive substring match on a passport's
friendly_idorid— not its name (up to 100 characters). Matching is a bounded scan, so a page can come back short, or empty, whilehas_moreis stilltrue: keep followingnext_cursorbefore concluding nothing matches.
- Name
lang- Type
- string
- Description
The language to read translated values in, or
all.
- Name
limit- Type
- integer
- Description
Page size, 1–100 (default 10).
- Name
cursor- Type
- string
- Description
A pagination cursor from a previous response's
next_cursor.
Request
curl -G https://api.synexcloud.com/v1/ontologies/ontology_7d1f4a2b9c3e5081/passports \
-H "Authorization: Bearer $SYNEX_API_KEY" \
-d path=B \
-d limit=10
Response
{
"object": "list",
"data": [
{
"object": "passport",
"id": "pass_3e9a1c5b7d2f4083",
"ontology": "ontology_7d1f4a2b9c3e5081",
"parent": "pass_5f0c8b3a6d1e4072",
"level": "B",
"path": "B:3e9a1c5b7d2f4083",
"friendly_id": "PACK-24-0917",
"ontology_version": 2,
"publish_status": "released",
"publish_status_resolved": "released",
"release_number": 1,
"values": {
"property_capacity": { "value": 78.4 },
"property_serial": { "value": "KES-EVP-24-0917", "language": "en", "is_fallback": false }
},
"metadata": { "batch_ref": "BATCH-2026-07" },
"created_at": "2026-07-22T14:10:43Z",
"updated_at": "2026-07-22T14:18:02Z"
},
{
"object": "passport",
"id": "pass_6b2d4f8a0c1e7359",
"ontology": "ontology_7d1f4a2b9c3e5081",
"parent": "pass_5f0c8b3a6d1e4072",
"level": "B",
"path": "B:6b2d4f8a0c1e7359",
"friendly_id": "PACK-24-0918",
"ontology_version": 2,
"publish_status": null,
"publish_status_resolved": "draft",
"release_number": 0,
"values": {
"property_capacity": { "value": 77.9 },
"property_serial": { "value": "KES-EVP-24-0918", "language": "en", "is_fallback": false }
},
"metadata": {},
"created_at": "2026-07-22T14:11:09Z",
"updated_at": "2026-07-22T14:11:09Z"
}
],
"has_more": true,
"next_cursor": "WyJvbnRvbG9neV83ZDFmNGEyYjljM2U1MDgxIl0",
"url": "/v1/ontologies/ontology_7d1f4a2b9c3e5081/passports"
}
Create a passport
Creates a passport at a level of the ontology, under a parent passport — start from the ontology's root_passport. singular levels allow one passport per parent (a second fails with 409 passport_exists_at_level); series and many levels allow any number. You never create level A — the root passport is created with the ontology, and trying to create it under a parent is a 400 parameter_invalid on level. The parent must also sit at the level the ontology declares as level's parent: you can't skip a level (creating C directly under an A) or hang a passport off the wrong branch — a mismatch is a 400 parameter_invalid on parent, and nothing is written. Requires passports:write. Accepts an optional Idempotency-Key header.
A team without a company — a supplier team — can't issue passports and is refused with 403 company_required. A create under an ontology with a passport transfer running is refused with 409 ontology_locked (see the note on Update a passport).
Required attributes
- Name
parent- Type
- string
- Description
The parent passport's id.
- Name
level- Type
- string
- Description
The level key to create at (e.g.
B).
Optional attributes
- Name
friendly_id- Type
- string
- Description
Human-readable alias, unique within the parent (
409friendly_id_takenotherwise).
- Name
metadata- Type
- object
- Description
Your own metadata for the new passport.
Request
curl https://api.synexcloud.com/v1/ontologies/ontology_7d1f4a2b9c3e5081/passports \
-H "Authorization: Bearer $SYNEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "parent": "pass_5f0c8b3a6d1e4072", "level": "B", "friendly_id": "PACK-24-0917" }'
Response
{
"object": "passport",
"id": "pass_3e9a1c5b7d2f4083",
"ontology": "ontology_7d1f4a2b9c3e5081",
"parent": "pass_5f0c8b3a6d1e4072",
"level": "B",
"path": "B:3e9a1c5b7d2f4083",
"friendly_id": "PACK-24-0917",
"ontology_version": 2,
"publish_status": null,
"publish_status_resolved": "draft",
"release_number": 0,
"values": {},
"metadata": {},
"created_at": "2026-07-22T14:10:43Z",
"updated_at": "2026-07-22T14:10:43Z"
}
Find a passport by path
Returns the single passport at an exact path, as a full read. Use this when you know a passport's position (e.g. the root at path A) rather than its id. Requires passports:read.
Required attributes
- Name
path- Type
- string
- Description
The exact path, e.g.
Afor the root.
Optional attributes
- Name
lang- Type
- string
- Description
The language to read translated values in, or
all.
Request
curl -G https://api.synexcloud.com/v1/ontologies/ontology_7d1f4a2b9c3e5081/passports/find \
-H "Authorization: Bearer $SYNEX_API_KEY" \
-d path=A
Response
{
"object": "passport",
"id": "pass_5f0c8b3a6d1e4072",
"ontology": "ontology_7d1f4a2b9c3e5081",
"parent": null,
"level": "A",
"path": "A",
"friendly_id": null,
"ontology_version": 1,
"publish_status": "released",
"publish_status_resolved": "released",
"release_number": 1,
"values": {
"property_line_code": { "value": "KES-EVP-LINE-01", "language": "en", "is_fallback": false }
},
"metadata": {},
"created_at": "2026-07-21T11:04:29Z",
"updated_at": "2026-07-21T11:09:52Z",
"discoverable_levels": ["B"],
"discovery_chain": ["B", "C"],
"granularity": { "tier": null, "model": null, "batch": null, "item": null }
}
Retrieve a passport
Retrieves a passport by its universal id — this works for any passport at any depth, without knowing its ontology or path. It's a full read: values (file and image values carry short-lived download links), the resolved publish status, traversal info, and reported granularity. Requires passports:read.
Optional attributes
- Name
lang- Type
- string
- Description
The language to read translated values in, or
all.
Request
curl https://api.synexcloud.com/v1/passports/pass_9c4e7a1d5b3f2064 \
-H "Authorization: Bearer $SYNEX_API_KEY"
Response
{
"object": "passport",
"id": "pass_9c4e7a1d5b3f2064",
"ontology": "ontology_7d1f4a2b9c3e5081",
"parent": "pass_3e9a1c5b7d2f4083",
"level": "C",
"path": "C:3e9a1c5b7d2f4083/9c4e7a1d5b3f2064",
"friendly_id": "CELL-24-0917-014",
"ontology_version": 2,
"publish_status": "released",
"publish_status_resolved": "released",
"release_number": 1,
"values": {
"property_cell_voltage": { "value": 3.671 }
},
"metadata": {},
"created_at": "2026-07-22T14:14:30Z",
"updated_at": "2026-07-22T14:16:11Z",
"discoverable_levels": ["B"],
"discovery_chain": ["A", "B"],
"granularity": { "tier": null, "model": null, "batch": null, "item": null }
}
Update a passport
Updates any combination of property values, friendly_id, publish_status, and metadata in one call. All values are validated against the property definitions of the passport's pinned ontology version before anything is written — a single bad value fails the whole values group with 400 value_invalid and per-property errors. Requires passports:write, plus releases:write to release a passport or take it out of release — see Releases.
The groups are applied as separate writes, in the order values → friendly_id → publish_status → metadata. Each is atomic — values is one write for the whole group — but the request isn't: a failure partway leaves the earlier groups applied. Two checks run before the first write: a status transition the release rules refuse, and the metadata limits — so a refused release or an over-limit bag leaves the values untouched. Send one group per request if partial application matters to you.
The response is the passport without the full-read fields, plus a release_run when the request started a release run. Every change emits one passport.updated event whose data.previous_attributes holds each changed field's value from before the request.
Optional attributes
- Name
values- Type
- object
- Description
A map of property id → new value. A translatable property also takes a map of language code → value, merged into its existing translations — see Translated values.
- Name
friendly_id- Type
- string
- Description
A new human-readable alias, unique within the parent.
- Name
publish_status- Type
- string
- Description
released,draft,archived, orautomatic. Settingautomaticclears the explicit status so the passport inherits again.
- Name
include_descendants- Type
- boolean
- Description
With
publish_status: "released"only: also release the passport's existing subtree, in a background release run.truewith any other status is a400parameter_invalid;falseis accepted on any request.
- Name
metadata- Type
- object
- Description
Merged per key into the passport's metadata.
While a passport transfer is running on the ontology, every group is
refused with 409 ontology_locked and nothing is written; reads are
unaffected, so retry once the transfer finishes. Transfers aren't
available yet, so nothing returns this code today.
A PATCH with an empty body changes nothing and returns the full-read shape, as GET does.
Request
curl -X PATCH https://api.synexcloud.com/v1/passports/pass_3e9a1c5b7d2f4083 \
-H "Authorization: Bearer $SYNEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"values": { "property_capacity": 78.4, "property_serial": "KES-EVP-24-0917" },
"friendly_id": "PACK-24-0917",
"publish_status": "released",
"include_descendants": true,
"metadata": { "batch_ref": "BATCH-2026-07" }
}'
Response
{
"object": "passport",
"id": "pass_3e9a1c5b7d2f4083",
"ontology": "ontology_7d1f4a2b9c3e5081",
"parent": "pass_5f0c8b3a6d1e4072",
"level": "B",
"path": "B:3e9a1c5b7d2f4083",
"friendly_id": "PACK-24-0917",
"ontology_version": 2,
"publish_status": "released",
"publish_status_resolved": "released",
"release_number": 1,
"values": {
"property_capacity": { "value": 78.4 },
"property_serial": { "value": "KES-EVP-24-0917", "language": "en", "is_fallback": false }
},
"metadata": { "batch_ref": "BATCH-2026-07" },
"created_at": "2026-07-22T14:10:43Z",
"updated_at": "2026-07-22T14:18:02Z",
"release_run": {
"object": "release_run",
"id": 4822,
"status": "pending",
"mode": "release",
"root": "pass_3e9a1c5b7d2f4083",
"total_count": 0,
"processed_count": 0,
"skipped_count": 0,
"failed_count": 0,
"created_at": "2026-07-22T14:18:02Z",
"updated_at": "2026-07-22T14:18:02Z"
}
}
Translated values
short_text, long_text, tags, and file properties hold one value per language, in any of the 24 official EU languages: bg cs da de el en es et fi fr ga hr hu it lt lv mt nl pl pt ro sk sl sv. Every other type holds a single value. Each ontology has a default language — the one its values are authored in.
Reading a language
The endpoints that return passport values — list, find, retrieve, and update — take ?lang=<code>. Each translatable value then reads in that language, with two fields beside value:
- Name
language- Type
- string
- Description
The language
valueis actually in.nullonly when the property has no translation at all, and thenvalueisnulltoo.
- Name
is_fallback- Type
- boolean
- Description
truewhenlanguageisn't the one you asked for.
Without ?lang, values read in the ontology's default language. When the requested language is missing, the value falls back to the default language, then to the first translation present in the code order above — and says so with is_fallback, so a missing Bulgarian text is never passed off as Bulgarian. Codes are case-insensitive and region subtags are dropped (DE and de-AT read as de); a code outside the 24 is ignored, and values read in the default language.
?lang=all reads value in the default language and adds translations: every language the property holds, keyed by code. On a full read, each translation of a file carries its own download link.
GET /v1/passports/pass_3e9a1c5b7d2f4083?lang=all
{
"values": {
"property_chemistry": {
"value": "NMC-811 lithium-ion",
"language": "en",
"is_fallback": false,
"translations": {
"de": "NMC-811-Lithium-Ionen",
"en": "NMC-811 lithium-ion"
}
}
}
}
A value stored without any language — written before its property held translations — reads as a plain value, without language or is_fallback, and counts as the default language. The next write to it stores it per language.
Writing a language
- A bare value writes the default language:
"property_chemistry": "NMC-811 lithium-ion". - A map of language codes writes those languages:
"property_chemistry": { "de": "NMC-811-Lithium-Ionen", "fr": "Lithium-ion NMC-811" }. Keys must be lowercase codes from the list — any other key (ru,DE,de-AT) fails withunsupported_language. - Writes merge: the languages you name are replaced, and the ones you leave out are kept.
- An explicit
null(or"", or[]) for a language deletes that translation:{ "fr": null }.
Text limits
Each translation is checked on its own: a short_text is at most 255 characters, a long_text 7,000, and a tags value at most 50 tags of up to 64 characters each. A translation is also capped at 14,000 bytes, which binds before the character limit only for a long_text in a script heavier than two bytes per character, such as CJK or emoji. A value over a limit fails the values group with 400 value_invalid, whose errors detail carries code value_too_long and the offending language. A value too large to store at all is 413 passport_too_large.
Dates
A date value is stored as the calendar day it names, always normalized to YYYY-MM-DD. The response echoes back that canonical form — a different string than you sent whenever you write another spelling — which is what keeps dates sortable and comparable with PassQL >, <, and between.
Accepted on write: 2026-07-22, 2026/07/22, 22 Jul 2026, July 22, 2026, 20260722, and ISO 8601 datetimes such as 2026-07-22T10:30:00Z (truncated to the day they name, with no timezone shift).
Rejected with 400 value_invalid / invalid_date: days that don't exist (2026-02-30, 2026-02-29), years outside four digits (99999-01-01), and relative expressions (next tuesday, tomorrow, +1 day) — a value whose meaning changes every time it's read is not a date.
Numeric dates are never guessed at
Whether 03/04/2026 means 3 April or 4 March is a fact about the writer's locale, not about the string, so the API refuses to pick one. A separator-delimited numeric date is rejected with 400 ambiguous_date whenever both readings are real days:
| Sent | Stored | Why |
|---|---|---|
13/05/2026 | 2026-05-13 | only day-first is a real date |
05/13/2026 | 2026-05-13 | only month-first is a real date |
03/03/2026 | 2026-03-03 | both readings agree |
03/04/2026 | 400 ambiguous_date | 3 April and 4 March are both real |
The same applies to - and . separators. Send YYYY-MM-DD and none of this applies to you.
This is deliberately strict for MM/DD/YYYY sources: a US-locale spreadsheet
pushed through imports fails on the rows whose day is 12 or less
and imports the rest. Rows are validated one at a time, so a rejected row is
simply never created — it lands in the import's failed rows with the
ambiguous_date cell named. Read them back with GET /v1/imports/:id/rows,
convert the column to YYYY-MM-DD at the source, and retry. Nothing has to be
un-imported, because the ambiguous values were never written.
Releases
released is the one publish status with rules of its own. draft and archived are labels; a release is a commitment — it is what the passport's public page serves, what a regulator may read, and — at the item tier's core level — what the team is billed for.
- Explicit, never inherited. A passport is released only when its own
publish_statussays so.draftandarchivedstill cascade down the chain; a passport with no explicit status under a released ancestor resolves todraft. - Its own ability.
publish_status: "released", and any move away fromreleased, needsreleases:writeon top ofpassports:write—403insufficient_permissionswithout it. Every other write needspassports:writealone. See Abilities. - Top-down. Every ancestor must be released first; otherwise the release is refused with
409ancestor_not_released, and the message names the nearest one that isn't. Anarchivedpassport may be released directly. - Locked while released. A
valuesorfriendly_idwrite, a move toarchived, andDELETEare all refused with409passport_released;metadatastays writable. Set it todraft(orautomatic) to edit, then release again — that re-release isrelease_number2. - Taken back bottom-up. Un-releasing a passport is refused with
409descendants_releasedwhile anything beneath it is still released. The exception is a passport at the level that carries the ontology'sitemtier as its core: taking its release back cancels the billed release, drafts the passport, and drafts its released descendants in adraft-mode release run, returned asrelease_runlike a cascade. A release already reported for billing can't be cancelled —409release_reported. - Checked first. A transition the rules refuse is checked before the
valuesandfriendly_idgroups of the same request are written, so a refused release leaves the values untouched. Filling a passport in and releasing it in one call works, because the values land while it is still editable. A release that moved between the check and the write — cancelled, or released again — is409release_conflict; re-read and decide again.
Releasing a subtree
Send include_descendants: true with publish_status: "released" to take the passport's existing subtree with it. The passport itself is released by the time the response is written; its descendants are released by a background run, returned as release_run on the response — poll it with Retrieve a release run. On a passport that is already released, the request starts the run without re-releasing the root.
- The cutoff. The run covers the passports that existed when the release was taken. Anything created afterwards is a new passport, released on its own terms.
- No re-releases. A descendant that is already released, or was released once and then taken back, keeps its own release number and is counted as skipped.
- The chain freezes. Until the run closes, releasing or un-releasing anything on its chain — the root, an ancestor, or a descendant — is refused with
409release_in_progress.
A single release or un-release emits passport.updated. A run emits only run-level events — release_run.started, then release_run.completed or release_run.failed — never one per descendant.
Delete a passport
Deletes the passport and releases its friendly_id for reuse within the parent. Requires passports:write. A released passport can't be deleted (409 passport_released), and neither can any passport while a transfer is running on its ontology (409 ontology_locked; see the note on Update a passport).
Deletion is not recursive. Only the named passport is removed. Passports beneath it survive, keep their ids and friendly ids, and stay readable — but their parent points at an id that returns 404 resource_missing. Delete a branch leaf-first to remove it whole.
Request
curl -X DELETE https://api.synexcloud.com/v1/passports/pass_9c4e7a1d5b3f2064 \
-H "Authorization: Bearer $SYNEX_API_KEY"
Response
{
"object": "passport",
"id": "pass_9c4e7a1d5b3f2064",
"deleted": true
}
Download a passport's QR code
Renders the QR code linking to the passport's public page — the same link the Synex app prints. Returns binary image data, so write it straight to a file. Requires passports:read.
Optional attributes
- Name
format- Type
- string
- Description
png(default),jpg,svg, orpdf.
- Name
size- Type
- integer
- Description
Pixel size, 64–2048 (default 512). A value outside that range is rejected with
400parameter_invalidrather than clamped.
Request
curl -G https://api.synexcloud.com/v1/passports/pass_3e9a1c5b7d2f4083/qr \
-H "Authorization: Bearer $SYNEX_API_KEY" \
-d format=png \
-d size=1024 \
-o passport-qr.png
Response
HTTP/1.1 200 OK
Content-Type: image/png
(binary QR image — PNG, JPG, SVG, or PDF per the `format` parameter)
The release run model
A release run is one release cascade: "release this passport and everything under it", or the same in reverse. It is opened by include_descendants on a release, or by taking back the release of an item-tier core passport — never by a request of its own. A run is bookkeeping, not a passport: it says how much of the subtree has been stamped, not what any of it now says.
- Name
object- Type
- string
- Description
Always
release_run.
- Name
id- Type
- integer
- Description
Unique identifier. Release runs are integer-keyed.
- Name
status- Type
- string
- Description
pendinguntil a worker picks the run up,runningwhile it fans out, thencomplete,partial(finished, withfailed_countpassports it could not stamp), orfailed(the run could not run at all — the root or the ontology was gone, or enumeration broke). A run that stops moving is swept and failed, so polling always ends.
- Name
mode- Type
- string
- Description
releasestamps the subtree released;drafttakes it back.
- Name
root- Type
- string
- Description
The passport the cascade is rooted at.
- Name
total_count- Type
- integer
- Description
Passports the run intends to touch. It accumulates as the run enumerates, so it can still be climbing while
statusisrunning— an early reading is not the final denominator.
- Name
processed_count- Type
- integer
- Description
Passports the run stamped.
- Name
skipped_count- Type
- integer
- Description
Passports the run deliberately stepped over — already released, created after the release was taken, cancelled meanwhile, or deleted. Skipping is a normal outcome and does not make a run
partial.
- Name
failed_count- Type
- integer
- Description
Passports the run could not stamp. Any at all makes the finished run
partial.
- Name
created_at- Type
- string
- Description
ISO 8601 timestamp of creation.
- Name
updated_at- Type
- string
- Description
ISO 8601 timestamp of the last progress update.
Retrieve a release run
Retrieves a release run's progress. Poll it until status is complete, partial, or failed; while it is pending or running, every release and un-release on its chain is refused with 409 release_in_progress. The id comes from the release_run on a PATCH /v1/passports/:id response.
Requires passports:read, and a key scoped to specific ontologies must cover the run's. A run belonging to another team, or an id that isn't a positive integer, is 404 resource_missing.
Request
curl https://api.synexcloud.com/v1/release_runs/4822 \
-H "Authorization: Bearer $SYNEX_API_KEY"
Response
{
"object": "release_run",
"id": 4822,
"status": "running",
"mode": "release",
"root": "pass_3e9a1c5b7d2f4083",
"total_count": 1240,
"processed_count": 875,
"skipped_count": 12,
"failed_count": 0,
"created_at": "2026-07-22T14:18:02Z",
"updated_at": "2026-07-22T14:18:44Z"
}