# Developer Utilities API — 20+ deterministic dev and AI-agent tools: hash, UUID, encode, JWT decode, cron, regex, format, data convert, color, mock data, diff, QR and more

> Hash/checksum text or binary (base64/hex) input: md5…sha3·blake2·crc32·adler32, optional HMAC keying → hex + base64 digests.
> ReefAPI engine `dev-utils` · 21 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/dev-utils/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /dev-utils/v1/hash — 1 credit
Hash/checksum text or binary (base64/hex) input: md5…sha3·blake2·crc32·adler32, optional HMAC keying → hex + base64 digests.

**Parameters:**
- `input` (string, required) — The data to hash. Plain text by default; set input_encoding=base64|hex to hash binary data.
- `algo` (enum, optional, default "sha256") — Hash/checksum algorithm. [one of: md5, sha1, sha224, sha256, sha384, sha512, sha3-256, sha3-512, blake2b, blake2s, crc32, adler32]
- `hmac_key` (string, optional) — Optional HMAC key — returns the keyed HMAC digest instead of the plain hash (not valid for crc32/adler32).
- `input_encoding` (enum, optional, default "text") — How to interpret `input`: utf-8 text, or base64/hex-encoded binary. [one of: text, base64, hex]

**Returns:** algo, hex, base64, base64url, length_bits, hmac (crc32/adler32: hex, decimal)

**Example request body:**
```json
{
  "input": "hello world",
  "algo": "sha256"
}
```

### POST /dev-utils/v1/uuid — 1 credit
Generate ids: uuid v4/v7/v1(MAC-safe)/v3/v5, ULID, nanoid — up to 100.

**Parameters:**
- `version` (enum, optional, default "v4") — Id kind. v4=random · v7=time-ordered (RFC 9562) · v1=timestamp (random multicast node — host MAC never leaks) · v3/v5=deterministic namespace+name (md5/sha1) · ulid=Crockford-base32 sortable · nanoid=21-char URL-safe. [one of: v4, v7, v1, v3, v5, ulid, nanoid]
- `count` (integer, optional, default 1) — How many ids to generate (v3/v5 always 1 — deterministic).
- `namespace` (string, optional) — v3/v5 namespace: dns|url|oid|x500 or a custom UUID.
- `name` (string, optional) — v3/v5 name to hash into the namespace.
- `size` (integer, optional, default 21) — nanoid length (nanoid only).

**Returns:** ids[], version, count, time_ordered (v7/ulid/v1), deterministic (v3/v5)

**Example request body:**
```json
{
  "version": "v4",
  "count": 3
}
```

### POST /dev-utils/v1/encode — 1 credit
Encode/decode: base64(+url-safe), hex, URL (path/component/form), HTML entities, unicode-escape, json-string.

**Parameters:**
- `input` (string, required) — The string to encode or decode.
- `op` (enum, required) — Codec. url=path-safe quote · url-component=encode everything (JS encodeURIComponent) · url-form=+ for spaces · html=entities · json-string=JSON string-literal escaping. [one of: base64, base64url, hex, url, url-component, url-form, html, unicode-escape, json-string]
- `direction` (enum, optional, default "encode") — encode (default) or decode. [one of: encode, decode]

**Returns:** output, op, direction, input_length, output_length

**Example request body:**
```json
{
  "input": "Merhaba Dünya! 👋",
  "op": "base64"
}
```

### POST /dev-utils/v1/jwt_decode — 1 credit
Decode a JWT WITHOUT needing the key (header+payload+claims analysis); optionally verify the signature with a provided key. Decode-only — this API never signs tokens.

**Parameters:**
- `token` (string, required) — The JWT to decode.
- `verify_key` (string, optional) — Optional verification key: the HMAC secret (HS*) or PEM public key (RS*/ES*/PS*). Algorithm is taken from the token header (whitelisted; alg=none always fails).

**Returns:** structure_valid, header{alg,typ}, payload, claims{exp/iat/nbf iso8601, expired, expires_in_seconds}, signature_checked, signature_valid, reason

**Example request body:**
```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "verify_key": "your-256-bit-secret"
}
```

### POST /dev-utils/v1/password — 1 credit
Generate cryptographically-secure passwords (charset controls, ambiguity filter) + entropy strength score; or score a provided password with `check`.

