API reference
MarkdownA small REST API for inspecting, cleaning and rewriting text and files, included with every plan. Base URL /api/v1. Create a key from API keys.
Authentication
Send the key as a bearer token. Keys are stored hashed, so the full value is shown once at creation and cannot be recovered afterwards.
curl https://gifi.ai/api/v1/usage \
-H "Authorization: Bearer wmr_live_..."Rate limits and credits
Limits are per key, per minute. Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds until the window rolls over), so you can pace yourself without waiting for a 429. A 429 adds Retry-After.
| Plan | Requests/min | Credits/month |
|---|---|---|
| Starter | 30 | 300 |
| Pro | 120 | 1,500 |
| Business | 600 | 6,000 |
Text inspect and text clean cost no credits. Cleaning a file costs one. Rewriting costs one credit per candidate. Failed jobs are refunded automatically, so you are never charged for work that did not complete.
POST /api/v1/inspect
/api/v1/inspectfreeReports what is present without modifying anything.
curl -X POST https://gifi.ai/api/v1/inspect \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Hello\u200bworld"}'curl -X POST https://gifi.ai/api/v1/inspect \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d "{\"file\": \"$(base64 -i photo.jpg)\", \"filename\": \"photo.jpg\"}"Text returns verifiable (each codepoint found, with offsets) and bestEffort (the writing-style heuristic). Files return the same findings the browser preview shows. They are separate because one is a countable fact and the other is a judgement.
POST /api/v1/clean
/api/v1/cleantext free · file 1 creditCleans text, or a file sent inline as base64.
curl -X POST https://gifi.ai/api/v1/clean \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"text": "The model\u2014which is large\u2014works."}'curl -X POST https://gifi.ai/api/v1/clean \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d "{\"file\": \"$(base64 -i photo.jpg)\", \"filename\": \"photo.jpg\"}"Inline files are capped at 3 MB, because the platform limits request bodies to 4.5 MB and base64 inflates a file by a third. Use the web app’s direct upload for anything larger.
POST /api/v1/rewrite
/api/v1/rewrite1 credit per candidateRewrites text so a statistical trail is no longer the original sequence. Best-effort.
curl -X POST https://gifi.ai/api/v1/rewrite \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Paste the marked prose here.", "strength": "paraphrase"}'You pick strength (paraphrase, humanize, code, backtranslate, structural). Routing is ours. The response does not name a host or model. A rewrite does not certify that any vendor detector will fail.
GET /api/v1/usage
/api/v1/usagefreeCredit balance, plan limits and the last 30 days of usage.
curl https://gifi.ai/api/v1/usage \
-H "Authorization: Bearer $KEY"Getting started
There is no sales call and no waiting list. Sign up, create a key, make the call.
- 1Inspecting text and cleaning invisible Unicode are free and run in your browser at https://gifi.ai — no account, no key, nothing uploaded.
- 2Create an account and issue a key yourself at https://gifi.ai/api-keys. It is shown once and stored only as a hash.
- 3
POST /api/v1/inspectcosts no credits, so you can exercise authentication and the response shape before spending anything. - 4Or issue a test key (
mode: "test") and run the whole API — including file cleaning — without a subscription and without spending a credit. See Sandbox below. - 5A plan is required for the billed endpoints — file cleaning and rewriting. Plans and limits are at https://gifi.ai/pricing.
Scopes are chosen per key, so a key issued for an agent can carry inspect alone and be unable to spend.
Sandbox
Create a test key and the whole API works without a subscription and without spending a credit. Keys beginning wmr_test_ run in sandbox; keys beginning wmr_live_ bill normally.
Sandbox is not a mock. Authentication, scopes, validation, rate limits and the cleaning engine are the real ones — a file you send is genuinely stripped and the actions you get back are the actions that were taken. What it does not do is spend credits or record a job, so nothing reaches your history and there is nothing for a retry to double-charge. Rewriting is the one exception: it returns the real response shape with your text unchanged, because calling a language model costs real money and inventing a rewrite would make an integration look correct while the output was a fiction.
Create one at https://gifi.ai/api-keys and choose "Test".
Errors
Failures are RFC 9457 problem documents, served as application/problem+json. Branch on code, not on the message: the message is written for a person and may be reworded.
{
"type": "https://gifi.ai/docs#error-insufficient_credits",
"title": "Insufficient credits",
"status": 402,
"detail": "Not enough credits",
"code": "insufficient_credits",
"hint": "Top up or upgrade at /pricing, then retry.",
"retryable": false,
"error": "Not enough credits"
}invalid_request400Invalid requestnot retryable- Fix the request body and send it again. Retrying it unchanged will fail the same way.
unauthenticated401Not authenticatednot retryable- Send a valid key as
Authorization: Bearer <key>. Create one at /api-keys, or see /auth.md for the OAuth flow. insufficient_credits402Insufficient creditsnot retryable- Top up or upgrade at /pricing, then retry. GET /api/v1/usage shows the current balance.
insufficient_scope403Missing scopenot retryable- Issue a key that carries the scope this endpoint needs, or request it during the OAuth flow.
subscription_required403No active subscriptionnot retryable- The API needs a plan. See /pricing. This is an account state, not a problem with the request.
not_found404Not foundnot retryable- Check the identifier. The same answer is returned whether a record belongs to another account or never existed, so this is not a signal that it exists elsewhere.
unsupported_format415Unsupported formatnot retryable- Gifi would rather refuse than return a partial strip. Call /api/v1/inspect first to see whether a format is supported.
payload_too_large413Payload too largenot retryable- Send a smaller file. Inline bodies are capped because the platform limits requests to 4.5 MB and base64 inflates a file by a third.
processing_failed422Processing failedretryable- Credits for a failed job are refunded automatically, so a retry costs you nothing beyond the call. If it fails twice on the same input, the input is the problem.
idempotency_in_flight409Idempotency key already in flightretryable- An earlier request with this Idempotency-Key has not finished. Wait and retry the same key — do not send a new one, or the work may run twice.
idempotency_key_reused422Idempotency key reused with a different bodynot retryable- This Idempotency-Key was already used for a different request. Generate a fresh key for a new request; reuse it only to retry the identical one.
rate_limited429Rate limitedretryable- Wait for the number of seconds in
Retry-After, then retry.RateLimit-Resetsays when the window rolls over. internal_error500Internal errorretryable- This one is ours. Retry with backoff; if it persists, send the response
codeand the time to support@gifi.ai. not_configured503Capability not configurednot retryable- This deployment cannot serve that endpoint. Retrying will not help until it is configured.
Retrying safely
Send an Idempotency-Key on POST /api/v1/clean and POST /api/v1/rewrite. The key is scoped to your account and the endpoint, bound to a hash of the body, and remembered for 24 hours.
Retrying with the same key and the same body replays the stored response with Idempotency-Replayed: true instead of repeating billed work. Reusing a key with a different body returns 422 rather than silently replaying the wrong answer. A retryable failure releases the key, so a refunded job can genuinely be retried.
Pagination
GET /api/v1/jobs is cursor-paginated. Read pagination.nextCursor and pass it back as cursor; null means the last page.
The cursor is anchored to the last row you saw rather than an offset, so jobs created while you page do not shift rows across page boundaries and make you read one twice.
Versioning
The major version is in the path. Additive changes ship in place, so ignore response fields you do not recognise.
A breaking change ships under a new path (/api/v2) rather than altering /api/v1 underneath you. A retiring operation returns Deprecation and Sunset response headers first, with at least 90 days between the announcement and the removal.
The machine-readable description is at /openapi.json.
MCP
Agents can call the same inspect, clean, rewrite and usage surface over MCP. Connect steps live on the agents page. Endpoint https://gifi.ai/mcp.
The server speaks OAuth 2.1 with PKCE S256 and Client ID Metadata Documents.
Scope of what the API can promise
Character removals and metadata actions are verifiable: every response names what was removed and you can confirm it independently. The writing-style score and any rewrite are best-effort. Nothing here certifies that content will pass or fail a third party’s AI detector — vendors publish neither detectors nor keys, so no tool can honestly make that claim. See terms for acceptable use.