Loods

API v1 · Built in the EU

For engineers

Every inbound channel, one signed event stream.

Loods reads your inbound channels and posts each message to your webhook as a signed JSON event. On request, it reads a message or drafts a reply with an AI model. It sends a message only when you ask for exactly that message, and it never sends mail.

IN · IMAP · platform push · messaging API · your own formOUT · signed JSON events

Built in the EURuns in the EUNever leaves it

POST to your webhookmail.received
{
  "id": "evt_01k5twq0v9g3m7c2h8n4p6r1s0",
  "type": "mail.received",
  "created_at": "2026-09-22T09:14:03Z",
  "channel": { "ref": "mail-info", "type": "imap" },
  "data": {
    "from": { "name": "Marieke de Vries" },
    "subject": "Re: Uw aanvraag voor een dakkapel",
    "received_at": "2026-09-22T09:13:58Z",
    "lead": null
  }
}

How events reach you

Name a channel with one PUT, and every new message on it becomes an event. Your keys see only your own channels and events.

IMAP
Any mailbox, polled, read-only. mail.received, with a lead when one is recognised.
Platform push
Lead sources post to an endpoint Loods issues per channel. lead.received.
Messaging API
A business number. Received-message and delivery-status events.
Your own form
A form on your pages posts straight to Loods, with no key to print in HTML. form.submitted.

Loods

Keeps each event encrypted for 30 days.

The same message read twice is one event.

Media is streamed through and never stored.

Your app

Pushed to your webhook, signed. Answer 2xx.

No webhook? Pull with GET /v1/events?after=.

Missed one? Fetch it again or ask for a redelivery.

Delivery you can plan for

  • At least once, not in order. Dedupe on id, and order by the times inside data.
  • Retried for about two days. If your webhook doesn't answer 2xx, Loods tries again with growing waits, then marks the event failed.
  • Never lost to a failure. A failed event stays pullable and redeliverable until it's pruned.
  • Kept for 30 days. Keep your own record of anything you need longer.

Verify before you trust

Every event carries a Loods-Signature header: an HMAC-SHA256 over the timestamp and the raw body, with your webhook secret.

Loods-Signature: t=1790000000,v1=…PHP
function loods_verified(string $body, string $header, string $secret): bool
{
    // t once, v1 one or more times: check the body against every one.
    $parts = [];
    foreach (explode(',', $header) as $part) {
        [$k, $v] = array_pad(explode('=', trim($part), 2), 2, '');
        $parts[$k][] = $v;
    }

    $t = (int) ($parts['t'][0] ?? 0);
    if ($t === 0 || abs(time() - $t) > 300) {
        return false;
    }

    $expected = hash_hmac('sha256', $t.'.'.$body, $secret);
    foreach ($parts['v1'] ?? [] as $candidate) {
        if (hash_equals($expected, $candidate)) {
            return true;
        }
    }

    return false;
}

The model, on request

Every AI call is stateless. You send what the model may see and get structured data back. Add guidance to say who you write as; it can't switch off Loods' own rules.

CallWhat it does
POST /v1/interpret/leadReads contact fields, the address, a title and a summary. What you pass in known beats what the model reads.
POST /v1/interpret/messagePicks one of your own intents and writes a one-line summary. Price lines come back as integers, never as a total.
POST /v1/draftFills the gaps in an outline you wrote. You render the result into your own template.
POST /v1/extractAnswers your own instructions in your own JSON Schema.

Built in
the EU

Runs in the EU.
Never leaves it.

Every lead and every reply is personal data. Loods treats it that way by design, not by setting.

  • Runs in the EULoods, its storage and the AI it calls all run inside the EU, and none of it leaves.
  • Kept brieflyEvents are encrypted at rest and deleted after 30 days.
  • Logged by cost onlyAn AI call leaves a token count behind, never what was read or written.
  • Checked on every changeLoods' promises are automated tests, and only a change that passes them is deployed.

The contract is the product

You get the full OpenAPI spec and an example of every event and response. Loods tests its own output against those examples; copy them into your tests too.

Errors always have one shape, with a stable code to branch on. Breaking changes get a new version: /v1 is never changed out from under you.

idempotency_key_reusedconflict · your request

Every send needs an Idempotency-Key. Repeat a request with the same key and Loods returns the first answer and sends nothing. Reuse a key for a different request and you get this.

Pricing

Two things are priced, because two different things cost money to run. AI calls cost credits, by the work done. A channel costs a flat fee, by who keeps it working. Events and delivery are included in both. Payments are taken by an EU payment provider.

Subscriptions
PlanCredits/moChannelsPrice
Starter5,0002 + 2€49
Pro25,0005 + ∞€149
Top-up packs
PackCreditsPrice
Starter1,000€10
Growth5,000€25
Scale25,000€50
Enterprise100,000€100
Channels beyond what a plan carries
TierWho keeps it workingPer monthSetup
MaintainedLoods follows the platform's own API or mail format, and fixes it when it changes€20—
WebhookSomething of yours posts and you own the fields: a form on your own pages. Not a platform push, which Loods follows€5—
CustomA channel for one platform that is yours alone, written and kept working by Loods€75€1,500

One credit is worth €0.01 at the base rate. A lead interpretation costs 25 credits (€0.25). A channel fee lands on the one monthly payment, never a second invoice, and nothing is prorated: a channel you connect today is charged from your next renewal, and one you remove today is not charged at all.

Start with a key

Ask for a key Read the docs