Partner Program API
The Partner Program API is a server-to-server interface for partners who provision and
manage FleetQ teams on behalf of their own customers. It is fully separate from the per-user
REST API (Sanctum bearer tokens) —
partner endpoints live under /api/partner/v1 and
authenticate with a single partner key rather than a user token.
Authentication
Every request must send your partner key in the X-Partner-Key
header. The platform stores only a SHA-256 hash of the key, so the raw value is shown once
at creation time and cannot be recovered afterwards.
curl -X POST https://fleetq.net/api/partner/v1/teams \
-H "X-Partner-Key: pk_finance_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp", "owner_email": "[email protected]"}'
Missing or invalid/revoked keys return 401.
All partner endpoints are rate-limited to 120 requests/minute; some sensitive
endpoints (credit refund, source quotas, cost analytics) carry a tighter 60/min limit.
Team lifecycle
Provision and manage the teams that belong to your partner program. Teams provisioned through the Partner API are linked to your program and are not visible to other partners.
| Method | Path | Purpose |
|---|---|---|
| POST | /teams | Provision a new team (creates the team + owner) |
| DELETE | /teams/{teamId} | Destroy a team and its data |
| POST | /teams/{teamId}/members | Add a member to a team |
| DELETE | /teams/{teamId}/members/{userId} | Remove a member from a team |
| POST | /teams/{teamId}/suspend | Suspend a team (halts activity, retains data) |
| POST | /teams/{teamId}/credits/refund | Refund platform credits to a team (60/min) |
Sub-program scoping & source quotas
A partner key can be scoped to one or more sub-programs. The allowed sub-program slugs
are stored in the key's metadata.allowed_sub_programs
list (set at key-creation time, or * for all). Sub-program endpoints require the requested
{slug} to be in that list, otherwise the request
is rejected with 403.
| Method | Path | Purpose |
|---|---|---|
| GET | /sub-programs/{slug}/cost-analytics | Cost & revenue analytics for the sub-program |
| GET | /sub-programs/{slug}/source-quotas | List per-team monthly credit caps by source |
| PUT | /sub-programs/{slug}/source-quotas/{teamId} | Set/update a team's source quota |
Webhooks
Register HTTP endpoints to receive lifecycle events for your program's teams. Webhook endpoints are managed self-service through the Partner API:
| Method | Path | Purpose |
|---|---|---|
| GET | /webhook-endpoints | List registered endpoints |
| POST | /webhook-endpoints | Register an endpoint (returns its signing secret) |
| DELETE | /webhook-endpoints/{endpointId} | Remove an endpoint |
| GET | /webhook-endpoints/{endpointId}/deliveries | Delivery log for an endpoint |
Event types
| Event | Fires when |
|---|---|
| team.provisioned | A team is provisioned for the program |
| team.suspended | A team is suspended |
| plan.changed | A team's plan changes (includes payment context) |
| pack.purchased | A credit pack is purchased (pack key + credits added) |
| credits.refunded | Credits are refunded to a team |
| credits.reset | Monthly credit allotment resets |
| credits.threshold | A team crosses a credit-usage threshold |
Delivery, signing & idempotency
Each delivery is a JSON POST with this envelope:
{
"id": "01HX...",
"event": "team.provisioned",
"created_at": "2026-06-09T12:00:00+00:00",
"data": { "team_id": "...", "team_name": "...", "plan": "...", "credits": { } }
}
Headers on every delivery:
| Header | Value |
|---|---|
| X-Partner-Signature | sha256=<HMAC-SHA256(body, endpoint secret)> — verify before trusting the payload |
| X-Partner-Event | The event type (matches the event field) |
| X-Partner-Delivery | Unique delivery id — use for idempotency / dedup on retries |
X-Partner-Signature with a constant-time comparison. Reject deliveries that
fail signature verification.
Failed deliveries are retried up to 5 times with exponential backoff
(~10s, 30s, 2m, 10m, 1h). After the final attempt the delivery is marked
failed. Always treat
X-Partner-Delivery as the idempotency key —
the same delivery may arrive more than once.
Operator: issuing partner keys
FleetQ operators create a partner program and issue its key with an Artisan command (super-admin only). The raw key is printed once and only the SHA-256 hash is persisted.
php artisan partner-programs:create \
--name="Finance" \
--slug=finance \
--allowed-sub-programs=finance,hr
Pass --allowed-sub-programs=* to allow all sub-programs, or omit it to leave the key
without sub-program access (the cost-analytics API then returns 403).