Layers
Partner APIConcepts

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.

View as Markdown

Three ID shapes cover every resource on the Partner API:

  1. Bare UUIDs — the underlying database keys, written into response bodies as-is for the top-level resources.
  2. Prefixed ULIDs<prefix>_&lt;26 Crockford base32> for resources that benefit from a self-describing opaque id (jobs, content, scheduled posts, events, request IDs).
  3. Custom shapesapp_&lt;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.

ResourceShapeExample
Organizationbare UUID2481fa5c-a404-44ed-a561-565392499abc
Projectbare UUID254a4ce1-f4ca-42b1-9e36-17ca45ef3d39
Ad accountbare UUIDf7c3d2a1-b8e4-4f9c-a012-3e4f5a6b7c8d
Social account (DB id)bare UUID9c1e42a0-b7f3-4e5d-a2c1-8b4f5e6c7d8e
Webhook endpointbare UUID3f71a8b2-4c58-4d2e-b1e3-8e0a2ae5c0c1
Webhook deliverybare UUID5a2b3c4d-6e7f-4a8b-9c0d-1e2f3a4b5c6d
API key IDbare UUIDc2037bb9-354d-4662-96b7-97a28ad6b6e1
GitHub installationinteger56781234
Content containercnt_<ULID>cnt_01HX9Y6K7EJ4T2ABCDEF01234
Scheduled postsp_<ULID>sp_01HX9Z8M3RBJK9CDEF0123456
Social account (public surface)sa_<ULID>sa_01HXA1NHK000AABBCCDDEEFF
Influencerinf_<ULID>inf_01HXA1NHK000AABBCCDDEEFF
Media assetmed_<ULID> or asset_<ULID>med_01HXA4MNP5RSTUVWXYZABCD
Lease requestlreq_<ULID>lreq_01HXB2J9FGHZMNOPQRSTUVWX
Jobjob_<ULID>job_01HX9Y6K7EJ4T2ABCDEF01234
Event (webhook)evt_&lt;26>evt_01KPM7QZEC6NJF4XJTCZRR6S3N
Request IDreq_&lt;26>req_RKT95R73PHHF5N1AMH9H2Q58MC
SDK appapp_&lt;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>_&lt;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_&lt;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_RKT95R73PHHF5N1AMH9H2Q58MC

If 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_&lt;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_&lt;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       ← bare

Both 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.

See also

On this page