Skip to main content

API Keys

API keys authenticate your backend with the Loyva API. Any admin in your org can self-serve create one from Settings → API Keys, or via this management API. Keys are scoped to specific permissions and confined to the org that created them.

This applies equally whether you're an integration partner (e.g. WeSuite) building on Loyva for your own customers, or a direct Loyva customer calling the API for your own org — there is no separate "customer key" mechanism, just one org-scoped key type.

Key format​

lk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
  • Prefix: lk_
  • Body: 40 hexadecimal characters
  • Total: 43 characters

Getting a key​

Any org admin can self-serve create a key from Settings → API Keys in the console, or by calling POST /api/v2/partners/keys (JWT-authenticated, admin role required):

curl -X POST https://api.stg.loyva.net/api/v2/partners/keys \
-H "Authorization: Bearer <your session JWT>" \
-H "Content-Type: application/json" \
-d '{
"partner_name": "Fire N Spec — internal integration",
"scopes": ["envelopes:read", "envelopes:write", "customers:read"],
"rate_limit_rpm": 100
}'

The response includes:

  • The raw lk_... key (shown once — store it immediately in your secrets manager)
  • The scopes granted on the key (see Scopes)
  • A rate_limit_rpm ceiling

partner_name is just a display label for the key — for a direct customer creating a key for their own use, it can be anything ("internal integration", a script name, an environment name).

danger

The raw key is only shown once. Loyva stores it as a SHA-256 hash and cannot recover it later. If you lose it, rotate the key (see below) — this issues a new raw key and invalidates the previous one atomically.

Using a key​

Pass the key in the X-API-Key header on every request:

curl https://api.stg.loyva.net/api/v2/partner/envelopes \
-H "X-API-Key: lk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"

The organization is derived from the key — no additional org header is required.

Key lifecycle​

All of these are self-serve, from Settings → API Keys or the API — no Loyva involvement required. Each action requires the admin role in your org.

ActionEndpointNotes
ListGET /api/v2/partners/keysNever returns raw key values
CreatePOST /api/v2/partners/keysA raw key is returned once; the hash is stored server-side
Update scopes / rate limit / webhookPATCH /api/v2/partners/keys/:key_idNon-disruptive — the same key keeps working
RotatePOST /api/v2/partners/keys/:key_id/rotateIssues a new raw key; the previous key keeps working through a grace period, then stops
DeactivateDELETE /api/v2/partners/keys/:key_idKey is rejected on the next request
Manage webhook endpointssee Managing endpointsSelf-serve, and independent of keys

You can verify a key is active by making a GET /api/v2/partner/envelopes request — a 401 means the key is invalid or deactivated. If you're an integration partner onboarding many downstream orgs at once, Loyva can also provision keys on your behalf in bulk — ask your Loyva point of contact.

Rate limits​

Every partner key has a rate_limit_rpm ceiling (requests per minute). The default is 100 RPM. When exceeded, the API returns:

HTTP 429 Too Many Requests
Retry-After: 60
{ "error": "Rate limit exceeded" }

Your key's current RPM ceiling is included in the create response, and is visible any time via GET /api/v2/partners/keys. Raise it yourself with PATCH /api/v2/partners/keys/:key_id.

Multi-tenant fan-out​

If you need per-tenant (e.g. per-dealer) isolation on outbound calls, provision one Loyva API key per tenant:

  • Each key has its own rate_limit_rpm ceiling, preventing one tenant from consuming another's quota
  • Each key has its own scopes, so a tenant integration grants only what it needs

Create each key yourself via POST /api/v2/partners/keys (self-serve), or ask your Loyva point of contact to provision the set in one batch for high-volume/automated onboarding.

Webhooks are not routed per key

Webhook endpoints are org-wide. Registering an endpoint does not tie it to an API key, and events are not attributed to the key that caused them — most events have no key at all (console actions, scheduled jobs, inbound provider webhooks).

Route by tenant inside your receiver, using customer_id or your own external_id:

POST https://your-app.com/hooks/loyva → switch on data.customer_id → dealer 123 / 456

Use external_id on envelopes to correlate Loyva records with your own tenant IDs.

Keys and webhooks are separate​

An API key authenticates your outbound calls to Loyva. A webhook endpoint receives Loyva's inbound calls to you. They are independent objects:

  • Endpoints are org-wide and are not attached to a key
  • Creating, rotating, or revoking a key has no effect on webhook delivery
  • Each endpoint has its own signing secret, unrelated to any API key

Manage endpoints under Webhooks.

Webhook deliveries​

Every attempted delivery is recorded — status, response code and body, attempt count, duration, and next retry time — and is readable self-serve via GET /api/v2/webhooks/endpoints/:endpoint_id/deliveries or in the console. Any delivery can be replayed. See Managing endpoints.

Security best practices​

  1. Never commit keys to source control — use environment variables or a secrets manager.
  2. Never expose keys in frontend code — keys are for server-to-server use only. Mint short-lived embed tokens for the browser instead.
  3. Use separate keys per environment — dev, staging, production.
  4. Scope keys minimally — only request the scopes your integration actually needs.
  5. Rotate on a schedule — rotations are atomic; plan for a brief window where both old and new secrets are deployed during the cut-over.
  6. Monitor last_used_at — if a key hasn't been used, it may be leaked or unnecessary; ask for it to be deactivated.