Skip to main content

Resource IDs

Every Moda resource has a prefixed wire ID like cvs_01HT9WK8N3M2J4A5Z6P7Q8R9TV. The prefix disambiguates the resource type on sight and prevents cross-resource lookup mistakes.

Prefixes

Encoding: Crockford base32 (no I, L, O, U to avoid visual confusion). Case-insensitive.

The two rules

Requests — tolerant (either form)

For the resources in the table above, JSON body fields and path parameters both accept the prefixed form or a bare UUID string. Pass a UUID straight from your database or a tool response without re-encoding.
Tolerance is a convenience for integrators who already hold raw UUIDs from an older system. Always prefer prefixed form in new code. Three spots are exceptions:
  • Typed form required — drive item and folder references: the polymorphic /v1/drive/items/{item_ref} verbs (move, rename, delete), and the fld_… filter on GET /v1/drive/folders and GET /v1/drive/files. A bare UUID is ambiguous across item kinds there.
  • Typed form required — POST /v1/webhook_deliveries/{delivery_id}/redeliver, which wants the whd_… id and answers 404 for anything else.
  • Bare UUID required — the task_id query parameter on GET /v1/canvases/{id}/export-status, which answers 400 "task_id must be a UUID." for a prefixed value. The task_id that POST /v1/canvases/{id}/export hands back is already in that form, so pass it through unchanged.

Responses — prefixed for these resources

The id fields of the resources in the table above always come back prefixed, so if you store one from a response and pass it in later, you’re fine. Surfaces outside that table carry raw UUIDs in both directions: the website endpoints, the export task_id above, and the GET /v1/events activity log (its row id, plus the nested resource.id and resource.canvas_id). The evt_ prefix belongs to the webhook envelope below — not to activity-log rows.

Why this design

  • Prefixed IDs are self-describing. Pasting one in a log or a PR makes it immediately clear what kind of object it is.
  • Request tolerance avoids breaking callers who already hold bare UUIDs from an older system or an internal store.
  • Prefixed responses mean a stored reference is still self-describing the next time you use it.

In responses

Every id field belonging to the resource types in the table above comes back prefixed:
Store the prefixed form for future calls.

Webhook payloads

Webhook events carry a prefixed evt_… id:
Use id (the event ID) as an idempotency key in your webhook handler — it’s stable across retries.

Common wrong guesses

  • Assuming bodies reject bare UUIDs. They don’t — requests take either form. Only the drive item_ref / fld_… refs and POST /v1/webhook_deliveries/{delivery_id}/redeliver require the typed form.
  • Storing bare UUIDs from older responses. They work in path params today, but storing the prefixed form (from any current response) is safer for future use.
  • Parsing the prefix at the client to dispatch on resource type. Don’t — use the kind field on task envelopes or the response shape. Prefixes are for humans.
  • Passing a prefixed task_… to GET /v1/canvases/{id}/export-status. That query parameter is bare-UUID-only — 400 "task_id must be a UUID.". Forward the task_id from the export response verbatim.
  • Assuming upl_ and file_ are interchangeable. upl_ is legacy; current uploads return file_. Don’t mix.

Upstream

docs.moda.app/api/authentication#resource-id-formats