Text tools
Eleven in-process string & document utilities — pure JavaScript, the same open-source libraries you could run yourself (jsdiff, node-diff3, marked, sanitize-html, html-to-text). Every op is a POST https://api.relaystation.ai/v1/text/<op> and returns a small JSON object — there is no file output.
Inputs
Most ops take either an inline text string or a file input source — { "inline": "<base64>" } (≤ 4 MB) or { "inputKey": "..." } (from POST /v1/cputools/upload-url, ≤ 50 MB) — exactly one. diff takes two strings a / b; apply-patch takes source + patch; merge3 takes base / yours / theirs; template takes a template string + a data object.
Billing
Every op bills per MB of input (min 1 MiB) at cputools.price.text.<op>.per_mb_micros (launch default $0.0002 / MB — a placeholder the operator tunes). The live 402 challenge is authoritative.
| Op | Billed on | Rate |
|---|---|---|
case | input MB | $0.0002 / MB |
slugify | input MB | $0.0002 / MB |
diff | input MB (a+b) | $0.0002 / MB |
apply-patch | input MB (source+patch) | $0.0002 / MB |
merge3 | input MB (base+yours+theirs) | $0.0002 / MB |
count | input MB | $0.0002 / MB |
regex-extract | input MB | $0.0002 / MB |
template | input MB | $0.0002 / MB |
markdown-to-html | input MB | $0.0002 / MB |
html-to-text | input MB | $0.0002 / MB |
sanitize-html | input MB | $0.0002 / MB |
case
Recase text. to is one of upper / lower / title / camel / snake / kebab. Returns { result }.
POST /v1/text/case
{ "text": "hello world", "to": "snake" }
slugify
URL-slugify: lowercase, strip diacritics, collapse non-alphanumeric to the separator (default -). Returns { slug }.
POST /v1/text/slugify
{ "text": "Héllo, World!" }
diff
Unified diff of two strings (a vs b). Returns { patch, changed }.
POST /v1/text/diff
{ "a": "line1\nline2\n", "b": "line1\nLINE2\n" }
apply-patch
The inverse of diff: apply a unified diff (patch) to a source string. Pairs with text/diff — diff produces the patch, apply-patch consumes it. Returns { result }. If the patch doesn’t apply cleanly (context mismatch), the call returns 422 PATCH_CONFLICT and the per-MB charge is refunded.
POST /v1/text/apply-patch
{ "source": "line1\nline2\n", "patch": "--- a\n+++ b\n@@ -1,2 +1,2 @@\n line1\n-line2\n+LINE2\n" }
merge3
Three-way merge of two divergent edits (yours, theirs) against a common ancestor (base) — the same model git merge uses. Returns { merged, conflict }. A clean merge returns the combined text with conflict: false; overlapping edits return the merged text with conflict markers (<<<<<<< / ||||||| / ======= / >>>>>>>) and conflict: true — the markers are the useful output, not an error.
POST /v1/text/merge3
{ "base": "a\nb\nc\n", "yours": "a\nB\nc\n", "theirs": "a\nb\nC\n" }
count
Count characters / words / lines + reading time. Returns { characters, charactersNoSpaces, words, lines, readingTimeMinutes } (wpm default 200).
POST /v1/text/count
{ "text": "one two three" }
regex-extract
Extract regex matches. The pattern is ReDoS-guarded: a catastrophic-backtracking pattern is rejected (422 UNSAFE_REGEX), the input is byte-capped, and the match count is bounded. Returns { matches, count, truncated }.
POST /v1/text/regex-extract
{ "text": "a1 b2 c3", "pattern": "([a-z])(\\d)" }
template
Render a logic-less mustache-subset template — no eval, no expression evaluation: {{var}} (HTML-escaped), {{{raw}}}, {{#section}}…{{/section}}, {{^inverted}}…{{/inverted}}. Lookups are own-property only (no prototype access). Returns { result }.
POST /v1/text/template
{ "template": "Hi {{name}}", "data": { "name": "Ada" } }
markdown-to-html
Render Markdown (GFM) → HTML, always run through the whitelist sanitizer — a <script> in your markdown can never reach the output. Returns { html }.
POST /v1/text/markdown-to-html
{ "text": "# Title\n\n**bold**" }
html-to-text
Convert HTML → plain text. Returns { text } (wordwrap default 80; pass false to disable).
POST /v1/text/html-to-text
{ "text": "<h1>Hi</h1><p>there</p>" }
sanitize-html
Sanitize HTML against a safe whitelist — drops <script>, event handlers, and javascript:/data: schemes (http/https/mailto only). Returns { html }.
POST /v1/text/sanitize-html
{ "text": "<p onclick=\"x()\">ok</p><script>bad()</script>" }