LOOMAL
SDK / API ReferencePayments

Mandates

Spend policy attached to your project's wallet

Scope: payments:spend

A mandate is the per-project spend policy Loomal enforces server-side on every payments.pay() call. One mandate per project at a time (typical setup). Create it once via the Pay tab in the Console or programmatically via this resource — every pay() afterward respects its caps.

Mounted at loomal.payments.mandates.

The Mandate object

{
  "mandateId": "m_abc123",
  "identityId": "id-...",
  "network": "base",
  "maxPerCallUsdc": "0.10",
  "dailyCapUsdc": "1.00",
  "validUntil": "2027-01-01T00:00:00.000Z",
  "sessionKeyAddress": "0x<derived-session-key>",
  "onchainInstalled": true,
  "installTxHash": "0x<install-tx-hash>",
  "installError": null,
  "spentTodayUsdc": "0.05",
  "remainingTodayUsdc": "0.95",
  "totalSpentUsdc": "1.23",
  "callCount": 27,
  "revokedAt": null,
  "createdAt": "2026-05-12T10:00:00.000Z"
}
FieldDescription
maxPerCallUsdcMax USDC any single pay() call can spend, decimal e.g. "0.10".
dailyCapUsdcMax cumulative USDC per UTC day. Must be ≥ maxPerCallUsdc.
validUntilISO 8601. Defaults to 7 days from creation. Mandate stops authorizing payments after this.
sessionKeyAddressAddress of the session key Loomal derived for this mandate. The key signs EIP-3009 authorizations on your Kernel smart account.
onchainInstalledtrue once the session key landed on Base. First-time install takes 10–30s.
installErrorSet when the session-key install failed. The mandate is unusable until reinstalled — call create() again.
spentTodayUsdc / remainingTodayUsdcLive counters, reset at UTC midnight.
revokedAtISO 8601 when the mandate was revoked, otherwise null.

Create

const mandate = await loomal.payments.mandates.create({
  maxPerCallUsdc: "0.10",
  dailyCapUsdc: "1.00",
});

if (mandate.installError) {
  throw new Error(`install failed: ${mandate.installError}`);
}
import { Loomal } from "@loomal/sdk";

const loomal = new Loomal({ apiKey: process.env.LOOMAL_API_KEY! });
const mandate = await loomal.payments.mandates.create({
  maxPerCallUsdc: "0.10",
  dailyCapUsdc: "1.00",
  validUntil: "2027-01-01T00:00:00Z", // optional, defaults to +7d
});
import os
from loomal import Loomal

loomal = Loomal(api_key=os.environ["LOOMAL_API_KEY"])
mandate = loomal.payments.mandates.create(
    max_per_call_usdc="0.10",
    daily_cap_usdc="1.00",
)
curl -X POST https://api.loomal.ai/v0/payments/mandates \
  -H "Authorization: Bearer loid-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "maxPerCallUsdc": "0.10",
    "dailyCapUsdc": "1.00"
  }'

Body

FieldTypeRequiredDescription
maxPerCallUsdcstringYesDecimal USDC, up to 6 fractional digits.
dailyCapUsdcstringYesDecimal USDC. Must be ≥ maxPerCallUsdc.
validUntilstringNoISO 8601. Defaults to 7 days from now.
networkstringNo"base" (only supported network).

Notes

  • First-call latency — creating a mandate installs the session key on Base, which takes 10–30s while the bundler confirms. Subsequent pay() calls reuse the key and are sub-second.
  • Install failures — if the bundler errors out (out of gas, network issue), the returned mandate has installError set and onchainInstalled: false. The mandate is unusable. Retry create().
  • Multiple mandates — the API allows multiple active mandates per project; pay() picks the first non-revoked, non-errored one with network === "base". In practice, keep one.

List

const { mandates } = await loomal.payments.mandates.list();
const active = mandates.find((m) => !m.revokedAt && !m.installError);
const { mandates } = await loomal.payments.mandates.list();
mandates = loomal.payments.mandates.list()["mandates"]
curl https://api.loomal.ai/v0/payments/mandates \
  -H "Authorization: Bearer loid-your-api-key"

Returns { mandates: Mandate[] }. Includes revoked and errored mandates — filter client-side as shown.


Get

const mandate = await loomal.payments.mandates.get("m_abc123");
const mandate = await loomal.payments.mandates.get("m_abc123");
mandate = loomal.payments.mandates.get("m_abc123")
curl https://api.loomal.ai/v0/payments/mandates/m_abc123 \
  -H "Authorization: Bearer loid-your-api-key"

Revoke

await loomal.payments.mandates.revoke("m_abc123");

Marks the mandate as revoked. The on-chain session key is not uninstalled — that's a manual step from the Console if you want to fully retire the key. Settled payments are unaffected.

await loomal.payments.mandates.revoke("m_abc123");
loomal.payments.mandates.revoke("m_abc123")
curl -X DELETE https://api.loomal.ai/v0/payments/mandates/m_abc123 \
  -H "Authorization: Bearer loid-your-api-key"

Errors

StatuserrorCause
400bad_requestmaxPerCallUsdc <= 0 or dailyCapUsdc < maxPerCallUsdc
401unauthorizedMissing or invalid Authorization header
403forbiddenAPI key lacks payments:spend scope
404not_foundMandate id doesn't exist (on get / revoke)

Next

On this page