Documentation menu

API reference

API reference

The base URL, authentication, request and response conventions, and every endpoint of the Smol API.

Base URL

base URL
https://api.smolmac.com

Every path in this reference is relative to it and starts with /v1. All requests use HTTPS. A trailing slash on a path is ignored.

Authentication

Send your API key in the Authorization header of every request, as a bearer token.

request header
Authorization: Bearer $SMOL_API_KEY
  • A key is smol_live_ or smol_test_ followed by 32 letters and digits. A test key works only on the sample files and is never billed.
  • Four requests need no key: GET /v1/capabilities, GET /v1/receipt_keys, GET /v1/openapi.json, and a download through a job's signed download_url.
  • Keys are for servers. The API sends no CORS headers, so a web page cannot call it from a browser.

See Authentication for how to create and revoke keys.

Versioning

The API is versioned by date. The current version is 2026-10-01, and it is the only one so far. Every response states the version that answered in a Smol-Version header.

request header, optional
Smol-Version: 2026-10-01

You may send the same header on a request to pin the version your code was written against. A request that names a version the API does not have is refused with 400 unsupported_version. Without the header, the current version answers.

Requests

  • JSON bodies. Endpoints that take JSON expect a JSON object of at most 64 KB. Field names are in snake_case. A field the endpoint does not define is refused with 400 bad_request, so a misspelled field fails and is not ignored.
  • File bodies. The three direct endpoints take the file itself: as the raw request body, or as a multipart/form-data form. See Compress.
  • Options. The same options are used everywhere: as dotted query parameters on a direct request (?image.quality=60), and as a nested JSON object on a job. An unknown option is refused with 400 invalid_options. See Options.
  • Methods. A method the path does not support returns status 405. A path that does not exist returns 404 not_found.
  • Idempotency. POST /v1/jobs accepts an Idempotency-Key header. See Idempotency.
  • Presets. A direct request or a job can name a saved set of options with preset. See Presets.

Responses

  • JSON. Field names are in snake_case. A field that does not apply is null. It is not left out.
  • Timestamps are ISO 8601 strings in UTC with milliseconds, such as 2026-10-01T12:00:03.118Z. Field names end in _at.
  • Sizes are whole numbers of bytes.
  • Durations are in seconds. Field names end in _seconds.
  • Objects carry an object field that names their kind, such as "job" or "upload".
  • Lists have the shape { "object": "list", "data": [...], "has_more": false }.
  • Files. A successful direct request, and a download of a job's output, return the file as the body. The details travel in response headers.
  • Errors are a status of 400 or above with a JSON body that holds one error object, on every endpoint. See Errors.
StatusMeaning
200Success.
201An upload, a preset or a webhook endpoint was created.
202A job was accepted. The work happens afterwards.
400 to 415, except 409The request cannot be carried out as sent. Change it.
422The request is well formed, but the file cannot be processed.
409The request conflicts with the state of something: an idempotency key, an upload, a job that has not finished.
429Too many requests, or too much in progress. Retry after the time in Retry-After.
500, 503, 504A fault or a shortage on our side. Retry.

Request ids

Every response carries a Smol-Request-Id header, such as req_nawnA3JOXOxTy0iq0T57. An error repeats it in the body as error.request_id. Log it with each call. It is the fastest way for support to find a request.

Object ids

An id is a prefix that names the kind of object, an underscore, and 20 letters and digits.

PrefixObject
req_A request
upl_An upload
job_A job
evt_A webhook event
whk_A webhook endpoint
pre_A preset

Endpoints

Direct requests. The file goes in and the result comes back in the same response. For images, PDFs, audio, tables and fonts up to 25 MB.

MethodPathPurpose
POST/v1/compressMake an image, a PDF or an audio file smaller.
POST/v1/convertChange a file to another format.
POST/v1/strip-metadataRemove metadata from an image or a PDF.

Uploads and jobs. For larger files, and for all video and office documents.

MethodPathPurpose
POST/v1/uploadsCreate an upload, to send a file that a job will use.
PUT/v1/uploads/{id}/contentSend the bytes of a file of up to 95 MB.
PUT/v1/uploads/{id}/parts/{part_number}Send one part of a larger file.
POST/v1/uploads/{id}/completeJoin the parts of a larger file.
POST/v1/jobsCreate a job: compress, convert or strip metadata.
GET/v1/jobs/{id}Retrieve a job and its result.
GET/v1/jobsList jobs, newest first.
DELETE/v1/jobs/{id}Cancel a job and delete its files now.
GET/v1/jobs/{id}/outputDownload the output of a job.
GET/v1/jobs/{id}/receiptGet the signed receipt of a finished job.
GET/v1/receipt_keysGet the public keys that verify receipts. No key needed.

Webhooks. To be told when a job finishes.

MethodPathPurpose
POST/v1/webhook_endpointsRegister a URL that receives job events.
GET/v1/webhook_endpointsList the registered URLs.
PATCH/v1/webhook_endpoints/{id}Pause or resume deliveries to a registered URL.
DELETE/v1/webhook_endpoints/{id}Remove a registered URL.
POST/v1/webhook_endpoints/{id}/rotate_secretReplace the signing secret of a registered URL.
POST/v1/webhook_endpoints/{id}/testSend a signed test event to a registered URL.
GET/v1/webhook_endpoints/signing_secretGet the secret that signs deliveries to a job's webhook_url.

Presets. Named sets of options.

MethodPathPurpose
POST/v1/presetsCreate a preset, or replace the one with the same name.
GET/v1/presetsList presets.
GET/v1/presets/{id or name}Retrieve a preset.
DELETE/v1/presets/{id or name}Delete a preset.

Planning and reporting.

MethodPathPurpose
GET/v1/capabilitiesList operations, formats, option values and plan limits. No key needed.
POST/v1/estimateGet the price and output format of a request without sending the file.
GET/v1/usageGet the usage of the account per meter and per day.

A machine-readable description of all of these, in OpenAPI 3.1, is served at GET /v1/openapi.json. It needs no key, and it may be cached for five minutes.

bash
curl "https://api.smolmac.com/v1/openapi.json" -o smol-openapi.json

Two SDKs wrap these endpoints: TypeScript and Node.js and Python.

Objects