AnvilJSON utilities

Anvil › Docs › /v1/ulid

ULID generator API: sortable 26-character IDs

A ULID packs the same amount of information as a UUID into 26 characters such as 01JB8ZQ7X4T9K2M3N5P6R7S8V0. The first 10 characters are the time in milliseconds and the last 16 are random, so sorting ULIDs as plain text sorts them by creation time.

In one line: GET /v1/ulid?count=3 returns JSON. No key, CORS on, 60 requests a minute.
GET

/v1/ulid

ULIDs: sortable, 26-character IDs. Change the values and press Send request to call the live API.

Parameters

NameTypeWhat it doesDefault
countintegerHow many, 1 to 1001

Example

Request:

GET https://api.oddlathe.com/v1/ulid?count=3

Response (generated by the real code when these docs were last built; random or time-based values will differ for you):

{
 "ulids": [
  "01M76NG22YE74801ZT43HG3523",
  "01M76NG22Y8XJ85V5EWY6DZ8S7",
  "01M76NG22YTTTGYY7BNGHNT7SY"
 ]
}

Code examples

curl
curl 'https://api.oddlathe.com/v1/ulid?count=3'
JavaScript (browser or Node 18+)
const params = new URLSearchParams({
  count: "3"
});
const res = await fetch(`https://api.oddlathe.com/v1/ulid?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);
Python (standard library only)
import json, urllib.parse, urllib.request

params = urllib.parse.urlencode({"count": "3"})
url = "https://api.oddlathe.com/v1/ulid?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
    data = json.load(r)
print(data)

When it's useful

  • Keys in key-value stores or file names where alphabetical order should equal time order
  • Short, URL-safe IDs without hyphens
  • Log or event IDs that you want to scan in time order

Good to know

  • Crockford base32 leaves out I, L, O and U so IDs are easy to read aloud and hard to mistype.
  • IDs made in the same millisecond share the time part and differ only in the random part; their relative order inside that millisecond is random.
  • ULIDs fit in a 128-bit UUID column if you decode them, but most people store them as text.

48-bit millisecond time + 80 random bits in Crockford base32. Lexicographically sortable and URL-safe.

Errors

Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:

  • bad_param (400): a value is the wrong type or out of range (the message says which)
  • rate_limited (429): over 60 requests a minute; wait for Retry-After seconds

Questions

ULID or UUID v7?

They carry the same idea. Pick UUID v7 if your database has a native UUID type; pick ULID if you store IDs as text and want them shorter and without hyphens.

Do ULIDs leak information?

They reveal the creation time to the millisecond, nothing else.

Related endpoints

Published · OpenAPI 3.1 spec · Limits and privacy