Resource IDs
Every Moda resource has a prefixed wire ID likecvs_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.- Typed form required — drive item and folder references: the polymorphic
/v1/drive/items/{item_ref}verbs (move, rename, delete), and thefld_…filter onGET /v1/drive/foldersandGET /v1/drive/files. A bare UUID is ambiguous across item kinds there. - Typed form required —
POST /v1/webhook_deliveries/{delivery_id}/redeliver, which wants thewhd_…id and answers404for anything else. - Bare UUID required — the
task_idquery parameter onGET /v1/canvases/{id}/export-status, which answers400 "task_id must be a UUID."for a prefixed value. Thetask_idthatPOST /v1/canvases/{id}/exporthands back is already in that form, so pass it through unchanged.
Responses — prefixed for these resources
Theid 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
Everyid field belonging to the resource types in the table above comes back prefixed:
Webhook payloads
Webhook events carry a prefixedevt_… id:
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 andPOST /v1/webhook_deliveries/{delivery_id}/redeliverrequire 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
kindfield on task envelopes or the response shape. Prefixes are for humans. - Passing a prefixed
task_…toGET /v1/canvases/{id}/export-status. That query parameter is bare-UUID-only —400 "task_id must be a UUID.". Forward thetask_idfrom the export response verbatim. - Assuming
upl_andfile_are interchangeable.upl_is legacy; current uploads returnfile_. Don’t mix.
Upstream
docs.moda.app/api/authentication#resource-id-formats