API Documentation
REST API reference for all UtilsToGo micro-utilities. Base URL: https://utils.bithub.org/api/v1
Authentication
Pass your API key in the X-API-Key header. Get your key from the Account page.
X-API-Key: utg_your_api_key_here
All stateless tool endpoints (text, encoding, hash, etc.) are also accessible without authentication, subject to per-IP rate limits.
Rate Limits
| Tier | API requests / min | URLs / month | Redirects / month |
|---|---|---|---|
| Anonymous (IP) | 60 | — | — |
| Free (API key) | 300 | 3 | 1,000 |
| Starter | 300 | 100 | 20,000 |
| Pro | 300 | 1,000 | 100,000 |
Rate limit errors return 429 Too Many Requests.
MCP Integration
UtilsToGo exposes a Model Context Protocol server. Connect any MCP-compatible client (Claude Desktop, Cursor, Zed, etc.).
{
"mcpServers": {
"utilstogo": {
"url": "https://utils.bithub.org/mcp",
"transport": "streamable-http"
}
}
}
Auto-discovery via /.well-known/mcp.json for WebMCP-compatible browser extensions.
Available MCP Tools
Short URLs
POST/api/v1/urls
Create a shortened URL.
// Request
{ "url": "https://example.com/long", "custom_code": "my-slug" }
// Response
{ "id": "...", "code": "2BKxmR", "short_url": "https://bbrl.uk/2BKxmR", "target_url": "..." }
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/urls \
-H "X-API-Key: utg_your_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# Python
import httpx
r = httpx.post("https://utils.bithub.org/api/v1/urls",
headers={"X-API-Key": "utg_your_key"},
json={"url": "https://example.com"})
print(r.json()["short_url"])
GET/api/v1/urls
List your short URLs with click counts.
curl -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/urls
→ [{"id":1,"short_code":"abc123","target_url":"https://example.com","clicks":42}]
GET/api/v1/urls/{id}/stats
Analytics for a URL. Free: count only. Starter: devices + referrers. Pro: full time-series.
curl -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/urls/1/stats
→ {"short_code":"abc123","clicks":42,"referrers":[{"source":"twitter.com","count":18}],"countries":[{"country":"GB","count":25}]}
DELETE/api/v1/urls/{id}
Delete a short URL and its click history.
curl -X DELETE -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/urls/1
→ {"deleted": true}
QR Codes
POST/api/v1/qr
Generate a QR code. qr_type: url | text | wifi | vcard
{ "qr_type": "url", "content": "https://example.com", "label": "My QR", "format": "png" }
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/qr \
-H "X-API-Key: utg_your_key" \
-H "Content-Type: application/json" \
-d '{"qr_type":"url","content":"https://example.com"}'
# Fetch the QR image
curl https://utils.bithub.org/api/v1/qr/{id}/image -o qr.png
GET/api/v1/qr/{id}/image
Returns the QR code as a PNG image.
curl / Python
# curl
curl -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/qr/123/image -o qr.png
# Python
import httpx
r = httpx.get("https://utils.bithub.org/api/v1/qr/123/image",
headers={"X-API-Key": "utg_your_key"})
open("qr.png", "wb").write(r.content)
Text Utilities
POST/api/v1/text/transform
Case conversion, slug, wrap. operation: uppercase | lowercase | titlecase | sentencecase | slug | wrap
{ "text": "hello world", "operation": "titlecase", "width": 80 }
→ { "result": "Hello World", "operation": "titlecase" }
POST/api/v1/text/count
Word, character, sentence, and paragraph counts.
{ "text": "Hello world" }
→ {"chars":11,"words":2,"lines":1,"sentences":1}
POST/api/v1/text/readability
Flesch-Kincaid, Gunning Fog, Coleman-Liau scores.
{ "text": "The quick brown fox jumps over the lazy dog." }
→ {"flesch_score":80.1,"grade_level":"6th","reading_time_seconds":2}
POST/api/v1/text/lorem
Generate Lorem Ipsum. { "count": 3, "unit": "paragraphs" }
{ "paragraphs": 2, "words_per_paragraph": 50 }
→ {"text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit..."}
POST/api/v1/text/regex
Test a regex pattern against input text. Returns all matches with positions.
{ "text": "foo bar baz", "pattern": "\\b\\w{3}\\b", "flags": "g" }
→ {"matches":["foo","bar","baz"],"count":3}
POST/api/v1/text/markdown
Convert Markdown to sanitised HTML.
{ "markdown": "# Hello\n**bold**" }
→ {"html":"<h1>Hello</h1>\n<p><strong>bold</strong></p>"}
POST/api/v1/text/html2text
Strip HTML tags and extract plain text.
{ "html": "<h1>Hello</h1><p>World</p>" }
→ {"text":"Hello\n\nWorld"}
POST/api/v1/text/escape
Escape/unescape for json | html | url | sql.
{ "text": "<script>alert('xss')</script>", "target": "html" }
→ {"escaped":"<script>alert('xss')</script>"}
Encoding / Decoding
POST/api/v1/encode/base64
Base64 encode or decode. direction: encode | decode
{ "input": "Hello World", "direction": "encode" }
→ { "result": "SGVsbG8gV29ybGQ=", "direction": "encode" }
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/encode/base64 \
-H "Content-Type: application/json" \
-d '{"input":"Hello World","direction":"encode"}'
# Python
import httpx
r = httpx.post("https://utils.bithub.org/api/v1/encode/base64",
json={"input": "Hello World", "direction": "encode"})
print(r.json()["result"]) # SGVsbG8gV29ybGQ=
POST/api/v1/encode/base32
Base32 encode/decode.
{ "text": "Hello", "operation": "encode" }
→ {"result":"JBSWY3DP"}
POST/api/v1/encode/url
URL percent-encode/decode.
{ "text": "hello world & more", "operation": "encode" }
→ {"result":"hello+world+%26+more"}
POST/api/v1/encode/html
HTML entity encode/decode.
{ "text": "<b>bold</b>", "operation": "encode" }
→ {"result":"<b>bold</b>"}
POST/api/v1/encode/jwt
Decode and inspect a JWT token (header + payload, no verification).
{ "payload": {"sub":"123","name":"Alice"}, "secret": "mysecret" }
→ {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWxpY2UifQ..."}
POST/api/v1/encode/hex
Hex encode/decode.
{ "text": "Hello", "operation": "encode" }
→ {"result":"48656c6c6f"}
POST/api/v1/encode/rot13
Apply ROT13 to text.
{ "text": "Hello World" }
→ {"result":"Uryyb Jbeyq"}
Hash / Checksum
POST/api/v1/hash/generate
Hash text. algorithm: md5 | sha1 | sha256 | sha512 | sha224 | sha384
{ "input": "hello", "algorithm": "sha256" }
→ { "hash": "2cf24dba5f...", "algorithm": "sha256", "input_length": 5 }
POST/api/v1/hash/hmac
{ "input": "...", "key": "secret", "algorithm": "sha256" }
{ "text": "message", "key": "secret", "algorithm": "sha256" }
→ {"hmac":"2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b"}
POST/api/v1/hash/crc32
CRC32 checksum of text.
{ "text": "Hello" }
→ {"crc32":"f7d18982","decimal":4157704578}
POST/api/v1/hash/bcrypt
bcrypt hash/verify. operation: hash | verify
{ "text": "mypassword", "rounds": 12 }
→ {"hash":"$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj4J/HS.iK0i"}
Data Conversion
POST/api/v1/convert/json
Format or minify JSON. operation: format | minify | validate
{ "input": "{\"a\":1}", "operation": "format", "indent": 2 }
POST/api/v1/convert/yaml
JSON ↔ YAML. direction: json_to_yaml | yaml_to_json
{ "input": "{\"name\":\"Alice\",\"age\":30}", "from": "json", "to": "yaml" }
→ {"result":"name: Alice\nage: 30\n"}
POST/api/v1/convert/xml
JSON ↔ XML.
{ "input": "{\"root\":{\"name\":\"Alice\"}}", "from": "json", "to": "xml" }
→ {"result":"<root><name>Alice</name></root>"}
POST/api/v1/convert/csv
CSV ↔ JSON array.
{ "input": "[{\"name\":\"Alice\",\"age\":30}]", "from": "json", "to": "csv" }
→ {"result":"name,age\nAlice,30\n"}
POST/api/v1/convert/toml
TOML → JSON.
{ "input": "{\"title\":\"Config\",\"port\":8080}", "from": "json", "to": "toml" }
→ {"result":"title = \"Config\"\nport = 8080\n"}
POST/api/v1/convert/ini
INI → JSON.
{ "input": "{\"db\":{\"host\":\"localhost\",\"port\":\"5432\"}}", "from": "json", "to": "ini" }
→ {"result":"[db]\nhost = localhost\nport = 5432\n"}
Date / Time
POST/api/v1/datetime/timestamp
Unix timestamp ↔ ISO 8601.
{ "unix": 1700000000 } → { "iso": "2023-11-14T22:13:20+00:00", ... }
{ "iso": "2023-11-14T22:13:20Z" } → { "unix": 1700000000, ... }
POST/api/v1/datetime/timezone
{ "datetime": "2026-01-15T12:00:00", "from_tz": "UTC", "to_tz": "America/New_York" }
{ "timestamp": 1700000000, "from_tz": "UTC", "to_tz": "America/New_York" }
→ {"converted":"2023-11-14T17:13:20-05:00","offset":"-05:00"}
POST/api/v1/datetime/diff
Days, weeks, months between two dates.
{ "start": "2024-01-01", "end": "2024-12-31" }
→ {"days":365,"weeks":52,"months":12,"years":1}
POST/api/v1/datetime/cron
Parse a cron expression and list next N run times.
{ "expression": "0 9 * * MON-FRI" }
→ {"next_runs":["2024-11-18T09:00:00","2024-11-19T09:00:00"],"description":"At 09:00 on every day-of-week from Monday through Friday"}
POST/api/v1/datetime/relative
Convert a date to "2 hours ago" / "in 3 days".
{ "timestamp": 1700000000 }
→ {"relative":"2 months ago","absolute":"2023-11-14T22:13:20Z"}
POST/api/v1/datetime/businessdays
Business days between two dates (excludes weekends).
{ "start": "2024-01-01", "end": "2024-01-31", "country": "GB" }
→ {"business_days":23,"holidays":["2024-01-01"]}
Math / Statistics
POST/api/v1/math/calc
Safe expression evaluator. Supports sqrt, sin, log, pi, factorial, etc.
{ "expression": "sqrt(2) * pi" } → { "result": 4.442882938..., "expression": "sqrt(2) * pi" }
POST/api/v1/math/convert
{ "value": 100, "from_unit": "km", "to_unit": "mi", "category": "length" }. Categories: length weight volume speed area data temperature
{ "value": 100, "from": "km", "to": "miles" }
→ {"result":62.137,"from_unit":"km","to_unit":"miles"}
POST/api/v1/math/percentage
Percentage calculations — of, change, increase/decrease.
{ "value": 75, "total": 200 }
→ {"percentage":37.5,"formatted":"37.5%"}
POST/api/v1/math/random
{ "min": 1, "max": 100, "count": 5, "type": "integer" }
{ "min": 1, "max": 100 }
→ {"value":42}
POST/api/v1/math/uuid
{ "count": 5, "version": 4 }
{}
→ {"uuid":"550e8400-e29b-41d4-a716-446655440000","version":4}
POST/api/v1/math/stats
Mean, median, mode, std dev, min, max, percentiles. { "data": [1,2,3,4,5] }
{ "numbers": [4,8,15,16,23,42] }
→ {"mean":18,"median":15.5,"std_dev":13.07,"min":4,"max":42}
POST/api/v1/math/baseconvert
{ "value": "255", "from_base": 10, "to_base": 16 }
{ "value": "255", "from_base": 10, "to_base": 16 }
→ {"result":"ff","from_base":10,"to_base":16}
Security
POST/api/v1/security/password
Generate cryptographically secure passwords.
{ "length": 24, "uppercase": true, "symbols": true, "count": 3 }
→ { "passwords": ["Xk#9mP...", ...], "entropy_bits": 157.6 }
POST/api/v1/security/verify
Verify text against a hash. { "input": "hello", "hash": "2cf24d...", "algorithm": "sha256" }
{ "hash": "$2b$12$LQv3c1yqBWVHxkd0LHAkCO...", "text": "mypassword" }
→ {"match":true,"algorithm":"bcrypt"}
POST/api/v1/security/cors
Check CORS policy for a URL. { "url": "https://api.example.com", "origin": "https://myapp.com" }
{ "url": "https://api.example.com", "origin": "https://app.example.com" }
→ {"cors_enabled":true,"allow_origin":"*","allow_methods":["GET","POST"]}
POST/api/v1/security/csp
Build a Content-Security-Policy header. { "directives": {"default-src": ["'self'"], "script-src": ["'self'", "cdn.example.com"]} }
{ "directives": {"default-src":["'self'"],"script-src":["'self'","https://cdn.example.com"]} }
→ {"policy":"default-src 'self'; script-src 'self' https://cdn.example.com","violations":[]}
POST/api/v1/security/jwt
Decode and inspect a JWT — header, payload, claims, expiry.
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk8azHhEqf-Q1w" }
→ {"header":{"alg":"HS256","typ":"JWT"},"payload":{"sub":"1234567890","name":"John Doe","iat":1516239022},"expired":false}
Network
POST/api/v1/network/ip
Geolocate an IP — country, region, city, ISP, ASN, timezone. Omit ip for your own.
{ "ip": "8.8.8.8" }
→ { "ip": "8.8.8.8", "country": "United States", "city": "Mountain View", "isp": "Google LLC", ... }
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/network/ip \
-H "Content-Type: application/json" \
-d '{"ip":"8.8.8.8"}'
# Python
import httpx
r = httpx.post("https://utils.bithub.org/api/v1/network/ip", json={"ip": "8.8.8.8"})
print(r.json()["country"])
POST/api/v1/network/dns
{ "domain": "example.com", "record_type": "MX" }. Types: A AAAA MX TXT NS CNAME SOA CAA SRV PTR
{ "domain": "example.com", "record_type": "A" }
→ {"records":[{"type":"A","value":"93.184.216.34","ttl":86400}]}
POST/api/v1/network/whois
WHOIS/RDAP for a domain — registrar, dates, nameservers.
{ "domain": "example.com" }
→ {"registrar":"IANA","created":"1995-08-14","expires":"2024-08-13","nameservers":["a.iana-servers.net"]}
POST/api/v1/network/port
{ "host": "example.com", "ports": [80, 443, 22], "timeout": 3 }. Up to 20 ports.
{ "host": "example.com", "port": 443 }
→ {"open":true,"host":"example.com","port":443,"response_ms":45}
POST/api/v1/network/headers
HTTP response headers + security score (HSTS, CSP, X-Frame-Options, etc.).
{ "url": "https://example.com" }
→ {"status":200,"headers":{"content-type":"text/html","server":"ECS"}}
POST/api/v1/network/ssl
TLS certificate details — expiry, issuer, SANs, days remaining.
{ "domain": "example.com" }
→ {"valid":true,"expires":"2025-03-15","issuer":"DigiCert Inc","days_remaining":120}
POST/api/v1/network/ping
TCP latency to a host (min/avg/max, packet loss). { "host": "google.com", "port": 80, "count": 4 }
{ "host": "example.com", "port": 80, "count": 3 }
→ {"reachable":true,"avg_ms":12.4,"min_ms":11.1,"max_ms":14.2}
URL / Link Utilities
POST/api/v1/link/parse
Parse a URL into scheme, host, path, query params, fragment.
{ "url": "https://example.com/path?foo=bar&baz=qux#section" }
→ {"scheme":"https","host":"example.com","path":"/path","query":{"foo":"bar","baz":"qux"},"fragment":"section"}
POST/api/v1/link/check
Check reachability and follow redirect chain. { "url": "https://example.com", "follow_redirects": true }
{ "url": "https://example.com" }
→ {"reachable":true,"status":200,"redirect_chain":[],"final_url":"https://example.com"}
POST/api/v1/link/utm
Build URLs with UTM campaign parameters.
{ "url": "https://example.com", "source": "newsletter", "medium": "email", "campaign": "spring" }
→ { "utm_url": "https://example.com?utm_source=newsletter&utm_medium=email&utm_campaign=spring" }
POST/api/v1/link/meta
Extract meta tags from any URL — title, description, keywords, robots, author.
{ "url": "https://example.com" }
→ {"title":"Example Domain","description":"This domain is for use in illustrative examples","og_title":null}
POST/api/v1/link/og
Open Graph + Twitter Card preview data — og:title, og:image, twitter:card.
{ "url": "https://github.com" }
→ {"og:title":"GitHub","og:description":"...","og:image":"https://github.githubassets.com/images/og.png","twitter:card":"summary"}
POST/api/v1/link/favicon
Find and verify the favicon for any domain.
{ "url": "https://github.com" }
→ {"favicon_url":"https://github.com/favicon.ico","format":"ico","size_px":null}
Image Utilities
All image endpoints accept multipart/form-data with a file field (max 20 MB). Binary endpoints return the processed image directly.
POST/api/v1/image/resize
Resize an image. Returns binary image.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/resize \
-F "file=@photo.jpg" -F "width=800" -F "height=600" \
-o resized.jpg
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/resize",
files={"file": f}, data={"width": 800, "height": 600})
open("resized.jpg", "wb").write(r.content)
POST/api/v1/image/crop
Crop to a region. Form fields: x y width height.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/crop \
-F "file=@photo.jpg" -F "x=100" -F "y=50" -F "width=400" -F "height=300" \
-o cropped.jpg
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/crop",
files={"file": f}, data={"x": 100, "y": 50, "width": 400, "height": 300})
open("cropped.jpg", "wb").write(r.content)
POST/api/v1/image/compress
Reduce file size. quality 1–95 for JPEG/WebP. optimise=true for PNG.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/compress \
-F "file=@photo.jpg" -F "quality=75" \
-o compressed.jpg
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/compress",
files={"file": f}, data={"quality": 75})
open("compressed.jpg", "wb").write(r.content)
POST/api/v1/image/convert
Convert format. format: png | jpeg | webp | gif.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/convert \
-F "file=@photo.jpg" -F "format=webp" \
-o photo.webp
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/convert",
files={"file": f}, data={"format": "webp"})
open("photo.webp", "wb").write(r.content)
POST/api/v1/image/placeholder
Generate placeholder. Form fields: width height bg_colour text_colour label. No file input needed.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/placeholder \
-F "width=400" -F "height=300" -F "label=400x300" \
-o placeholder.png
# Python
import httpx
r = httpx.post("https://utils.bithub.org/api/v1/image/placeholder",
data={"width": 400, "height": 300, "label": "400x300"})
open("placeholder.png", "wb").write(r.content)
POST/api/v1/image/palette
Extract dominant colour palette. Returns JSON with hex + RGB values.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/palette \
-F "file=@photo.jpg" -F "count=5"
# → {"palette":[{"hex":"#3a7bd5","rgb":{"r":58,"g":123,"b":213},"percentage":32.1},...]}
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/palette",
files={"file": f}, data={"count": 5})
print(r.json()["palette"])
POST/api/v1/image/exif-strip
Remove all EXIF metadata (privacy). Returns clean image.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/exif-strip \
-F "file=@photo.jpg" \
-o clean.jpg
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/exif-strip",
files={"file": f})
open("clean.jpg", "wb").write(r.content)
POST/api/v1/image/base64
Encode image to Base64 data URI. Returns JSON { "data_uri": "data:image/png;base64,..." }
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/base64 \
-F "file=@photo.jpg"
# → {"data_uri":"data:image/jpeg;base64,/9j/4AAQ..."}
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/base64",
files={"file": f})
print(r.json()["data_uri"][:50])
POST/api/v1/image/watermark
Add text watermark. Form fields: text position opacity font_size colour.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/image/watermark \
-F "file=@photo.jpg" -F "text=© 2024 Company" -F "position=bottom-right" -F "opacity=0.7" \
-o watermarked.jpg
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/image/watermark",
files={"file": f},
data={"text": "© 2024 Company", "position": "bottom-right", "opacity": 0.7})
open("watermarked.jpg", "wb").write(r.content)
Colour Utilities
POST/api/v1/colour/convert
Convert between HEX, RGB, HSL, HSV. Provide any one as input.
{ "hex": "#ff6600" }
→ { "hex": "#ff6600", "rgb": {"r":255,"g":102,"b":0}, "hsl": {"h":24,"s":100,"l":50}, "css": "rgb(255,102,0)" }
POST/api/v1/colour/name
Find nearest CSS named colour. { "hex": "#ff6347" } → { "name": "tomato", "distance": 0 }
{ "hex": "ff6347" }
→ {"name":"tomato","exact":true,"distance":0,"hex":"#ff6347"}
POST/api/v1/colour/contrast
WCAG contrast ratio. { "hex1": "#000000", "hex2": "#ffffff" } → ratio + AA/AAA pass/fail.
{ "hex1": "000000", "hex2": "ffffff" }
→ {"ratio":21.0,"aa_normal":true,"aa_large":true,"aaa_normal":true,"aaa_large":true}
POST/api/v1/colour/palette
Generate colour scheme. { "hex": "#3b82f6", "scheme": "triadic" }. Schemes: complementary, analogous, triadic, split_complementary, tetradic.
{ "hex": "3b82f6", "scheme": "triadic" }
→ {"colours":["#3b82f6","#f6a83b","#82f63b"],"scheme":"triadic"}
POST/api/v1/colour/mix
Blend two colours. { "hex1": "#ff0000", "hex2": "#0000ff", "weight": 0.5 } → #7f007f
{ "hex1": "ff0000", "hex2": "0000ff", "weight": 0.5 }
→ {"result":"#7f007f","rgb":{"r":127,"g":0,"b":127}}
Code Utilities
POST/api/v1/code/highlight
Syntax-highlight code as HTML with embedded CSS. 100+ languages, multiple Pygments themes.
{ "code": "def hello(): print('hi')", "language": "python", "theme": "monokai" }
→ { "html": "<div class=\"highlight\">...</div>", "css": "...", "language": "python" }
POST/api/v1/code/minify
Minify html | css | javascript. Returns minified code + size reduction stats.
{ "code": " body { color: red; } ", "language": "css" }
→ {"minified":"body{color:red}","original_size":22,"minified_size":14,"reduction_pct":36.4}
POST/api/v1/code/format/sql
Pretty-print SQL. { "sql": "select * from users", "keyword_case": "upper", "indent_width": 2 }
{ "sql": "select id,name from users where active=true", "keyword_case": "upper" }
→ {"formatted":"SELECT id,\n name\nFROM users\nWHERE active = true"}
POST/api/v1/code/stats
Code statistics — total lines, blank, comments, code lines, byte size. { "code": "...", "language": "python" }
{ "code": "def hello():\n # greet\n print('hi')\n", "language": "python" }
→ {"total_lines":3,"code_lines":2,"comment_lines":1,"blank_lines":0,"size_bytes":42}
Diff & Patch
POST/api/v1/diff/text
Generate a diff between two texts. style: unified | context | ndiff | html
{ "original": "foo\nbar", "modified": "foo\nbaz", "style": "unified" }
→ { "diff": "--- original\n+++ modified\n@@...", "added_lines": 1, "deleted_lines": 1, ... }
POST/api/v1/diff/patch
Apply a unified diff patch to original text. { "original": "...", "patch": "---\n+++ ..." }
{ "original": "foo\nbar\nbaz", "patch": "--- a\n+++ b\n@@ -2 +2 @@\n-bar\n+qux" }
→ {"result":"foo\nqux\nbaz","success":true}
POST/api/v1/diff/similarity
Similarity scores 0–100%. Returns char, word, and line similarity. { "text1": "...", "text2": "..." }
{ "text1": "The quick brown fox", "text2": "The quick red fox" }
→ {"char_similarity":88.9,"word_similarity":75.0,"line_similarity":0.0}
POST/api/v1/diff/merge
3-way merge with conflict markers. { "base": "...", "ours": "...", "theirs": "..." }
{ "base": "hello world", "ours": "hello earth", "theirs": "hello globe" }
→ {"result":"<<<<<<< ours\nhello earth\n=======\nhello globe\n>>>>>>> theirs","has_conflicts":true}
PDF Tools
All PDF endpoints accept multipart/form-data. Max file size 20 MB per file.
POST/api/v1/pdf/extract
Extract text from a PDF. Form fields: file + pages (all, 1, 1-3, 1,3,5).
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/pdf/extract \
-F "file=@document.pdf" -F "pages=1-3"
# Python
import httpx
with open("document.pdf", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/pdf/extract",
files={"file": f}, data={"pages": "1-3"})
print(r.json()["text"])
POST/api/v1/pdf/metadata
Page count, dimensions, author, title, creator, encryption status.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/pdf/metadata \
-F "file=@document.pdf"
# → {"title":"My Doc","author":"Alice","pages":12,"created":"2024-01-01"}
# Python
import httpx
with open("document.pdf", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/pdf/metadata",
files={"file": f})
print(r.json()["pages"])
POST/api/v1/pdf/merge
Merge 2–20 PDFs. Send multiple files fields. Returns binary PDF. Header x-page-count = total pages.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/pdf/merge \
-F "files=@a.pdf" -F "files=@b.pdf" -o merged.pdf
# Python
import httpx
r = httpx.post("https://utils.bithub.org/api/v1/pdf/merge",
files=[("files", open("a.pdf","rb")), ("files", open("b.pdf","rb"))])
open("merged.pdf","wb").write(r.content)
POST/api/v1/pdf/split
Extract pages as a new PDF. Form fields: file + pages (e.g. 2-4 or 1,3,5). Returns binary PDF.
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/pdf/split \
-F "file=@document.pdf" -F "pages=1-3" \
-o pages.pdf
# Python
import httpx
with open("document.pdf", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/pdf/split",
files={"file": f}, data={"pages": "1-3"})
open("pages.pdf", "wb").write(r.content)
AI Utilities
Powered by Claude. Requires a valid API key with AI access.
POST/api/v1/ai/summarise
Summarise text. style: bullet | paragraph | one_line
{ "text": "Long article...", "style": "bullet", "max_words": 100 }
→ { "summary": "• Key point 1\n• Key point 2\n...", "word_count": 42 }
POST/api/v1/ai/sentiment
Sentiment analysis. Returns sentiment (positive/negative/neutral/mixed), confidence, reasoning.
{ "text": "I absolutely love this product, it works great!" }
→ {"sentiment":"positive","confidence":0.97,"scores":{"positive":0.97,"neutral":0.02,"negative":0.01}}
POST/api/v1/ai/language
Detect language. Returns ISO 639-1 code, name, confidence, and alternatives.
{ "text": "Bonjour le monde" }
→ {"language":"French","code":"fr","confidence":0.99}
POST/api/v1/ai/alttext
Generate accessible alt text from an image upload (multipart/form-data).
curl / Python
# curl
curl -X POST https://utils.bithub.org/api/v1/ai/alttext \
-H "X-API-Key: utg_your_key" \
-F "file=@photo.jpg"
# → {"alt_text":"A golden retriever dog playing in a sunny park with a red ball"}
# Python
import httpx
with open("photo.jpg", "rb") as f:
r = httpx.post("https://utils.bithub.org/api/v1/ai/alttext",
headers={"X-API-Key": "utg_your_key"},
files={"file": f})
print(r.json()["alt_text"])
POST/api/v1/ai/translate
{ "text": "Hello", "target_language": "Spanish", "formality": "formal" } → { "translation": "Hola", "detected_source": "English" }
{ "text": "Hello, world!", "target_language": "Spanish" }
→ {"translated":"¡Hola, mundo!","source_language":"English","target_language":"Spanish"}
POST/api/v1/ai/grammar
Grammar and style check. Returns issues[], style_suggestions[], score, corrected_text.
{ "text": "Their going to the store, its very far." }
→ {"corrected":"They're going to the store; it's very far.","changes":[{"original":"Their","correction":"They're"},{"original":"its","correction":"it's"}]}
Webhooks
Register HTTPS endpoints to receive real-time POST notifications when events occur. Each delivery is signed with HMAC-SHA256 for verification. Requires authentication.
Available Events
POST/api/v1/webhooks
Register a new webhook. The secret is returned once — store it securely.
// Request
{ "url": "https://your-server.com/webhook", "events": ["url.clicked", "url.created"] }
// Response
{ "id": 1, "url": "...", "events": [...], "secret": "abc123...", "is_active": true, "created_at": "..." }
curl / Python + verification
# Create webhook
curl -X POST https://utils.bithub.org/api/v1/webhooks \
-H "X-API-Key: utg_your_key" \
-H "Content-Type: application/json" \
-d '{"url":"https://your-server.com/hook","events":["url.clicked"]}'
# Verify signature (Python)
import hmac, hashlib
def verify(body: bytes, secret: str, signature_header: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
GET/api/v1/webhooks
List all registered webhooks including status, failure count, and last triggered time.
curl -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/webhooks
→ [{"id":"uuid","url":"https://your-server.com/hook","events":["url.clicked"],"active":true,"created_at":"2024-01-01T00:00:00Z"}]
DELETE/api/v1/webhooks/{id}
Delete a webhook and stop all future deliveries.
curl -X DELETE -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/webhooks/uuid
→ {"deleted": true}
GET/api/v1/webhooks/{id}/deliveries
Get last 50 delivery attempts — event, payload, HTTP status, success flag, timestamp.
curl -H "X-API-Key: utg_your_key" https://utils.bithub.org/api/v1/webhooks/uuid/deliveries
→ [{"id":1,"event":"url.clicked","status":200,"delivered_at":"2024-01-01T00:00:00Z","response_ms":45}]
POST/api/v1/webhooks/{id}/deliveries/{delivery_id}/retry
Re-dispatch a previous delivery. Useful for replaying failed events. Returns 202 Accepted.
Delivery payload format
{
"event": "url.clicked",
"timestamp": 1709990400,
"data": { "code": "2BKxmR", "target_url": "https://example.com" }
}
Webhook is auto-disabled after 10 consecutive delivery failures. Re-enable via the dashboard.
OpenAPI Specification
Auto-generated OpenAPI 3.0 spec with full request/response schemas: