For developers

ULID / request id decoder

Split one of our own prefixed ids, or a bare ULID, and read the exact UTC time it was minted - and say plainly when a prefix is not one of ours.

Free, no accountIn your browser

One of our own ids (ord_..., evt_...) or a bare ULID. Case and surrounding spaces do not matter.

Try

Result

number order · minted 2025-01-01 00:00:00.000 UTC

Decoded as a timestamp of 2025-01-01 00:00:00.000 UTC (1735689600000 ms since the Unix epoch) plus a 16-character random half.

  • Info

    Minted at 2025-01-01 00:00:00.000 UTC

    The first 10 characters encode a 48-bit millisecond timestamp: 1735689600000 ms since the Unix epoch, which is 2025-01-01 00:00:00.000 UTC.

  • Passed

    "ord_" is one of ours: number order

    The "ord" prefix matches our own id prefix table, so this id names a number order record rather than something else.

Decoded

Kind
number order
Created at (UTC)
2025-01-01 00:00:00.000 UTC
Unix milliseconds
1735689600000
Random half
7Q9K2XWM5A3N8PZ2
  • The time shown is when whichever service minted the id set its own clock to create it - it is not when you are reading this, and it is not proof the record it names still exists today.
  • The 16-character random half carries no decodable information at all; it is shown only because it is part of the id.

What this is

This ulid timestamp decoder splits the prefix off one of our own ids or a bare ULID, names the record kind from our prefix table when the prefix is one of ours, and decodes the first ten characters into the exact UTC moment the id was minted.

Every id our API hands back - an order's ord_..., an event's evt_..., a webhook delivery's whd_... - is a three-letter prefix in front of a ULID: a 26-character identifier that sorts by creation time because its first 10 characters are a millisecond timestamp written in Crockford's base32, and its last 16 are random. Splitting the prefix off and decoding those 10 characters is all this page does.

A prefix that is not in our own table is never guessed at. This tool only names a record kind when the prefix exactly matches one it knows; anything else is reported as not one of ours, because a prefix that merely looks like ours could belong to a completely different system.

How to read the result

The "Kind" row names the record a recognised prefix belongs to, or says plainly that the prefix is not one of ours, or that there was no prefix to begin with. "Created at (UTC)" and "Unix milliseconds" are the same moment written two ways, decoded straight out of the ULID's first 10 characters. "Random half" is the last 16 characters shown as-is - they carry no further information, which is why nothing is decoded out of them.

"Verifying one of our webhooks" uses this same decoding, by hand, on one of our own ids read out of a log line, after its own sections on signing, the retry schedule and every documented error code.

Common mistakes

What goes wrong most often, and how to tell.

  • Reading the decoded time as proof the record still existsThe timestamp is only the moment whichever service minted the id - it says nothing about whether the order, event or delivery it names was ever completed, or whether it has since been deleted. Treat it purely as a creation time, not as evidence of current state.
  • Typing an I, L, O or U and expecting it to decode anywayCrockford's base32, which the ULID specification uses, deliberately drops the letters I, L, O and U so nothing is ever confused with a 1 or a 0 - a ULID genuinely cannot contain any of those four letters, so one in your input is almost always a 1, 0 or 1 mistyped by whoever (or whatever OCR) copied it.

Questions

What people ask about this tool.

  • Our ids are a three-letter prefix in front of a ULID, and a ULID is designed to sort by creation time without a database needing to look anything up: its first 10 characters are literally a millisecond timestamp, so two ids created a second apart already sort in the right order as plain strings, with no separate created-at column required.
  • It means the three letters before the underscore do not match anything in our own id prefix table, so this tool refuses to guess what kind of record the id names. That is a deliberate choice: a prefix that happens to look like ours could belong to an entirely unrelated system, and naming a kind anyway would be a guess dressed up as a fact.
  • No. It only decodes the timestamp and prefix that are mathematically encoded inside the id's own characters - it makes no request to any API and holds no record of what actually happened to whatever the id names, so the time shown is a creation time only, never a current status.
  • A ULID is case-insensitive by design - the specification treats uppercase and lowercase Crockford base32 letters as identical - and this tool trims whitespace from both ends before splitting the prefix off, so a value copied with a stray space or in lowercase still decodes exactly the same way.

Sources

Every fixed value here comes from the provider’s own documentation. These pages change, so each says the day it was last read.

Use it from the API

The same check, as one request.

Request
curl -X POST https://resellerhq.com/api/tools/ulid-request-id-decoder \
  -H "Content-Type: application/json" \
  -d '{"id":"ord_01JGFJJZ007Q9K2XWM5A3N8PZ2"}'
Response
{
  "tool": "ulid-request-id-decoder",
  "input": {
    "id": "ord_01JGFJJZ007Q9K2XWM5A3N8PZ2"
  },
  "result": {
    "verdict": {
      "tone": "success",
      "headline": "number order · minted 2025-01-01 00:00:00.000 UTC",
      "summary": "Decoded as a timestamp of 2025-01-01 00:00:00.000 UTC (1735689600000 ms since the Unix epoch) plus a 16-character random half."
    },
    "findings": [
      {
        "id": "decoded-timestamp",
        "severity": "info",
        "title": "Minted at 2025-01-01 00:00:00.000 UTC",
        "detail": "The first 10 characters encode a 48-bit millisecond timestamp: 1735689600000 ms since the Unix epoch, which is 2025-01-01 00:00:00.000 UTC."
      },
      {
        "id": "recognized-prefix",
        "severity": "pass",
        "title": "\"ord_\" is one of ours: number order",
        "detail": "The \"ord\" prefix matches our own id prefix table, so this id names a number order record rather than something else."
      }
    ],
    "parts": [
      {
        "kind": "facts",
        "title": "Decoded",
        "rows": [
          [
            "Kind",
            "number order"
          ],
          [
            "Created at (UTC)",
            "2025-01-01 00:00:00.000 UTC"
          ],
          [
            "Unix milliseconds",
            "1735689600000"
          ],
          [
            "Random half",
            "7Q9K2XWM5A3N8PZ2"
          ]
        ]
      }
    ],
    "limits": [
      "The time shown is when whichever service minted the id set its own clock to create it - it is not when you are reading this, and it is not proof the record it names still exists today.",
      "The 16-character random half carries no decodable information at all; it is shown only because it is part of the id."
    ]
  }
}

Build on the same API this tool is part of: numbers, domains and mailboxes, one key.

Read the API

Company names and logos are trademarks of their owners, shown only to identify each service.