Convert a file

POST https://api.iconscout.com/v3/convert/{operation}

Convert an uploaded file between formats.

Two response shapes

Most operations are synchronous: the converted file is returned directly in the response body with the appropriate Content-Type. There is no JSON envelope and no base64 — write the body straight to disk.

Lottie render operations (lottie-to-gif, lottie-to-webp, lottie-to-mp4, lottie-to-webm) are asynchronous because they can take tens of seconds. They return 202 Accepted with a job to poll via GET /v3/convert/jobs/{job}.

Operations

OperationInputOutputMode
png-to-jpgpngjpgsync
jpg-to-pngjpgpngsync
svg-to-pngsvgpngsync
svg-to-jpgsvgjpgsync
svg-to-pdfsvgpdfsync
lottie-optimizejsonjsonsync
lottie-to-dotlottiejsonlottiesync
svg-to-lottiesvgjsonsync
lottie-to-gifjsongifasync
lottie-to-webpjsonwebpasync
lottie-to-mp4jsonmp4async
lottie-to-webmjsonwebmasync

Credits and entitlements

Each call consumes API credits from your account's single credit balance. Call GET /v3/convert/operations for the current credit cost of each operation and whether your plan includes it — prices are configuration and are best read from the API rather than hard-coded. For plans and pricing, see iconscout.com/api.

A 403 means your plan does not include the capability, or the app has file conversion switched off in the API dashboard; a 429 means it does, but your credits are spent. Failed conversions are not charged.

Note that the upload is validated before entitlement is, so a malformed call to an operation your plan excludes reports the validation error first and the 403 only once the request is otherwise valid. Read available_on_your_plan from GET /v3/convert/operations to know before you call.

Idempotency

Idempotency-Key suppresses duplicate work. It does not replay a response, which is where it differs from the same header on Stripe or Square — read it as a duplicate guard.

Key's original runWhat a repeat gets
still in flight409 idempotency_in_progress
completed, async202 with the original job — poll it as normal
completed, sync409 idempotency_already_completed — the output is gone
failed and refunded409 idempotency_already_failed

The sync row is the one to design around. A conversion that succeeded but whose response you lost to a network timeout has already been charged, and its bytes are not retained: the only way forward is a new key, which is a second charge. If that matters to your integration, prefer the async operations, whose job survives the round trip.

Browser-only conversions

lottie-to-svg is performed client-side in the iconscout.com editor and has no API equivalent.

Parameters

NameInTypeNotes
operationpathstringrequired; one of svg-to-png, svg-to-jpg, svg-to-pdf, png-to-jpg, jpg-to-png, lottie-optimize, lottie-to-dotlottie, svg-to-lottie, lottie-to-gif, lottie-to-webp, lottie-to-mp4, lottie-to-webm
Conversion to perform. See the table above, or call GET /v3/convert/operations.
Idempotency-Keyheaderstringoptional
Optional. 16–128 URL-safe characters. A replay guard, not a replay: a key whose original run already completed is rejected rather than re-dispatched. For an async render the original job is returned, so the result is still reachable. A synchronous conversion streams its bytes and keeps no copy, so a repeated key gets a 409 and the output cannot be recovered — retry with a new key, and the original charge stands.

Responses

StatusMeaning
200 Converted file, returned directly. Synchronous operations only.
202 Render queued. Asynchronous operations only. Location points at the job to poll and Retry-After gives the interval to poll it at — follow them rather than guessing, which is how a client ends up polling a 40-second render every 200ms. A 1080×1080 MP4 typically completes in well under a minute.
400 Validation error, or the uploaded file does not match the operation input format. data.reason is invalid_request, invalid_input_file, invalid_idempotency_key, async_operation or sync_operation.
401 Unauthorized — missing or invalid Client-ID / Client-Secret. data.reason is invalid_credentials.
403 Your plan does not include the capability this operation requires, or the app has file conversion switched off in the API dashboard. data.reason is entitlement_required for both; the message says which. Check available_on_your_plan on GET /v3/convert/operations before calling to avoid this round trip — it accounts for the plan and the app setting alike.
404 Unknown conversion operation. data.reason is unknown_operation.
409 This Idempotency-Key has already been used. data.reason is idempotency_in_progress, idempotency_already_completed or idempotency_already_failed — see the Idempotency section above for what each means and what is recoverable.
413 Uploaded file exceeds max_upload_kb for your plan. data.reason is invalid_request.
422 This client holds no active API subscription. data.reason is subscription_required.
429 Two different conditions, told apart by data.reason. rate_limit_exceeded — too many requests this minute for this client. Transient; Retry-After says when to retry, and the X-RateLimit-* headers say what the budget is. Those headers are on every response the limiter admits, not only this one; only a 401, refused before the limiter runs, carries none. quota_exhausted — the API credit allowance for the billing period is spent. A spend ceiling, not a request-rate limit: waiting does not clear it before the period rolls over.
500 The conversion service could not complete the request. data.reason is conversion_failed. Credits are not charged.
504 The conversion service did not respond in time. Credits are not charged.

Examples

SVG to PNG (sync, writes the file)

curl -X POST 'https://api.iconscout.com/v3/convert/svg-to-png' \
  -H 'Client-ID: your-client-id' \
  -H 'Client-Secret: your-client-secret' \
  -F 'file=@logo.svg' \
  -o logo.png

Lottie to MP4 (async, returns a job)

curl -X POST 'https://api.iconscout.com/v3/convert/lottie-to-mp4' \
  -H 'Client-ID: your-client-id' \
  -H 'Client-Secret: your-client-secret' \
  -F 'file=@animation.json' \
  -F 'width=1080' \
  -F 'height=1080'

SVG to Lottie with a preset

curl -X POST 'https://api.iconscout.com/v3/convert/svg-to-lottie' \
  -H 'Client-ID: your-client-id' \
  -H 'Client-Secret: your-client-secret' \
  -F 'file=@icon.svg' \
  -F 'preset=fade-in-up' \
  -o animation.json

Python requests (sync)

import requests

with open('logo.svg', 'rb') as handle:
    resp = requests.post(
        'https://api.iconscout.com/v3/convert/svg-to-png',
        headers={
            'Client-ID': 'your-client-id',
            'Client-Secret': 'your-client-secret',
        },
        files={'file': handle},
    )

resp.raise_for_status()
with open('logo.png', 'wb') as out:
    out.write(resp.content)

print('credits charged:', resp.headers['X-Credits-Consumed'])

Node.js fetch (async render)

const form = new FormData();
form.append('file', new Blob([await fs.readFile('animation.json')]), 'animation.json');
form.append('width', '1080');
form.append('height', '1080');

const res = await fetch('https://api.iconscout.com/v3/convert/lottie-to-mp4', {
  method: 'POST',
  headers: {
    'Client-ID': 'your-client-id',
    'Client-Secret': 'your-client-secret',
  },
  body: form,
});

const { response } = await res.json();
console.log(response.job.uuid, response.job.status);
Try it in the interactive reference →