{"openapi":"3.1.0","info":{"title":"AI Remover Pro — Image metadata API","version":"1.0.0","description":"Strip image metadata, write GPS coordinates, and write SEO metadata. The body of every request is the raw image; options travel in the X-Image-Options header, base64-encoded so non-ASCII values survive a latin1 header channel. A successful strip or metadata call returns the processed image bytes, not JSON."},"servers":[{"url":"https://airemover.pro/image-api"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer <key>"},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"MetadataOptions":{"type":"object","description":"JSON object, base64-encoded into X-Image-Options. Unknown fields are REJECTED rather than ignored, so a typo cannot silently produce a file missing the field you asked for.","additionalProperties":false,"properties":{"gps":{"type":"object","description":"Geotag. Written to the EXIF GPS IFD.","required":["lat","lng"],"properties":{"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180}}},"keywords":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"String or array of strings. Written to EXIF XPKeywords."},"title":{"type":"string","maxLength":4000,"description":"Written to EXIF XPTitle and XMP dc:title."},"description":{"type":"string","maxLength":4000,"description":"Written to EXIF ImageDescription and XMP dc:description."},"artist":{"type":"string","maxLength":4000,"description":"Written to EXIF Artist and XMP dc:creator."},"copyright":{"type":"string","maxLength":4000,"description":"Written to EXIF Copyright and XMP dc:rights."},"altText":{"type":"string","maxLength":4000,"description":"Accessibility/SEO alt text. XMP Iptc4xmpCore:AltTextAccessibility."},"usageTerms":{"type":"string","maxLength":4000,"description":"XMP xmpRights:UsageTerms."},"webStatement":{"type":"string","maxLength":4000,"description":"Licence URL. XMP xmpRights:WebStatement."},"credit":{"type":"string","maxLength":4000,"description":"XMP photoshop:Credit."},"source":{"type":"string","maxLength":4000,"description":"XMP photoshop:Source."},"creatorTool":{"type":"string","maxLength":4000,"description":"XMP xmp:CreatorTool."},"dateTime":{"type":"string","maxLength":4000,"description":"EXIF DateTime."},"dateTimeOriginal":{"type":"string","maxLength":4000,"description":"EXIF DateTimeOriginal."},"dateTimeDigitized":{"type":"string","maxLength":4000,"description":"EXIF DateTimeDigitized."},"createDate":{"type":"string","maxLength":4000,"description":"XMP xmp:CreateDate."},"modifyDate":{"type":"string","maxLength":4000,"description":"XMP xmp:ModifyDate."}}},"StripOptions":{"type":"object","additionalProperties":false,"properties":{"mode":{"type":"string","enum":["full","ai-only"],"default":"full","description":"full removes everything removable; ai-only removes AI provenance, IPTC and XMP while keeping camera EXIF, GPS and the colour profile."}}}}},"paths":{"/health":{"get":{"summary":"Liveness check","security":[],"responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"service":{"type":"string"}}}}}}}}},"/openapi.json":{"get":{"summary":"This document","security":[],"responses":{"200":{"description":"OpenAPI document"}}}},"/v1/metadata":{"post":{"summary":"Write GPS coordinates and SEO metadata","description":"Merges into any existing EXIF, so camera make/model, capture date and orientation survive. Every XMP value is read back out of the finished bytes before being reported as written. HEIC is refused: adding metadata would require rebuilding the file's item table.","parameters":[{"name":"X-Image-Options","in":"header","required":false,"description":"base64 of a MetadataOptions object. At least one field is required.","schema":{"type":"string","description":"base64 of a JSON object"}}],"requestBody":{"required":true,"description":"The raw image bytes. Not multipart, not base64 — the body IS the file.","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/heic":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"The image with the metadata written","headers":{"X-Image-Report":{"description":"ASCII-escaped JSON describing what was done — see the service README.","schema":{"type":"string"}},"X-Quota-Limit":{"description":"Monthly allowance. Absent for an uncapped key.","schema":{"type":"integer"}},"X-Quota-Used":{"description":"Requests used this month. Absent for an uncapped key.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Requests left this month. Absent for an uncapped key.","schema":{"type":"integer"}}},"content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/heic":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Malformed options or image (UNKNOWN_FIELD, INVALID_OPTIONS, INVALID_GPS, INVALID_MODE, INVALID_FIELD, FIELD_TOO_LONG, OPTIONS_TOO_LARGE, EMPTY_IMAGE, NO_FIELDS, READ_FAILED)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"UNAUTHORIZED — missing, unknown or disabled key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"QUOTA_EXCEEDED — the key's monthly allowance is spent. Retrying will not help until next month.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"413":{"description":"TOO_LARGE — over the 20MB limit","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"415":{"description":"UNSUPPORTED_TYPE or TYPE_MISMATCH — the bytes do not match the declared content-type","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"422":{"description":"UNSUPPORTED_FORMAT or MALFORMED — the engine refused the file, with its own reason","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"RATE_LIMITED — per key, per minute. Retry-After is set.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"UNAVAILABLE — key verification, rate limiting or quota accounting could not reach the database","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/strip":{"post":{"summary":"Remove metadata","description":"Note: in-pixel watermarks such as Google SynthID live in the image data itself and cannot be removed by stripping metadata. When the input carried AI provenance, that caveat appears in the report's warnings.","parameters":[{"name":"X-Image-Options","in":"header","required":false,"description":"base64 of a StripOptions object.","schema":{"type":"string","description":"base64 of a JSON object"}}],"requestBody":{"required":true,"description":"The raw image bytes. Not multipart, not base64 — the body IS the file.","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/heic":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"The cleaned image","headers":{"X-Image-Report":{"description":"ASCII-escaped JSON describing what was done — see the service README.","schema":{"type":"string"}},"X-Quota-Limit":{"description":"Monthly allowance. Absent for an uncapped key.","schema":{"type":"integer"}},"X-Quota-Used":{"description":"Requests used this month. Absent for an uncapped key.","schema":{"type":"integer"}},"X-Quota-Remaining":{"description":"Requests left this month. Absent for an uncapped key.","schema":{"type":"integer"}}},"content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/heic":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Malformed options or image (UNKNOWN_FIELD, INVALID_OPTIONS, INVALID_GPS, INVALID_MODE, INVALID_FIELD, FIELD_TOO_LONG, OPTIONS_TOO_LARGE, EMPTY_IMAGE, NO_FIELDS, READ_FAILED)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"UNAUTHORIZED — missing, unknown or disabled key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"QUOTA_EXCEEDED — the key's monthly allowance is spent. Retrying will not help until next month.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"413":{"description":"TOO_LARGE — over the 20MB limit","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"415":{"description":"UNSUPPORTED_TYPE or TYPE_MISMATCH — the bytes do not match the declared content-type","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"422":{"description":"UNSUPPORTED_FORMAT or MALFORMED — the engine refused the file, with its own reason","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"RATE_LIMITED — per key, per minute. Retry-After is set.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"UNAVAILABLE — key verification, rate limiting or quota accounting could not reach the database","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"/v1/inspect":{"post":{"summary":"Read metadata without changing anything","requestBody":{"required":true,"description":"The raw image bytes. Not multipart, not base64 — the body IS the file.","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"image/heic":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Decoded analysis: format, metadata blocks present, EXIF fields and GPS, XMP, IPTC, C2PA attribution","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Malformed options or image (UNKNOWN_FIELD, INVALID_OPTIONS, INVALID_GPS, INVALID_MODE, INVALID_FIELD, FIELD_TOO_LONG, OPTIONS_TOO_LARGE, EMPTY_IMAGE, NO_FIELDS, READ_FAILED)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"UNAUTHORIZED — missing, unknown or disabled key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"402":{"description":"QUOTA_EXCEEDED — the key's monthly allowance is spent. Retrying will not help until next month.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"413":{"description":"TOO_LARGE — over the 20MB limit","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"415":{"description":"UNSUPPORTED_TYPE or TYPE_MISMATCH — the bytes do not match the declared content-type","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"422":{"description":"UNSUPPORTED_FORMAT or MALFORMED — the engine refused the file, with its own reason","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"429":{"description":"RATE_LIMITED — per key, per minute. Retry-After is set.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"503":{"description":"UNAVAILABLE — key verification, rate limiting or quota accounting could not reach the database","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}}}