Skip to content
Make It Say

DEVELOPERS

Make It Say API: change the text in images from code

Send an image and the lines to change; get back a PNG with the new text in the same lettering. Base URL https://makeitsay.com/api/v1. Every request needs Authorization: Bearer mis_YOUR_KEY.

Get a key

Sign in, confirm your email address, and create a key on API keys. The key is shown once. Keep it out of shared code; anyone with it can spend the credits on your account. Revoke it there if it leaks.

POST /edits

Change the text in an image. JSON with image_url or image_base64 and replacements, or multipart with a file field and replacements as a JSON string. Optional hint says where the text is when it appears twice. Returns 202 with the edit. Add an Idempotency-Key header to retry safely: the same key returns the same edit and is not scanned or charged again.

curl https://makeitsay.com/api/v1/edits \
  -H "Authorization: Bearer $MAKEITSAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: menu-001" \
  -d '{ "image_url": "https://example.com/menu.jpg", "replacements": [ { "from": "$12", "to": "$14" }, { "from": "Tuesday", "to": "Wednesday" } ] }'

Response:

{
  "id": "2kFq…",
  "status": "working",
  "credits": 1,
  "changes": [
    { "from": "$12", "to": "$14", "box": [412, 188, 498, 231] },
    { "from": "Tuesday", "to": "Wednesday", "box": [120, 540, 380, 590] }
  ],
  "result_url": null
}

GET /edits/{id}

The edit. status is working, ready or failed (the credit is returned). When ready, result_url is the edited PNG, valid for one hour.

curl https://makeitsay.com/api/v1/edits/2kFq… \
  -H "Authorization: Bearer $MAKEITSAY_API_KEY"

Response:

{
  "id": "2kFq…",
  "status": "ready",
  "result_url": "https://…/results/2kFq….png?X-Amz-Signature=…",
  "result_url_expires_at": "2026-10-24T13:00:00.000Z"
}

POST /scans

Read the text without editing: every line with its box (0 to 1000 from the top left). Free; counts toward the scan limit.

curl https://makeitsay.com/api/v1/scans \
  -H "Authorization: Bearer $MAKEITSAY_API_KEY" \
  -F file=@menu.jpg

Response:

{
  "lines": [{ "text": "Lunch special $12", "box": [80, 180, 500, 235] }],
  "width": 1200,
  "height": 1600
}

GET /credits

Credits available on the account.

curl https://makeitsay.com/api/v1/credits \
  -H "Authorization: Bearer $MAKEITSAY_API_KEY"

Response:

{ "credits": 40 }

Errors

Errors are JSON: { "error": "code", "message": "…" }

StatuserrorMeaning
401unauthorizedMissing, wrong or revoked key.
402insufficient_creditsNo credits left.
400text_not_foundA "from" text is not in the image. The response has missing and lines.
400invalid_request, invalid_replacementsThe body is not what the endpoint expects.
400image_fetch_failedimage_url could not be downloaded over https within 10 seconds.
400, 413, 415bad_imageNot a PNG or JPG, or outside the size limits.
422documentAn ID or official document; refused, nothing charged.
404not_foundNo edit with this id on this account.
429rate_limited, quota, too_manyOver 120 requests a minute for this key, over the scan limit, or three edits already running.
503not_open, busyThe API or scanning is switched off for now.

Using Claude Code, Cursor or Codex? Connect over MCP →

Credits and limits

  • Same credits as the website: 1 credit per image, however many lines you change. Failed edits are not charged.
  • Images: PNG or JPG, 64 to 4096 pixels a side, up to 8.4 megapixels and 10 MB. Send a file, a public https URL, or base64.
  • Up to 20 lines per image, each up to 200 characters. "from" is the text as it appears in the image; an empty "to" removes the line.
  • The image is scanned first. If a "from" text is not in the image, nothing is charged and the response lists the lines that were read.
  • IDs, passports, licences, certificates, transcripts, receipts, invoices and bank documents are refused.
  • Scans count toward 30 an hour and 100 a day per account. Three edits can run at once.
  • The result is a PNG at the size of the original. Its URL works for one hour; get the edit again for a fresh one. The original and the result are kept 30 days, then deleted.
  • Each key allows 120 requests a minute. Keys are shown once; you can have 5 active keys.