Skip to main content
Use Lodger from trusted server-side code. API keys are secrets and should not be shipped to browsers or mobile apps.

Request handlers

Record user actions after your application has committed the underlying change.
await removeMember(member.id)

await lodger.event(
  "organization.member.removed",
  {
    actor: { id: user.id, type: "user", email: user.email },
    target: { id: member.id, type: "organization_member" },
    metadata: { organizationId: organization.id },
  },
  {
    request: {
      requestId: request.headers.get("x-request-id"),
      sessionId: session.id,
      traceId: request.headers.get("x-trace-id"),
    },
  }
)

Jobs and workers

Use a service actor for background work.
await lodger.event("billing.invoice.paid", {
  actor: { id: "billing-worker", type: "service" },
  target: { id: invoice.id, type: "invoice" },
  metadata: {
    customerId: invoice.customer,
    amount: invoice.amount_paid,
    currency: invoice.currency,
  },
  source: "automation",
  userVisible: true,
})

Webhooks

Use webhook delivery IDs as idempotency keys when possible.
await lodger.event(
  "billing.invoice.paid",
  {
    actor: { id: "billing-webhook", type: "service" },
    target: { id: invoice.id, type: "invoice" },
    metadata: { webhookEventId: event.id },
  },
  { idempotencyKey: `billing_${event.id}` }
)

Customer activity

Only mark records userVisible: true when they should be visible in customer-facing activity history. Internal security and support records should stay internal unless you have a reason to expose them. Do not build a public form that accepts a user ID or email and calls Lodger directly. Mint a scoped activity token from your backend after your own app has authenticated the user.
const activity = await lodger.activityToken(user.id, {
  projectId: "core",
  expiresInSeconds: 60 * 15,
})

return activity.activityUrl
activityUrl stores the token in the URL fragment. When reading activity directly, the SDK sends that token as a bearer token instead of a query string.