API v1
All systems operational

API Documentation

Integrate powerful image processing directly into your application. Remove backgrounds and prepare product images for e-commerce with a simple REST API.

QuickstartGet your API key
Base URL

Quickstart

Go from zero to your first processed image in under two minutes. OptikAPI speaks plain REST: send multipart/form-data, get back JSON with your image as a Base64 data URL.

1

Create an account

Sign up for free. Every new account gets 20 trial credits.

2

Generate an API key

Create a key in the dashboard. Keys are shown once — store them safely.

3

Make a request

POST an image to an endpoint and get the processed result back.

Your first request
curl -X POST https://your-domain.com/api/v1/remove-background \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@product.jpg"
Response
{
  "job_id": "job_9f3a2c1e",
  "status": "succeeded",
  "output_url": "data:image/png;base64,iVBORw0KGgoAAAANS...",
  "reserved_credits": 1
}
That's it. The image in output_url is a transparent PNG, ready to use. Decode the Base64 payload and save it — or pass it straight to your storefront.

Authentication

All API requests are authenticated with a Bearer token. Include your secret API key in the Authorization header of every request.

HTTP header
Authorization: Bearer optk_your_api_key_here

API keys start with optk_ and can be created or revoked at any time from the API Keys dashboard. Revoking a key takes effect immediately.

Never expose API keys in client-side code, browser JavaScript, or public repositories. Treat them like passwords. If a key leaks, revoke it from the dashboard and generate a new one.

Background Removal

POST
/api/v1/remove-background

Removes the background from an image with high precision — clean edges around hair, glass, and complex shapes. Costs 1 credit per successful image and returns a transparent PNG as a Base64 data URL.

For safe retries, send an Idempotency-Key header (1–200 visible ASCII characters). Reuse the same key with the same image and service: a completed job returns its saved result without another charge; a running job returns 202 with its job ID andRetry-After. A failed job returns its saved failure; use a new key for a new attempt. Reusing a key with different content or a different service returns 409. Keys belong to your account. Replayed responses include Idempotency-Replayed: true. File contents must match their declared JPEG, PNG, or WebP type. Files are limited to 10 MiB; the whole multipart body is limited to 10 MiB + 64 KiB. Suspended accounts receive 403.

Request Body

Format: multipart/form-data

ParameterTypeDescription
fileFile (required)Source image. Accepted types: JPEG, PNG, WebP. Max size: 10MB.

Response (200 OK)

FieldTypeDescription
job_idstringUnique job identifier. Use it with Get Job to retrieve details later.
statusstringAlways "succeeded" on a 200 response.
output_urlstringProcessed image as a Base64 data URL (image/png).
reserved_creditsnumberCredits charged for this job (1).

Code Examples

bash
curl -X POST https://your-domain.com/api/v1/remove-background \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@/path/to/image.jpg"

# Response (200):
# {
#   "job_id": "job_9f3a2c1e",
#   "status": "succeeded",
#   "output_url": "data:image/png;base64,...",
#   "reserved_credits": 1
# }

E-commerce Preparation

POST
/api/v1/prepare-product

An all-in-one pipeline: removes the background, centers the product with optical (not geometric) alignment, applies consistent margins, and places it on a clean white canvas. Costs 2 credits per successful image. Output is a 2000×2000 white-background image returned as a Base64 data URL.

Request Body

Format: multipart/form-data

ParameterTypeDescription
fileFile (required)Source product image. Accepted types: JPEG, PNG, WebP. Max size: 10MB.

Response (200 OK)

FieldTypeDescription
job_idstringUnique job identifier.
statusstringAlways "succeeded" on a 200 response.
output_urlstringProcessed 2000×2000 image as a Base64 data URL.
reserved_creditsnumberCredits charged for this job (2).

The processor returns the prepared image. Product classification, fill ratio, and centering measurements are not included in the response.

Code Examples

bash
curl -X POST https://your-domain.com/api/v1/prepare-product \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@/path/to/product.jpg"

# Response (200):
# {
#   "job_id": "job_7b1d4e8a",
#   "status": "succeeded",
#   "output_url": "data:image/png;base64,...",
#   "reserved_credits": 2
# }

Get Credits

GET
/api/v1/credits

Returns the current credit balance of the authenticated account. Use it to monitor usage and trigger alerts before you run out.

Example
curl https://your-domain.com/api/v1/credits \
  -H "Authorization: Bearer YOUR_API_KEY"

# Response (200):
# {
#   "credits": {
#     "total": 500,
#     "available": 492,
#     "reserved": 8
#   }
# }
FieldTypeDescription
credits.totalnumberTotal credits ever purchased or granted.
credits.availablenumberCredits you can spend right now.
credits.reservednumberCredits temporarily locked by in-flight jobs.