**Parameters:**
- `length` (integer, optional, default 16) — Password length.
- `count` (integer, optional, default 1) — How many passwords.
- `lowercase` (boolean, optional, default true) — Include a-z.
- `uppercase` (boolean, optional, default true) — Include A-Z.
- `digits` (boolean, optional, default true) — Include 0-9.
- `symbols` (boolean, optional, default true) — Include symbols (!@#$%^&*()-_=+[]{};:,.<>?/~).
- `exclude_ambiguous` (boolean, optional, default false) — Drop look-alikes (Il1O0o`'"|).
- `check` (string, optional) — Score THIS password instead of generating (entropy heuristic; the password is not stored or logged).

**Returns:** passwords[{password, strength{entropy_bits, score, verdict}}] — or with `check`: strength{} for the provided password

**Example request body:**
```json
{
  "length": 24,
  "count": 2
}
```

### POST /dev-utils/v1/cron — 1 credit
Explain a cron expression in plain language (15 locales) + compute the next N run times in any IANA timezone (DST-correct).

**Parameters:**
- `expression` (string, required) — 5-field cron (min hour dom month dow), @aliases (@daily, @hourly…), or 6-field with seconds first.
- `runs` (integer, optional, default 5) — How many upcoming run times to return.
- `tz` (string, optional, default "UTC") — IANA timezone for the run times (DST handled).
- `locale` (enum, optional, default "en") — Language of the human explanation. [one of: en, de, es, fr, it, nl, pl, pt, ro, ru, tr, uk, ja, ko, zh]
- `from_time` (string, optional) — Compute runs after this ISO-8601 instant (default now). Pin it for reproducible output.

**Returns:** valid, description (localized), next_runs[] (ISO-8601 with offset), tz, fields{minute,hour,day_of_month,month,day_of_week[,second]}

**Example request body:**
```json
{
  "expression": "*/15 9-17 * * 1-5",
  "runs": 3,
  "tz": "UTC",
  "from_time": "2026-06-10T12:00:00+00:00"
}
```

### POST /dev-utils/v1/slugify — 1 credit
URL-safe slug from any-script text (CJK/Cyrillic/Arabic → ASCII via anyascii transliteration).

**Parameters:**
- `input` (string, required) — Text to slugify.
- `separator` (string, optional, default "-") — Word separator (default '-').
- `lowercase` (boolean, optional, default true) — Lowercase the slug (default true).
- `max_length` (integer, optional, default 0) — Truncate at a word boundary (0 = no limit).

**Returns:** slug, original, transliterated, length

**Example request body:**
```json
{
  "input": "Çok Güzel Bir Başlık — 2026!"
}
```

### POST /dev-utils/v1/regex_test — 1 credit
Test a regex against text: matches + groups + named groups, optional replace. User patterns run with a hard 1s timeout (ReDoS-guarded) + size caps.

**Parameters:**
- `pattern` (string, required) — The regular expression (≤2000 chars; Python `regex` syntax — PCRE-compatible incl. \p{...}).
- `input` (string, required) — The subject text to scan.
- `flags` (string, optional) — Flag letters, any of: i (ignorecase), m (multiline), s (dotall), x (verbose). E.g. 'im'.
- `replacement` (string, optional) — Optional replacement template — when set, `replaced` holds the substituted text (backrefs \1, \g<name>).
- `max_matches` (integer, optional, default 100) — Cap on returned matches.

**Returns:** pattern_valid, match_count, matches[{match,start,end,groups[],named{}}], replaced (when replacement given), timed_out, truncated

**Example request body:**
```json
{
  "pattern": "(\\w+)@([\\w.]+)",
  "input": "mail jane@acme.com now"
}
```

### POST /dev-utils/v1/format — 1 credit
Pretty-print, minify or validate JSON / YAML / XML / SQL (string-level; file/data CONVERSION lives in the file-convert API).

**Parameters:**
- `input` (string, required) — The document text.
- `type` (enum, required) — Document type. [one of: json, yaml, xml, sql]
- `op` (enum, optional, default "pretty") — pretty | minify | validate (sql: pretty/minify only — sqlparse is non-validating). [one of: pretty, minify, validate]
- `indent` (integer, optional, default 2) — Indent width for pretty (json/yaml/xml).
- `sort_keys` (boolean, optional, default false) — Sort object keys (json/yaml).
- `keyword_case` (enum, optional, default "upper") — SQL keyword casing (sql only). [one of: upper, lower, capitalize]

**Returns:** valid, output (pretty/minify), error{message,line,column} on invalid, statement_count (sql)

**Example request body:**
```json
{
  "input": "{\"b\":1,\"a\":[1,2]}",
  "type": "json",
  "op": "pretty",
  "sort_keys": true
}
```

### POST /dev-utils/v1/convert — 1 credit
Convert structured data between JSON / YAML / CSV / XML at the string level (paste-in, ≤512KB). CSV↔JSON is tabular (array of flat objects). For file/Excel/multi-MB conversion use the file-convert API.

**Parameters:**
- `input` (string, required) — The source document text.
- `from` (enum, required) — Source format. [one of: json, yaml, csv, xml]
- `to` (enum, required) — Target format. [one of: json, yaml, csv, xml]
- `indent` (integer, optional, default 2) — Indent width for json/yaml/xml output (0=compact).
- `sort_keys` (boolean, optional, default false) — Sort object keys (json/yaml).

**Returns:** output, from, to, valid, error{message} on invalid/non-tabular input

**Example request body:**
```json
{
  "input": "[{\"id\":1,\"name\":\"a\"},{\"id\":2,\"name\":\"b\"}]",
  "from": "json",
  "to": "csv"
}
```

### POST /dev-utils/v1/qr — 1 credit
Generate a QR code as SVG (text), base64-PNG (text data-URI), or terminal ASCII — all textual output, no binary asset. Up to QR version 40.

**Parameters:**
- `input` (string, required) — The data to encode (URL, text, vCard, wifi string…).
- `kind` (enum, optional, default "svg") — Output: svg (scalable vector text) · png_base64 (base64 + data-URI) · text (terminal ASCII art). [one of: svg, png_base64, text]
- `error_correction` (enum, optional, default "m") — Recovery level: l~7% · m~15% · q~25% · h~30%. [one of: l, m, q, h]
- `scale` (integer, optional, default 4) — Module pixel size (png/svg).
- `border` (integer, optional, default 4) — Quiet-zone width in modules (spec default 4).

**Returns:** svg | png_base64+data_uri | text, version, error_correction, designator, modules, is_micro, mime

**Example request body:**
```json
{
  "input": "https://reefapi.com",
  "kind": "svg"
}
```

### POST /dev-utils/v1/color — 1 credit
Parse any CSS color (hex/rgb()/hsl()/name) → every format + CSS3 name + luminance; optional second color → WCAG 2.x contrast ratio + AA/AAA.

**Parameters:**
- `input` (string, required) — The color: '#1a2b3c', '#abc', 'rgb(26,43,60)', 'hsl(210,40%,17%)' or a CSS3 name ('rebeccapurple').
- `contrast_with` (string, optional) — Optional second color — returns the WCAG contrast ratio + AA/AAA pass flags for normal/large text.

**Returns:** hex, rgb{}, hsl{}, hsv{}, cmyk{}, alpha, name, nearest_name, luminance, is_dark + contrast{ratio, aa_normal, aa_large, aaa_normal, aaa_large}

**Example request body:**
```json
{
  "input": "#1a2b3c",
  "contrast_with": "#ffffff"
}
```

### POST /dev-utils/v1/mock_data — 2 credits
Generate fake/test records (Faker, 70+ locales): preset bundles (person/address/company/internet/profile/product/lorem) or a custom field→type schema; seed for reproducible output.

**Parameters:**
- `preset` (enum, optional) — Ready-made record shape (ignored when `schema` is given). [one of: person, address, company, internet, profile, product, lorem]
- `schema` (object, optional) — Custom shape: {output_field: type}. Types: address, bool, catch_phrase, city, color_hex, color_name, company, company_email, country, country_code, credit_card_full, credit_card_number, currency_code, date, date_of_birth, domain, email, emoji, file_name, first_name, float, free_email, iban, int, ipv4, ipv6, iso8601, job, language_code, last_name, latitude, locale, longitude, mac, mime_type, name, paragraph, password, phone, sentence, slug, ssn, state, street, text, time, url, user_agent, username, uuid, word, zip.
- `count` (integer, optional, default 5) — How many records.
- `locale` (string, optional, default "en_US") — Faker locale (en_US, tr_TR, de_DE, ja_JP…). Unknown locales fall back to en_US.
- `seed` (integer, optional) — Seed for deterministic output (same seed+schema+locale +count+faker-version → same records).

**Returns:** rows[], count, locale (resolved), preset|schema, seeded

**Example request body:**
```json
{
  "preset": "person",
  "count": 2,
  "seed": 42
}
```

### POST /dev-utils/v1/text_diff — 1 credit
Unified diff between two texts + change stats + similarity ratio.

**Parameters:**
- `a` (string, required) — The original text.
- `b` (string, required) — The changed text.
- `context` (integer, optional, default 3) — Context lines around each hunk.
- `label_a` (string, optional, default "a") — Label for the original.
- `label_b` (string, optional, default "b") — Label for the changed text.

**Returns:** diff (unified), identical, added_lines, removed_lines, hunks, similarity (0-1 SequenceMatcher ratio)

**Example request body:**
```json
{
  "a": "one\ntwo",
  "b": "one\n2"
}
```

### POST /dev-utils/v1/text_analyze — 2 credits
Algorithmic text analysis (no LLM): language detect (97 langs) · readability (Flesch & co) · profanity flag/censor · keyword extraction · full stats. Pick checks or get all.

**Parameters:**
- `input` (string, required) — The text to analyze.
- `checks` (array, optional) — Which analyses to run (default all): language, readability, profanity, keywords, stats.
- `top_keywords` (integer, optional, default 10) — How many keywords to extract.

**Returns:** language{language,confidence}, readability{flesch…, note}, profanity{contains_profanity,censored}, keywords[], stats{characters,words,sentences,…}

**Example request body:**
```json
{
  "input": "The quick brown fox jumps over the lazy dog. The fox is fast."
}
```

### POST /dev-utils/v1/timestamp — 1 credit
Parse/convert any timestamp ('now', unix s/ms/µs, ISO-8601, RFC-2822) → every format + timezone conversion + relative time.

**Parameters:**
- `value` (string, optional, default "now") — The timestamp. 'now' (default), unix seconds (≤10 digits), unix ms (12-14), unix µs (15-17), ISO 8601, or RFC 2822.
- `tz` (string, optional, default "UTC") — IANA timezone for the local-time outputs.

**Returns:** detected_format, unix, unix_ms, iso8601_utc, iso8601_local, rfc2822, tz, utc_offset, weekday, day_of_year, iso_week, is_leap_year, is_dst, relative ('3 hours ago')

**Example request body:**
```json
{
  "value": "1718000000",
  "tz": "Europe/Istanbul"
}
```

### POST /dev-utils/v1/case_convert — 1 credit
Convert identifier/text casing: camel·pascal·snake·kebab·constant·dot·title·sentence·upper·lower (+ detected input case).

**Parameters:**
- `input` (string, required) — The text/identifier to convert.
- `target` (enum, required) — Target case style. [one of: camel, pascal, snake, kebab, constant, dot, title, sentence, upper, lower]

**Returns:** output, target, detected_case, tokens[]

**Example request body:**
```json
{
  "input": "getUserProfileURL",
  "target": "snake"
}
```

### POST /dev-utils/v1/base_convert — 1 credit
Convert integers between bases 2-36 (arbitrary precision; 0x/0b/0o prefixes accepted).

**Parameters:**
- `input` (string, required) — The number (string). Prefixes 0x/0b/0o override from_base.
- `from_base` (integer, optional, default 10) — Source base (ignored if input has a prefix).
- `to_base` (integer, optional, default 10) — Target base.

**Returns:** output, decimal, binary, octal, hex, from_base, to_base, bits

**Example request body:**
```json
{
  "input": "ff",
  "from_base": 16,
  "to_base": 10
}
```

### POST /dev-utils/v1/markdown — 1 credit
Render CommonMark+tables markdown → sanitized HTML (raw HTML escaped, XSS-safe) + heading TOC with slugs.

**Parameters:**
- `input` (string, required) — The markdown source.

**Returns:** html, toc[{level,text,slug}], html_sanitized, stats{headings,html_bytes}

**Example request body:**
```json
{
  "input": "# Hello\n\nworld **bold**\n\n## Sub Title"
}
```

### POST /dev-utils/v1/user_agent — 1 credit
Parse a User-Agent string → browser/OS/device families + versions + bot flag (uap-core database).

**Parameters:**
- `input` (string, required) — The User-Agent header value.

**Returns:** browser{family,version}, os{family,version}, device{family,brand,model}, is_bot

**Example request body:**
```json
{
  "input": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
}
```

### POST /dev-utils/v1/batch — 1 credit
Run up to 100 mixed dev-utils calls in one request.

**Parameters:**
- `items` (array, required) — Up to 100 items, each {action, params}. Items run independently — a bad item yields its own error entry, never fails the batch.

**Returns:** count, ok_count, results[{action, ok, data|error}]

**Example request body:**
```json
{
  "items": [
    {
      "action": "hash",
      "params": {
        "input": "abc",
        "algo": "md5"
      }
    },
    {
      "action": "base_convert",
      "params": {
        "input": "1010",
        "from_base": 2
      }
    },
    {
      "action": "encode",
      "params": {
        "input": "x",
        "op": "nope"
      }
    }
  ]
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=dev-utils
- Human docs page: https://reefapi.com/docs/dev-utils
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
