Get started
Authentication
Every request carries an API key in the Authorization header; this page covers key types, IP allow-lists, rotation and the errors a key can cause.
Send the key
Put the key in the Authorization header as a bearer token. There is no other way to authenticate: no query parameter, no cookie, no basic auth.
curl -X POST "https://api.smolmac.com/v1/compress" \
-H "Authorization: Bearer $SMOL_API_KEY" \
--data-binary @photo.jpg \
-o photo.min.jpgFour requests work without a key:
- GET /v1/capabilities, which describes the API;
- GET /v1/receipt_keys, the public keys that verify receipts;
GET /v1/openapi.json, the OpenAPI description of the API;- the signed download link of a finished job (
result.download_url), which carries its own signature.
A request may also carry a Smol-Version header to pin the API version. It is optional. See Versioning.
Live and test keys
A key is a prefix followed by 32 letters and digits. The prefix says which mode the key runs in.
| Prefix | Mode | Works on | Billed |
|---|---|---|---|
smol_live_ | Live | Your own files. The account needs a payment method or a plan. | Yes |
smol_test_ | Test | The published sample files only. Works as soon as the account exists. | No |
Both modes use the same endpoints, options and response formats. The two modes do not see each other: a job created with a test key is not visible to a live key, and the reverse. See Test mode for the details.
Create and store keys
Keys are created in the dashboard. You give the key a name of up to 60 characters, choose live or test, and may list the IP addresses it works from. An account can have up to 20 active keys, so each service or environment can have its own.
Store the key the way you store a database password: in an environment variable or a secret manager, not in source control. The examples in these docs read it from SMOL_API_KEY.
Restrict a key to IP addresses
A key can carry an allow-list: up to 20 IP addresses or CIDR ranges, IPv4 or IPv6. You enter the list when you create the key. A key with no list works from any address.
203.0.113.7
198.51.100.0/24
2001:db8:1234::/48- A request with the key from any other address is refused with 403 ip_not_allowed. Nothing is processed and nothing is billed.
- The list applies to every request that carries the key, including the requests that send upload content.
- The address checked is the one the request arrives from. Behind a proxy, a NAT gateway or a cloud function, that is the outgoing address of that service, not of your machine.
- An IPv4 range matches IPv4 addresses only, and an IPv6 range IPv6 only. If your servers can connect over both, list both.
- The list cannot be edited afterwards. To change it, create a new key with the new list and revoke the old one.
- A signed
result.download_urlcarries no key, so the list does not apply to it. It can be opened from any address until it expires.
Rotate a key
A key cannot be changed in place. To rotate, replace it:
- Create a new key in the dashboard.
- Deploy the new key to every service that used the old one.
- Revoke the old key in the dashboard.
Both keys work until step 3, so there is no downtime. A revoked key is refused with revoked_key. Revocation can take up to 30 seconds to reach every server. It cannot be undone.
If a key has leaked, revoke it first and replace it second. Jobs that the key already started keep running and stay readable with any other key of the same mode on the account.
Errors a key can cause
The key is checked before anything else. A request that fails here is not processed and not billed. Every error has the same JSON shape:
{
"error": {
"type": "authentication_error",
"code": "invalid_key",
"message": "This API key is not valid.",
"param": null,
"request_id": "req_nawnA3JOXOxTy0iq0T57",
"doc_url": "https://smolmac.com/docs/reference/errors#invalid_key"
}
}| Status | Code | Cause | What to do |
|---|---|---|---|
| 401 | missing_key | No Authorization: Bearer header on the request. | Send the header. |
| 401 | invalid_key | The key is malformed or does not exist. | Check for a truncated key or stray whitespace. |
| 401 | revoked_key | The key was revoked in the dashboard. | Use a current key. |
| 402 | no_payment_method | A live key on an account with no payment method or plan. | Add one in the dashboard, or use a test key. |
| 402 | payment_required | A live key on an account with an unpaid invoice. | Pay the invoice in the dashboard. |
| 402 | spend_cap_reached | A live key, and the account has reached its monthly spend cap. | Raise the cap in the dashboard, or wait for the next month. |
| 402 | test_mode_sample_required | A test key was used with a file that is not a published sample. | Use a sample file, or a live key. |
| 403 | account_suspended | The account is suspended. Applies to live and test keys. | Contact support. |
| 403 | ip_not_allowed | The key has an allow-list, and the request came from an address that is not on it. | Call from a listed address, or create a key with the right list. |
None of these are worth retrying without a change on your side. The full list of error codes is in Errors.
Server side only
Call the API from your own backend. The API sends no CORS headers, so a browser cannot call it from a web page in any case. When a user uploads a file, send it to your server, and have your server call Smol.
To hand a result to a browser without exposing a key, give it the result.download_url of a finished job. That link is signed, expires with the job, and works without a key. See Large files and jobs.