Leapfile APIs¶
Leapfile has two HTTP APIs. Both are part of your own Leapfile site, so the base URL is your account's domain — for example https://your-company.leapfile.com.
| API | What it does | Key prefix | Who enables it |
|---|---|---|---|
| Transfer API | Send transfers: create a transfer, attach files, send it, and check whether recipients collected it. | lf_ |
An administrator turns on the account feature and grants the permission to a user; the user creates their own key. |
| Event Monitoring | Read-only feed of account activity for a SIEM or log pipeline. | obs_ |
An administrator enables it on Account Settings → Security → Events. |
An Event Monitoring key cannot send files, and a Transfer API key cannot read the event feed.
Turning the Transfer API on¶
Three things must be true before a key works.
- The account feature is on. An administrator turns on Transfer API under Account Settings → Account → Features. The option is available only on plans that include outgoing transfers.
- The user has the permission. On the user's record under Account Settings → Users, tick Use the transfer API. It is off by default for every user, including users who can already send files.
- The user can send files. A user whose sending is turned off can still read transfers through the API, but cannot create a key, create a transfer, upload a file, or send.
The first two are checked on every request; the third on creating a key, creating a transfer, uploading a file, and sending. A missing one gives a 403 — see Error codes for which code means which.
api_not_enabled covers both the account feature being off and a plan without outgoing transfers. If an administrator confirms the feature is on and requests still fail with it, the plan is the reason.
Turning the account feature off cuts every key on the account immediately. The keys are not revoked, so turning it back on restores them.
Creating an API key¶
Keys belong to a user, not to the account. Each user creates their own from My Profile → Integrations → API Keys.
The Integrations section only appears once both the account feature and that user's permission are on. A user who cannot see it is missing one of the two. Creating a key also needs Send files: without it the Create form appears but returns an error.
- Go to My Profile → Integrations → API Keys.
- Create a key and give it a label — the name of the system that will use it is a good choice. The label is for you; it has no effect on what the key can do.
- The full key is shown once, at creation. It starts with
lf_. Copy it into a secrets manager before you leave the page. - Give the key and your site's base URL to whoever builds the integration.
Leapfile stores only a hash of the key and the first few characters, so a lost key cannot be shown again — create a new one and revoke the old.
You can hold several keys at once. That is how to rotate: create the new key, move the integration over, then revoke the old one. Revoking takes effect on the next request.
Keys do not expire on their own. A key works until it is revoked, or until one of these stops it, without being revoked: the user is deleted or deactivated, the user loses the Use the transfer API permission, or the account feature is turned off.
Every send is live
A send emails the recipients and is billed, on any account. Build against an address you control.
Authentication¶
Send the key as a bearer token on every request:
Authorization: Bearer lf_Ab3fK9x2...
A missing, malformed, unknown, or revoked key all return the same 401 invalid_api_key.
What a key can see¶
A key sees only the transfers its own user sent. A transfer sent by a colleague on the same account returns 404, the same response as an id that does not exist.
Rate limit¶
60 requests per 60 seconds, per key. The window is a fixed counting window rather than a minimum gap between calls, so a burst is fine as long as the total stays under 60. It opens on the key's first request after an idle period, not on the clock minute.
Every endpoint counts, and each file is one request, so one transfer costs one create, one per file, and one send. That sets where the limit actually bites:
| What you are doing | Requests | Hits the limit? |
|---|---|---|
| One transfer, up to 58 files | up to 60 | No — this is the ceiling for a single window |
| One transfer, 59 files or more | 61+ | Yes, always. The sleep is part of the normal path at this size |
| Many small transfers, one file each | 3 each | At 20 transfers a minute |
| Polling for pickup | 1 each | Only in combination with the above; hourly polling is negligible |
So it is many small files that meet it, not large ones — a large upload holds the connection long enough to space itself out. In practice the outstanding-transfer limit usually binds before this one does.
Exceeding it returns 429 rate_limited with a Retry-After header giving the seconds left in the window. Sleep that long and repeat the call that was refused.
A request refused before the key is checked — bad or missing Authorization, a create body that is not JSON, an upload with no Content-Length — does not count against the window.
Give each system its own key rather than sharing one: the allowance is per key with no account-wide ceiling above it, and each key's last-used time is listed separately.
Error responses¶
Every error is a JSON object with a machine-readable code and a human-readable message:
{
"error": "invalid_request",
"message": "subject is required."
}
Branch on error, not on message — the wording can change.
Versioning¶
Every path begins with /v1. A change that would break an existing integration goes into a new version rather than into /v1.