Skip to content

API overview

The OpenPartner API is a REST service over HTTPS that returns JSON. It’s the same API used by the SDK, the portal, and the click router — there’s no internal-only surface.

Base URL

The API is served from your OpenPartner instance under /api:

  • Hosted, multi-tenant: https://app.openpartner.dev/api/t/<your-slug> — the path includes your tenant slug between /api and the route. Find your slug in any of your portal URLs (/t/<slug>/...).
  • Self-host: https://your-host.example.com/api (no tenant slug — single-tenant mode).

Leaving the slug out of the URL on a multi-tenant install returns:

HTTP 400
{ "error": "tenant_slug_missing", "detail": "..." }

Throughout this reference, <base> refers to the appropriate URL above.

Authentication

Three modes:

ModeUse for
Session cookie (op_session)Browser portal. Set by /auth/magic/verify.
Bearer admin keyServer-to-server. Set via ADMIN_API_KEY env, or rotated via POST /api-keys. Behaves as headless admin.
Bearer scoped keyServer-to-server with narrow permissions. Mint under Admin → CRM integration. Recommended for Zapier / ActivePieces / CRM webhook integrations — a leak can’t escalate to full admin.

Send the key as Authorization: Bearer <key>. Scoped keys carry a comma-separated list of scopes — see the per-endpoint reference for which scope each route requires.

The current bundled scope set (minted by Admin → CRM integration):

  • events:writePOST /attribution/events
  • partners:writePOST /partners, POST /partners/:id/revoke
  • partners:readGET /partners, GET /partners/:id
  • commissions:readGET /commissions, GET /partners/:id/commissions

Conventions

  • Timestamps: ISO 8601 strings in UTC.
  • Money: decimal strings (e.g. "12.00") plus an ISO 4217 currency code. Stored as Postgres numeric; comes back through the JSON layer as a string to avoid float precision loss.
  • IDs: ULIDs, sometimes prefixed by entity type (e.g. prt_<ulid> for partnerships, evt_<ulid> for events). Partner IDs are bare ULIDs.
  • Pagination: cursor-based via ?cursor=...&limit=.... Endpoints that support it return a nextCursor field (null on the last page).
  • Errors: { "error": "<code>", "detail"?: "..." } with the appropriate HTTP status. The error field is a stable machine-readable code; detail is human-readable.

Endpoint reference

  • Partners — create, list, invite, revoke
  • Events — record conversion events for attribution
  • Commissions — list + per-partner commissions
  • Webhooks — subscribe to outbound events + signature verification