Partner API
Provision and manage end-customers entirely server-to-server. The Partner API is for resellers and platform integrators who want to embed Warm AI’s identification under their own brand — without sending their customers into the Warm AI dashboard.
Looking for the standard customer-facing API? See Identification API. The Partner API is only enabled for accounts flagged as partners — contact us if you need partner status enabled.
When to use it
Use the Partner API when:
- You sell a product that bundles visitor identification (cold-email tools, sales-intel platforms, agency dashboards).
- Your customers should never log into a Warm AI URL — you control the UX end-to-end.
- You want per-customer quotas, billing, and reporting that you mirror into your own backend.
You don’t need the Partner API if you’re just identifying visitors on your own site — use the Identification API directly.
How the model works
┌──────────────────────────────────────────────────────────────┐
│ Partner account (you) │
│ ─────────────── │
│ • is_partner = true │
│ • one master api_key (the warm_… you authenticate with) │
│ │
│ ├── Child customer A (parent_api_key_id = master) │
│ │ • own api_key, own quota, own webhook │
│ │ • own tracking_script_id, own domain │
│ │ │
│ ├── Child customer B │
│ └── Child customer C │
└──────────────────────────────────────────────────────────────┘- Each child is a phantom user under your account. They have no login, no email inbox, no dashboard access. They exist purely as a billing + tracking unit you manage on their behalf.
- Each child has its own
api_key(which you can hand back to the customer for server-side calls), its owntracking_script_id(forpulse.jsinstall), its ownsubscriptionrow (quota / period / topup balance), and its own optionalwebhook_url. - All
partner-*endpoints authenticate with your masterx-access-key— never the child’s. The child’s key is for the child’s own tracker traffic.
Authentication
Every Partner API request must include:
| Header | Description |
|---|---|
x-access-key | Your master partner api key (starts with warm_…) |
Content-Type | application/json for POST endpoints |
The API rejects the call with 401 if the key is missing, unknown, or revoked, and 403 if the key is valid but the account isn’t flagged is_partner=true.
Never embed your master x-access-key in a browser, mobile app, or any client-side bundle. It has full provisioning authority over every customer you’ve created — treat it like a Stripe secret key.
Billing model
Each child has its own subscription row with:
| Field | Meaning |
|---|---|
monthly_id_quota | IDs the child gets each period (resets on roll-over). Set this when creating or updating the child. |
ids_used_this_period | Counter, resets to 0 at period roll-over (or when you change monthly_id_quota). |
topup_balance | Non-expiring pool consumed after monthly_id_quota is exhausted. |
current_period_end | When the period rolls over and the counter resets. Defaults to 30 days from creation. |
id_price_pence_override | Your per-ID rate for this child, in pence. Informational — used for partner-side billing math. |
The partner is invoiced for the IDs their children consume, aggregated across all customers, on whatever commercial agreement you have with us. You bill your end-customers however you like — the per-child id_price_pence_override is the unit cost you’ve agreed for that customer, so you can build margin into your own pricing.
Endpoint surface
Five endpoints cover the full customer lifecycle:
| Endpoint | Purpose |
|---|---|
POST partner-create-child-key | Mint a brand-new managed customer (key + tracker + subscription) |
POST partner-update-child | Change a child’s name, quota, rate, status, or period |
GET partner-list-children | Enumerate your customers with their current quota / usage / status |
POST partner-adopt-existing-key | Convert one of your existing direct trackers into a managed customer |
POST partner-release-child | Reverse an adoption — child’s tracker returns to your direct account |
Plus the standard customer-facing endpoints, which you’ll call with the child’s api key (not yours) to fetch their visitors:
| Endpoint | Purpose |
|---|---|
GET list-visitors | Pull identified visitors for one tracker — accepts tracker_site, since, source, search, limit, offset |
GET api-account-status | Quota / topup status for one child |
What’s not in the API yet
These pieces are planned and tracked on the roadmap. Until they ship, work around them as noted.
| Feature | Workaround | Tracking |
|---|---|---|
| Real-time events for period roll-over, quota exhaustion, topup balance changes | The 4 immediate-action events (child.created / updated / released / adopted) are live — see Webhooks. Poll partner-list-children for the rest. | KAN-79 / 80 / 81 |
Partner → child topup transfer (gift IDs from your balance to one child’s topup_balance) | See partner-transfer-topup — atomic transfer with insufficient-balance protection and child.topup_changed(reason="gift") event | ✅ Live |
| Rotate a lost child api key plaintext | See partner-rotate-child-key — rate-limited to 10/child/24h, audit-logged | ✅ Live |
| CDN whitelabel for the tracker script | See separate CDN whitelabel docs (coming soon) | KAN-38 |
Next steps
- Quick Start — end-to-end TypeScript walkthrough: create a child, install the tracker, fetch visitors, release.
- Endpoints — full reference for every
partner-*endpoint. - Webhooks — real-time partner-side state-change events.