# ID formats (/docs/api/concepts/id-formats)



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 shapes** — `app_&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](#the-tolerance-rule) below.

## Catalog [#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_&lt;26>`                  | `evt_01KPM7QZEC6NJF4XJTCZRR6S3N`       |
| Request ID                      | `req_&lt;26>`                  | `req_RKT95R73PHHF5N1AMH9H2Q58MC`       |
| SDK app                         | `app_&lt;24 hex>`              | `app_8ffb9410eb0eb848264f8a`           |

<Callout>
  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.
</Callout>

## Prefixed ULID format [#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 [#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
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 [#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 [#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 [#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.

```http
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.

<Callout type="warn">
  Tolerance runs one way. **Responses always carry the canonical shape** — we don't strip prefixes on the way out. Store whatever we hand you.
</Callout>

## Which to use when [#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 [#see-also]

* [Common patterns — error envelope, request ID](/docs/api/getting-started/common-patterns#error-shape)
* [Jobs — job IDs and the polling pattern](/docs/api/concepts/jobs)
* [Webhooks — event IDs and delivery IDs](/docs/api/operational/webhooks)
* [Idempotency — partner-created IDs as stronger idempotency](/docs/api/operational/idempotency#partner-created-ids-as-an-alternative)
