Innbocks Partner API

Build your CRM and billing system on top of Innbocks operations.

Use `/api/v1` to provision invited customers, map external CRM IDs, read compliance and mail state, request mail actions, inspect webhooks, and reconcile active mailbox usage.

Authentication

Create scoped keys in Dashboard Settings, then send them as `Authorization: Bearer ib_live_...`.

Idempotency

Send `Idempotency-Key` on customer creation, updates, deactivation, and mail-action requests to safely retry CRM jobs.

Errors

Errors use `"error": { "code", "message", "request_id" }. Every response includes `X-Request-Id`.

Inbound Mail Operations

Partners with `mail:write` can create inbound mail/package records for their own customers. The API requires `customer_id`, `type`, at least one photo URL, and `performed_by`. Innbocks verifies that the customer belongs to the partner, has active billing/prepay, and is approved for mailbox receipt before emitting `mail.arrived` or `package.arrived`. Reassignment is intentionally not exposed; delete a partner-created mail record and recreate it if your system assigned it incorrectly.

MVP Endpoints

POST/api/v1/customersCreate an invited customer and mailbox
GET/api/v1/customersList customers
GET/api/v1/customers/{customer_id}Retrieve a customer
PATCH/api/v1/customers/{customer_id}Update CRM-managed fields
POST/api/v1/customers/{customer_id}/deactivateDeactivate service
GET/api/v1/customers/{customer_id}/complianceRead Form 1583 and ID status
GET/api/v1/customers/{customer_id}/mailList customer mail
GET/api/v1/customers/{customer_id}/mailboxRead mailbox assignment
POST/api/v1/mailCreate inbound mail/package
GET/api/v1/mail/{mail_id}Retrieve a mail item
DELETE/api/v1/mail/{mail_id}Delete partner-created mail
POST/api/v1/mail/{mail_id}/scanRequest scan
POST/api/v1/mail/{mail_id}/forwardRequest forwarding
POST/api/v1/mail/{mail_id}/shredRequest shredding
POST/api/v1/mail/{mail_id}/pickupRequest pickup
GET/api/v1/webhook-eventsList event types
GET/api/v1/webhook-deliveriesList webhook delivery attempts
GET/api/v1/billing/usageRead active-mailbox usage

Scopes

customers:readcustomers:writemail:readmail:writemail_actions:writewebhooks:readbilling:read

Create Customer

curl -X POST https://app.innbocks.com/api/v1/customers \
  -H "Authorization: Bearer ib_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm_customer_123_create" \
  -d '{
    "external_customer_id": "crm_customer_123",
    "email": "jane@example.com",
    "name": "Jane Smith",
    "phone": "+15555555555",
    "prepay": true
  }'

Create Inbound Mail

curl -X POST https://app.innbocks.com/api/v1/mail \
  -H "Authorization: Bearer ib_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: inbound_mail_789" \
  -d '{
    "customer_id": "cus_123",
    "type": "package",
    "photos": ["https://example.com/package-front.jpg"],
    "performed_by": "warehouse_user_42",
    "tracking_number": "1Z9999999999999999"
  }'

Webhook Verification

import crypto from "crypto";

export function verifyInnbocksWebhook(rawBody, timestamp, signatureHeader, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest("hex");

  const received = signatureHeader
    ?.split(",")
    .map((part) => part.trim())
    .find((part) => part.startsWith("v1="))
    ?.slice(3);

  return Boolean(received) &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
}