ID formats
Every ID shape on the Partner API surface — bare UUIDs, prefixed ULIDs, the app_ format, request IDs, event IDs, and the prefix-tolerance rule.
Three ID shapes cover every resource on the Partner API:
- Bare UUIDs — the underlying database keys, written into response bodies as-is for the top-level resources.
- Prefixed ULIDs —
<prefix>_<26 Crockford base32>for resources that benefit from a self-describing opaque id (jobs, content, scheduled posts, events, request IDs). - Custom shapes —
app_<24 hex>for SDK apps. That's the only exception.
You don't need to memorize the prefixes — every path param accepts the bare UUID too. See the tolerance rule below.
Catalog
Every resource you'll see at the boundary. This table is the source of truth; if you find an endpoint emitting something different, file a bug.
| Resource | Shape | Example |
|---|---|---|
| Organization | bare UUID | 2481fa5c-a404-44ed-a561-565392499abc |
| Project | bare UUID | 254a4ce1-f4ca-42b1-9e36-17ca45ef3d39 |
| Ad account | bare UUID | f7c3d2a1-b8e4-4f9c-a012-3e4f5a6b7c8d |
Social account (DB id) | bare UUID | 9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e |
| Webhook endpoint | bare UUID | 3f71a8b2-4c58-4d2e-b1e3-8e0a2ae5c0c1 |
| Webhook delivery | bare UUID | 5a2b3c4d-6e7f-4a8b-9c0d-1e2f3a4b5c6d |
| API key ID | bare UUID | c2037bb9-354d-4662-96b7-97a28ad6b6e1 |
| GitHub installation | integer | 56781234 |
| Content container | cnt_<ULID> | cnt_01HX9Y6K7EJ4T2ABCDEF01234 |
| Scheduled post | sp_<ULID> | sp_01HX9Z8M3RBJK9CDEF0123456 |
| Social account (public surface) | sa_<ULID> | sa_01HXA1NHK000AABBCCDDEEFF |
| Influencer | inf_<ULID> | inf_01HXA1NHK000AABBCCDDEEFF |
| Media asset | med_<ULID> or asset_<ULID> | med_01HXA4MNP5RSTUVWXYZABCD |
| Lease request | lreq_<ULID> | lreq_01HXB2J9FGHZMNOPQRSTUVWX |
| Job | job_<ULID> | job_01HX9Y6K7EJ4T2ABCDEF01234 |
| Event (webhook) | evt_<26> | evt_01KPM7QZEC6NJF4XJTCZRR6S3N |
| Request ID | req_<26> | req_RKT95R73PHHF5N1AMH9H2Q58MC |
| SDK app | app_<24 hex> | app_8ffb9410eb0eb848264f8a |
Some endpoints return the underlying bare UUID for a resource that also has a prefixed form — adAccountId, for example, is documented as aa_<ULID> on the public reference but today ships as a bare UUID drawn from the credentials row. Treat the shape you receive as opaque; path params tolerate either form.
Prefixed ULID format
<prefix>_<26 characters of Crockford base32>. Crockford base32 is the 32-character alphabet 0123456789ABCDEFGHJKMNPQRSTVWXYZ — no I, L, O, or U to avoid visual confusion.
- 26 chars carry 130 bits, slightly more than a UUID's 128. Collision risk is negligible.
- Not monotonic. We don't rely on the ULID time prefix for ordering; the leading chars are random entropy. Sort on
createdAt, not the id string. - Case-insensitive in spirit (Crockford), but we always emit uppercase body after the lowercase prefix. Don't re-case them before sending back.
The generator is shared across event IDs, request IDs, and every other prefixed ULID the API mints — same logic everywhere.
Request ID format
Every response carries X-Request-Id: req_<26 Crockford base32>. The same value appears as error.requestId in every 4xx/5xx body — copy that one line into a support ticket and we can pull the full trace.
HTTP/1.1 200 OK
X-Request-Id: req_RKT95R73PHHF5N1AMH9H2Q58MCIf you set your own X-Request-Id request header, we use it as-is (up to 128 chars) so your traces can span the proxy. Otherwise we mint one.
Event ID format
Webhook deliveries carry X-Layers-Event-Id: evt_<26 Crockford base32>. The id is stable across retries of the same event — dedupe on it in your handler. Replays (via POST /v1/webhook-deliveries/:id/replay) mint a fresh event id and set data.replayOf to the original delivery id.
SDK app format
The odd one out: SDK apps use app_<24 hex chars>, not a ULID. This pre-dates the partner ID conventions — SDK app IDs ship into customer binaries and the shorter hex form was baked into the client SDKs before the prefix catalog existed. They're still opaque; treat them as strings.
The tolerance rule
Every path param that documents a prefixed id also accepts the bare UUID. The handler strips the prefix if present and uses the remainder as the lookup key; it doesn't care which you sent.
GET /v1/content/cnt_01HX9Y6K7EJ4T2ABCDEF01234 ← prefixed
GET /v1/content/01HX9Y6K7EJ4T2ABCDEF01234 ← bareBoth resolve the same row. This is not a validation — a malformed id (wrong length, wrong charset) still falls through to a NOT_FOUND. Every content, scheduled-post, social-account, and leased-account path param behaves this way.
Tolerance runs one way. Responses always carry the canonical shape — we don't strip prefixes on the way out. Store whatever we hand you.
Which to use when
- Storing a reference in your system — save the exact string we returned. Don't normalize, don't re-prefix, don't parse it.
- Calling back with it — pass it through verbatim.
- Displaying to an end-user — the prefixed form (
cnt_01HX...) is the intended UX. It's self-describing at a glance and pastes cleanly into logs. - Grepping logs for a specific id — the prefixed form is unambiguous; the bare UUID form can collide with unrelated UUIDs in a large log corpus.