Get Job

GET
/api/v1/jobs/:job_id

Retrieves the status and result of a job by its ID. Image endpoints are synchronous — they return the final image immediately — so this endpoint is mainly useful for auditing, debugging, and checking a request that is still processing.

Example
curl https://your-domain.com/api/v1/jobs/job_7b1d4e8a \
  -H "Authorization: Bearer YOUR_API_KEY"

# Response (200):
# {
#   "job_id": "job_7b1d4e8a",
#   "status": "succeeded",
#   "service_type": "prepare-product",
#   "created_at": "2026-09-19T10:24:11.000Z",
#   "output_url": "data:image/png;base64,...",
#   "credits_consumed": 2
# }
FieldTypeDescription
job_idstringJob identifier.
statusstring"accepted", "processing", "succeeded", or "failed".
service_typestring"remove-background" or "prepare-product".
created_atstringISO 8601 creation timestamp.
output_urlstringResult data URL. Present only when status is "succeeded".
credits_consumednumberCredits charged. Present only when status is "succeeded".
errorstringFailure reason. Present only when status is "failed".
Jobs belong to the account that created them. Requesting another account's job returns 404 NOT_FOUND, as does an unknown ID.

Limits & Queue

Rate limits

The API allows 300 requests per minute per account across all /api/v1/* endpoints. Exceeding it returns 429 RATE_LIMITED with a Retry-After header telling you exactly when to try again.

Fair-use concurrency queue

Each account may run up to 3 image jobs concurrently. Requests beyond that wait in a FIFO line for up to ~20 seconds instead of failing, which makes bursty catalog imports work smoothly without any client-side throttling.

If the waiting line is full or a request waits too long, the API responds with 429 and one of two error codes — always with a Retry-After header:

CodeMeaningWhat to do
QUEUE_FULLThe waiting line for your account is full.Back off and retry after the Retry-After seconds.
QUEUE_TIMEOUTYour request waited ~20s without getting a slot.Retry; reduce burst size or add a short delay between requests.
Queued-out jobs never consume credits. Credits are only reserved once your job actually starts processing, and they are fully refunded if processing fails.

Error Codes

OptikAPI uses standard HTTP status codes. Every error response has the same shape — a machine-readable code and a human-readable message:

Error response shape
{
  "error": {
    "code": "PAYMENT_REQUIRED",
    "message": "Insufficient credits"
  }
}
StatusCodeDescription
400BAD_REQUESTMissing required parameter (usually the file field).
401UNAUTHORIZEDMissing or invalid API key.
402PAYMENT_REQUIREDInsufficient credits for the requested operation.
403FORBIDDENThe job belongs to a different account.
404NOT_FOUNDJob not found.
413PAYLOAD_TOO_LARGEUploaded image exceeds the 10MB limit.
422UNSUPPORTED_MEDIA_TYPEFile type not supported. Use JPEG, PNG, or WebP.
429RATE_LIMITED, QUEUE_FULL, QUEUE_TIMEOUTToo many requests or concurrency slots busy. Respect the Retry-After header.
500INTERNAL_SERVER_ERRORProcessing failed on our side. Credits are refunded; retry with exponential backoff.

Best Practices

Retrying safely

  • On 429, always wait at least the Retry-After seconds before retrying.
  • On 500 and network errors, use exponential backoff with jitter (e.g. 1s, 2s, 4s, 8s — max 5 attempts).
  • Never retry 400, 401, 402, 413, or 422 without fixing the request first.
Backoff example (Node.js)
async function processWithRetry(form, attempt = 0) {
  const res = await fetch('https://your-domain.com/api/v1/remove-background', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
    body: form,
  });

  if (res.ok) return res.json();

  const retryable = res.status === 429 || res.status >= 500;
  if (retryable && attempt < 5) {
    const retryAfter = Number(res.headers.get('retry-after') || 0);
    const backoff = Math.min(2 ** attempt + Math.random(), 30);
    await new Promise(r => setTimeout(r, Math.max(retryAfter, backoff) * 1000));
    return processWithRetry(form, attempt + 1);
  }

  const { error } = await res.json();
  throw new Error(`${error.code}: ${error.message}`);
}

Working with Base64 output

  • Split on the first comma only: output_url.split(",")[1] — never strip the data:image/png;base64, prefix with fixed string lengths.
  • For large batches, stream results to disk or object storage instead of holding them in memory.

Getting the best results

  • Use the highest-resolution source you have (the model handles up to 10MB comfortably).
  • Well-lit products with clear contrast against their background produce the cleanest edges.
  • For catalog work, always use prepare-product — consistent 2000×2000 canvases make listings look uniform.