Developers
HTTP API
Same specialised text-erase model as All text and Select in the editor. Authenticate with an API key from Account → Developer. Calls run on prepaid API credits (ladder below) or on the monthly credits from a plan on Pricing.
Base URL
https://api.erasetext.com/v1
Every path below is relative to this base. HTTPS only. OpenAPI: /openapi.json.
Authentication
X-Api-Key: et_…
Creating your first key grants a one-time 50 API credit trial — 50 calls, no card. After that a key spends your prepaid API credits first, then any monthly plan credits.
MCP
Agents can call the same erase path over MCP. The server is Streamable HTTP at https://api.erasetext.com/mcp. Send the same X-Api-Key (or Authorization: Bearer et_…). erase_text spends 1 credit on success; get_account, handshake and tool listing are free. Failures are not charged.
{
"mcpServers": {
"erasetext": {
"url": "https://api.erasetext.com/mcp",
"headers": { "X-Api-Key": "et_…" }
}
}
}Cursor, Claude Desktop, and other clients that speak remote MCP with headers work today. Hosted OAuth connectors are not shipped — use an API key. Manifest: /.well-known/mcp.json.
What a call costs
Every successful /erase spends 1 credit — one flat price, whatever the image size or output format. Failures are not charged, and neither is GET /account.
POST /erase
Multipart or JSON. Returns image bytes by default.
image_fileorimage_url— requiredmask_file/mask_url— optional; omit for all-text detectformat=webp|png|jpg— default webpresolution— short-edge target for the model, clamped to 256–1024, default 512paste_back— defaulttrue; keeps original pixels outside the erased areareturn_boxes=1— OCR quads inX-Ocr-Boxes. Only applies when you send no mask, since that is when detection runsresponse=json— return JSON with base64 instead of raw bytes
Mask polarity: white (any channel value above 127) marks what to erase, black keeps. Send it at the same aspect ratio as the image. Omit the mask and detection builds one for every piece of text it finds.
curl -X POST \ -H "X-Api-Key: et_…" \ -F "[email protected]" \ "https://api.erasetext.com/v1/erase" \ -o out.webp
The JSON body takes the same flags but different image fields — image_url or image_file_b64 (and mask_url / mask_file_b64):
curl -X POST \
-H "X-Api-Key: et_…" \
-H "Content-Type: application/json" \
-d '{"image_url":"https://…/photo.jpg","response":"json"}' \
"https://api.erasetext.com/v1/erase"Response
Raw image bytes with the matching Content-Type, plus these headers:
X-Credits-Charged— always 1 on successX-Credits-Remaining— API plus web balance after the callX-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(unix seconds)X-Ocr-Boxes— JSON quads, only withreturn_boxes=1
With response=json the body carries the same information instead:
{
"image_base64": "…",
"content_type": "image/webp",
"credits_charged": 1,
"credits_remaining": 199,
"ocr_boxes": null
}GET /account
curl -H "X-Api-Key: et_…" \ "https://api.erasetext.com/v1/account"
Returns the API and web balances, your plan, and this UTC month's call count and credits spent. It never spends a credit, so it is safe to poll before a batch.
Rate limits
Counted per API key in a sliding 60-second window. Requests over the limit return 429 with Retry-After; the limit follows the plan on the account that owns the key, and prepaid credits do not raise it.
| Plan | Requests / minute |
|---|---|
| Free | 6 |
| Lite | 30 |
| Pro | 120 |
| Volume+ | 300 |
Need more throughput than Volume+? Talk to us.
Limits and timing
- Image and mask must each be between 32 bytes and 25 MB, whether uploaded or fetched from a URL. JPEG, PNG and WebP are the safe input formats.
/eraseis synchronous: it holds the connection until the image is ready. Allow up to 90 seconds — past that you get504and are not charged. There is no callback or polling mode yet, so set a client timeout above 90s and retry the whole call.- A typical call lands in a few seconds; a cold model start is the slow case the timeout covers. Concurrency is bounded by your rate limit, so spread a batch across the minute rather than firing it all at once.
- Nothing you send is kept for the API path — bytes are processed in flight and the result is returned in the response. Only the web editor stores uploads, and those expire after an hour.
- The
/v1prefix is the contract: fields are only added, never removed or retyped. Breaking changes would ship as a new prefix.
Developers
API credits — volume ladder
Buy once, never expires, and the unit price drops as the pack grows. One call spends 1 credit, whatever the image size — so a pack’s credit count is the number of images it erases. These are API credits: your keys spend them first, and they are not used for editor downloads — that is why they cost a fraction of a web plan. Monthly Lite / Pro / Volume+ grants cover both and still reset on your billing date, see Pricing.
Starter
Try the API at volume rates.
$261,200 API credits · never expire
$0.022 / credit
Growth
Steady catalogue pipelines.
$665,000 API credits · never expire
$0.013 / credit
Scale
Product and media teams.
$19920,000 API credits · never expire
$0.010 / credit
Volume pack
Lowest unit price.
$666100,000 API credits · never expire
$0.007 / credit
Running 100,000+ credits a month? Talk to us for a dedicated rate.
Errors
Every failure is JSON shaped { "error": "…", "code": "…" }. Branch on code, not on the prose. Some codes add fields — 402 carries required and balance, 429 carries retryAfter.
| Status | code | When |
|---|---|---|
| 400 | bad_request | No image, unreadable base64, wrong Content-Type, file outside the size bounds, unfetchable URL, or a retired parameter (size, engine) |
| 401 | invalid_api_key | Missing, unknown or revoked key |
| 402 | insufficient_credits | API and web balance together cannot cover the call |
| 404 | not_found | Unknown path |
| 405 | method_not_allowed | Right path, wrong method — /erase is POST only |
| 429 | rate_limit | Over the per-key requests-per-minute limit |
| 429 | busy | The erase backend is saturated, not you — back off and retry |
| 500 | internal | Unexpected failure — safe to retry once |
| 502 | erase_failed | The model rejected or failed the job — not charged |
| 503 | misconfigured | Server-side configuration problem; retrying will not help |
| 504 | timeout | The model did not finish inside 90s — not charged, retry |