Skip to content
Core Concepts

Resource IDs

Every resource exposed through the Public API has a stable, prefixed identifier of the form <prefix>_<26 base32 chars>.

msg_01HXYZABCDEFGHJKMNPQRSTVWX
PrefixResource
msg_Message
cnv_Conversation
ctc_Contact
lbl_Label
tmpl_Template
wbs_Webhook subscription
wbd_Webhook delivery
evt_Event (KCKit envelope payload id)
key_API key
sec_Webhook signing secret
req_Request id (response envelope + X-Request-Id header)
org_Organisation
usr_User (conversation assignee)
  • Length: 4 (prefix) + 1 (_) + 26 (id body) = 31 characters total for most resources. tmpl_* is 32 chars (5-char prefix).
  • Alphabet: Crockford base32 (0-9 and A-Z minus I L O U). Always uppercase.
  • URL-safe: No characters require percent-encoding.
  • Permanent. Once Kirim hands you an id, that id refers to that exact resource for as long as the resource exists. Hard deletes remove the row entirely, but the id is never reused for a new row.
  • Opaque. The body of the id encodes no public meaning. Do not parse, decode, or sort by it. Order resources by created_at (always returned alongside).
  • Globally unique within Kirim. No two resources share an id, even across organisations.
  • Tenant-scoped retrieval. Every endpoint that takes an id enforces that the resource belongs to the caller’s organisation. A cross-org id returns 404 resource_not_found — never 403, to avoid leaking existence.

Internally Kirim uses 12-character nanoids as primary keys. The public id (msg_…) is stored on a separate column (external_id) and is the only id form ever returned through the API. If you see a shorter id-shaped string somewhere in a payload (e.g. assigned_to on conversations), it’s the internal user id — the only resource without an external_id contract in v1. A future migration may extend the usr_ prefix to users.

  • Don’t sort by id. Crockford base32 is lexicographic but the id body is not strictly time-monotonic across all resources. Sort by created_at instead.
  • Don’t substring-match prefixes for routing. Use the resource type implied by the endpoint, not the id prefix on the wire.
  • Don’t store IDs you didn’t get from Kirim. Generated ids (yours or anyone else’s) won’t match the storage format and will fail validation with 400 invalid_field_value.