Get started
The partner API is for companies that sell ilo products or build them into their own service. To get access, write to us at support@ilo.tools with your company and what you plan to build. You get a partner account with the plans you may sell, your partner prices, a monthly license quota and API keys.
Base URL: https://ilo-site.vercel.app/api/v1 — HTTPS only, JSON in and out. Start with a sandbox key (ilo_test_…): it works exactly like a live key but issues test keys that are never billed and never activate.
Authentication
Send your key in the Authorization header on every request:
Authorization: Bearer ilo_live_k1a2b3c4d5e6_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- Live keys start with
ilo_live_, sandbox keys with ilo_test_. We show a key once, when it is created, and keep only a fingerprint of it — we can never show it again.
- Call the API from your server only. Never put a key in a web page, a mobile app or a public repository; the API refuses browser requests from other sites.
- Each key has permissions (scopes):
catalog:read, licenses:issue, licenses:read, licenses:revoke, downloads:read, usage:read. Ask for the ones you need.
- Your account can be limited to your servers' addresses. Keys can expire; we can rotate or revoke one at any time.
Quick start
Check your key:
curl https://ilo-site.vercel.app/api/v1/ping \
-H "Authorization: Bearer $ILO_KEY"
See what you can sell, at your price:
curl https://ilo-site.vercel.app/api/v1/catalog \
-H "Authorization: Bearer $ILO_KEY"
Issue a license after your customer pays (the reference is your own order id):
curl https://ilo-site.vercel.app/api/v1/licenses \
-H "Authorization: Bearer $ILO_KEY" \
-H "Content-Type: application/json" \
-d '{ "plan": "an-1y", "email": "customer@example.com", "name": "Dana Levi", "reference": "ORDER-10045" }'
{
"license": {
"id": "lic_9Qx…", "reference": "ORDER-10045", "mode": "live",
"plan": "an-1y", "product": "animation", "email": "customer@example.com",
"price": 149, "currency": "usd",
"keys": [ { "product": "Ilo Animation", "key": "ANI-…", "type": "1 year", "expires": "2027-10-07" } ],
"status": "active", "createdAt": "2026-10-07T10:12:03.000Z", "revokedAt": null
}
}
Give the customer the key and the installer link (from /downloads). They paste the key in the app the first time they open it.
Endpoints
| Call | Scope | What it does |
GET/ping | — | Your account, the key's mode and scopes, your limits. |
GET/catalog | catalog:read | The products and plans you may sell, with the retail price and your partner price. |
POST/licenses | licenses:issue | Issue license keys: { plan, email, name?, reference }. Answers 201, or 200 with "idempotent": true when the reference was already issued. |
GET/licenses | licenses:read | Your licenses, newest first. Filters: ?reference=, ?email=, ?limit= (1–200), ?before= (the next value of the previous page). |
GET/licenses/{id} | licenses:read | One license, with its live state on the license servers (activations, expiry, revoked). |
POST/licenses/{id}/revoke | licenses:revoke | Stop the keys (refund, chargeback, cancelled order). Optional { reason }. |
POST/licenses/{id}/restore | licenses:revoke | Allow revoked keys again. |
GET/downloads | downloads:read | The current installers for macOS and Windows, per product. |
GET/usage | usage:read | This month's calls, licenses, revoked licenses and amount, and your remaining quota. ?month=2026-10 for another month. |
Issuing licenses
- Plans:
raw-1m, raw-6m, raw-1y, ct-… (Color Tools), rt-… (Retouch), an-… (Animation), b-… (Raw + Color Tools) and all-… (all four) — for 1 month, 6 months or 1 year. A bundle returns one key per product.
- One reference, one license. Send the same
reference again (a retry after a timeout, a double click) and you get the same license back — never a second one. The same reference with a different plan or email is refused with 409.
- Keys work on two computers each and expire at the end of the plan. Your customer activates them in the app; you can watch activations with
GET /licenses/{id}.
- Billing: each live license is billed at your partner price; revoked licenses are not billed. We send a monthly statement.
Errors
Errors have an HTTP status and a JSON body: { "error": { "code": "…", "message": "…", "requestId": "req_…" } }. Every answer has an X-Request-Id header — send it to us when something looks wrong.
| Status | Code | Meaning |
| 400 | invalid_json | The body is not a JSON object. |
| 401 | unauthorized · key_revoked · key_expired | No key, a wrong key, or a key that no longer works. |
| 403 | insufficient_scope · plan_not_allowed · ip_not_allowed · account_suspended | The key or the account may not do this. |
| 404 | not_found | No such endpoint, or no such license on your account. |
| 409 | reference_conflict | The reference was already used for a different license. |
| 413 · 415 | body_too_large · unsupported_media_type | Bodies are JSON, up to 32 KB. |
| 422 | unknown_plan · invalid_email · invalid_reference | A field is missing or wrong. |
| 429 | rate_limited · quota_exceeded · too_many_failures | Slow down (see Retry-After), or your monthly quota is used up. |
| 5xx | server_error · unavailable | Our side — retry with the same reference; it is always safe. |
Limits
Each account has a number of requests per minute (60 unless agreed otherwise) and, optionally, a number of licenses per month. Every answer tells you where you stand:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1791370800
When you hit the limit you get 429 with Retry-After in seconds. Back off and retry — with the same reference for a license, so nothing is ever issued twice.
Sandbox
With an ilo_test_ key everything works the same, but licenses get keys like TEST-4F2A1-… that never activate, are never sent to the license servers and are never billed. Sandbox and live licenses are kept apart: a sandbox key never sees live licenses, and the other way round. Build and test with the sandbox, then switch the key.
Security
- Keys are stored only as keyed fingerprints; a stolen database would not reveal them. Keep yours in your server's secret store and rotate them.
- Repeated failed sign-ins from one address are blocked for ten minutes. Every call is written to an audit log (time, key, call, answer — never keys or customer details).
- Lost a key, or think it leaked? Tell us — we revoke it at once and give you a new one.
- Customer emails are used only to issue and look up their licenses, as in our privacy policy.