# Spenza Partner API ## Docs - [Poll the status of any v3 async operation](https://docs.spenza.com/api-reference/async-status/poll-the-status-of-any-v3-async-operation.md): Universal status poll for any async endpoint that returns a `transactionId` — plan purchase, eSIM provisioning, top-up, port-in, subscription changes. **No authentication required** — the `transactionId` itself is the bearer, matching every other endpoint that hands one out. - [Exchange credentials for a token](https://docs.spenza.com/api-reference/authentication/exchange-credentials-for-a-token.md): Exchange your API key and secret for a 1-hour bearer token. This endpoint itself requires no authentication — your key and secret *are* the credentials being verified. - [Add prepaid credit](https://docs.spenza.com/api-reference/billing/add-prepaid-credit.md): Create a hosted Stripe checkout link to add prepaid credit. `amount` is in the currency's **major unit** (e.g. `100` = $100.00). The returned `transactionId` moves to `COMPLETED`/`FAILED` once Stripe's checkout webhook fires — poll `statusEndpoint`, not this call, for the outcome. - [Download invoice PDF](https://docs.spenza.com/api-reference/billing/download-invoice-pdf.md): On success, returns a `302` redirect to the PDF URL — **no JSON envelope on the 302 itself**, this is the one endpoint that writes a raw HTTP response instead of the standard envelope. Error responses are still the standard JSON envelope. - [Get an invoice](https://docs.spenza.com/api-reference/billing/get-an-invoice.md): Get a single invoice's full detail, line items, and usage breakdown. - [Get credit balance](https://docs.spenza.com/api-reference/billing/get-credit-balance.md): Available prepaid credit balance by currency. - [List invoices](https://docs.spenza.com/api-reference/billing/list-invoices.md): List invoices, paginated, with date filters. `from`/`to` are **date-only** (`YYYY-MM-DD`) here — unlike Orders/Transactions, which take full ISO datetimes. - [Create a device-group](https://docs.spenza.com/api-reference/device-groups/create-a-device-group.md) - [Delete a device-group](https://docs.spenza.com/api-reference/device-groups/delete-a-device-group.md) - [Get a device-group](https://docs.spenza.com/api-reference/device-groups/get-a-device-group.md) - [List device-groups](https://docs.spenza.com/api-reference/device-groups/list-device-groups.md) - [Move a device into this group](https://docs.spenza.com/api-reference/device-groups/move-a-device-into-this-group.md) - [Remove a device from this group](https://docs.spenza.com/api-reference/device-groups/remove-a-device-from-this-group.md): No default device-group exists, so the device's group is simply cleared (`movedTo` is `null`). - [Update a device-group](https://docs.spenza.com/api-reference/device-groups/update-a-device-group.md) - [Assign a device to a user](https://docs.spenza.com/api-reference/devices/assign-a-device-to-a-user.md): The "user" here is a Employee — the same resource as `/api/v1.1/users` — not a Team Member/admin. - [Get a device](https://docs.spenza.com/api-reference/devices/get-a-device.md): Get a device's details, including who it's currently assigned to. - [List devices in your catalog](https://docs.spenza.com/api-reference/devices/list-devices-in-your-catalog.md): List the phones/tablets you can hand out to your team. - [Unassign a device](https://docs.spenza.com/api-reference/devices/unassign-a-device.md) - [Get eSIM activation QR](https://docs.spenza.com/api-reference/esim/get-esim-activation-qr.md): Re-fetch the eSIM's activation QR image URL and activation code. Deliberately does not regenerate/rotate the eSIM profile on a live carrier — it's a read, not a mutation — so `activationCode` may be `null` if it was never persisted. - [Provision an eSIM, optionally with a plan](https://docs.spenza.com/api-reference/esim/provision-an-esim-optionally-with-a-plan.md): Provision an eSIM. Omit `planId` for a bare eSIM (SIM-only provisioning is only supported for the SpenzaJ carrier family today — other carriers return `501` on the SIM-only path); include `planId` to also activate a plan in the same operation. Always asynchronous — `202` with a `transactionId`/`stat… - [Send an SMS](https://docs.spenza.com/api-reference/messaging/send-an-sms.md): Send a Mobile-Originated (MO) SMS from a number provisioned on your account. Requires the account's `Admin` role tier. **MO SMS is only implemented for some operators** (SpenzaJ today) — everyone else gets `501`. This is a synchronous endpoint that returns `201` directly (NestJS's default for `@Post… - [Get notification preferences](https://docs.spenza.com/api-reference/notifications/get-notification-preferences.md): Always returns the full preference matrix — one entry per event type, even ones you've never touched. Unset keys resolve to that key's default: `sendOnboardingNotification` defaults `true` (opt-out); every other key defaults `false` (opt-in). - [List notifications](https://docs.spenza.com/api-reference/notifications/list-notifications.md): List notifications for your account, newest first. `meta` carries an extra `unreadCount` field alongside the usual pagination fields — `unreadCount` is always the account-wide unread total; it is not filtered by the `status` query parameter and does not reflect the returned page's contents. - [Update a notification preference](https://docs.spenza.com/api-reference/notifications/update-a-notification-preference.md): Enable or disable exactly one preference key per call — despite the plural resource name, this is a single-key update. Returns the full matrix so you can confirm without a follow-up GET. - [Check port-in eligibility](https://docs.spenza.com/api-reference/numbers-&-port-in/check-port-in-eligibility.md): Check whether a number is eligible for port-in without submitting one — read-only, no order created. An ineligible number is a `200` with `eligible: false`, not an HTTP error. Only the **SpenzaJ** carrier actually implements this check today; every other carrier (Simetry, Soracom, EsimGo, CiscoJaspe… - [List port-in requests](https://docs.spenza.com/api-reference/numbers-&-port-in/list-port-in-requests.md): List port-in requests and their status, paginated. - [Submit a port-in](https://docs.spenza.com/api-reference/numbers-&-port-in/submit-a-port-in.md): **The only port-in submission endpoint** — there is no `POST /api/v1.1/port-ins`. Move an existing number from another carrier into Spenza. Always asynchronous. - [Get an order](https://docs.spenza.com/api-reference/orders-&-transactions/get-an-order.md): Get an order and the transactions raised against it (embedded, capped at 100 — use `GET /api/v1.1/transactions` for the full paginated history). - [List orders](https://docs.spenza.com/api-reference/orders-&-transactions/list-orders.md): List order history, paginated. `from`/`to` are **full ISO 8601 datetimes** here (unlike Invoices' date-only filters) — a bare date parses to UTC midnight, so `from == to` collapses the range to a single instant; set `to` to end-of-day explicitly. - [List transactions](https://docs.spenza.com/api-reference/orders-&-transactions/list-transactions.md): Financial transaction history, paginated — charges and refunds. `type` is derived from the sign of `amount` (`REFUND` is negative), and `status` here excludes `OTHER` as a filter value even though it can appear in a response. `from`/`to` are full ISO 8601 datetimes, same same-day-collapse caveat as… - [Get a plan](https://docs.spenza.com/api-reference/plans-&-catalog/get-a-plan.md): Get a plan's details. `planId` is the plan's `productId`. Optionally includes `tieredPricing` (only when `planType` is `PAY_AS_YOU_GO`) and/or `volumeTierPricing` (only when volume-tiered pricing is enabled for the plan) — same conditional fields as the list endpoint. - [List plans](https://docs.spenza.com/api-reference/plans-&-catalog/list-plans.md): List the plans your account may purchase. `search` requires `searchType` to be set (otherwise the search matches nothing rather than erroring loudly). Omitting `category` restricts results to `MSP_PLAN` and `RESELLER_PLAN`; supplying it narrows to exactly that one category. - [List SIM products](https://docs.spenza.com/api-reference/plans-&-catalog/list-sim-products.md): List purchasable SIM products (ACTIVE only) — the physical/eSIM unit itself, separate from a data plan. Each SIM product optionally includes `volumeTierPricing` when volume-tiered pricing is enabled for it. - [Purchase a plan (asynchronous)](https://docs.spenza.com/api-reference/plans-&-catalog/purchase-a-plan-asynchronous.md): Purchase / activate a plan for a SIM, asynchronously — always `202` with a `transactionId` to poll. A different request contract from `POST /api/v1.1/plans/purchase`: `activateNow` defaults from whether `scheduleDate` is set (rather than being required), `scheduleDate` is a full ISO 8601 datetime (n… - [Purchase a plan (synchronous)](https://docs.spenza.com/api-reference/plans-&-catalog/purchase-a-plan-synchronous.md): Purchase / activate a plan for a SIM. Synchronous — blocks and returns the finished purchase. For an async variant, use `POST /api/v3/plans/purchase` instead (a different request/response contract, not an alias of this one). - [Create a sim-group](https://docs.spenza.com/api-reference/sim-groups/create-a-sim-group.md) - [Delete a sim-group](https://docs.spenza.com/api-reference/sim-groups/delete-a-sim-group.md) - [Get a sim-group](https://docs.spenza.com/api-reference/sim-groups/get-a-sim-group.md) - [List sim-groups](https://docs.spenza.com/api-reference/sim-groups/list-sim-groups.md) - [Move a SIM into this group](https://docs.spenza.com/api-reference/sim-groups/move-a-sim-into-this-group.md) - [Remove a SIM from this group](https://docs.spenza.com/api-reference/sim-groups/remove-a-sim-from-this-group.md): The SIM moves back to the account's default sim-group — `movedTo` is the literal string `"default"`, not that group's actual name. - [Update a sim-group](https://docs.spenza.com/api-reference/sim-groups/update-a-sim-group.md) - [Assign a SIM to a user](https://docs.spenza.com/api-reference/sims/assign-a-sim-to-a-user.md): Assign or reassign the SIM to a user, identified by email. Reassigning an already-assigned SIM is supported. If no user exists for that email and `name` is supplied, the user is auto-created; if the user already exists and `name` differs, the profile name is synced best-effort. - [Get a SIM by ICCID](https://docs.spenza.com/api-reference/sims/get-a-sim-by-iccid.md): Get a single SIM by ICCID, account-scoped — another account's SIM reports the same 404 as a nonexistent one. - [Get SIM usage](https://docs.spenza.com/api-reference/sims/get-sim-usage.md): Data / voice / SMS usage for the SIM's current billing cycle. `data.used` is decimal GB (1 GB = 1e9 bytes) sourced from the invoice; `history` is `[]` unless `history=true`, and is empty even then for a SIM not covered by the usage-snapshot pipeline. - [List SIMs](https://docs.spenza.com/api-reference/sims/list-sims.md): List the SIMs on your account, paginated, with live status and assignment. - [Request a new phone number](https://docs.spenza.com/api-reference/sims/request-a-new-phone-number.md): Request a new phone number for the SIM. Rate-limited (a burst backstop — your plan's real monthly quota is enforced separately). - [Cancel a subscription](https://docs.spenza.com/api-reference/subscriptions/cancel-a-subscription.md): Cancel the SIM's subscription. Always cancels at end of the current billing period (`cancelNow: false` under the hood) — an `ACTIVE` subscription typically comes back `CANCEL_SCHEDULED`, not `CANCELLED`. Synchronous. Returns **`201`** (not `200`) on success. - [Get a SIM's subscription](https://docs.spenza.com/api-reference/subscriptions/get-a-sims-subscription.md): Get the subscription attached to a SIM. Falls back to the newest `SCHEDULED` subscription if there's no currently-serving one, so a subscription you can list is never a surprise 404 here. - [List subscriptions](https://docs.spenza.com/api-reference/subscriptions/list-subscriptions.md): List subscriptions across the account, paginated. `status=ACTIVE` (the default) is widened to also include `PENDING` and `CANCEL_SCHEDULED` — the still-serving set. Every other filter value is an exact match. - [Get a team member](https://docs.spenza.com/api-reference/team-members/get-a-team-member.md) - [Invite a teammate as an admin](https://docs.spenza.com/api-reference/team-members/invite-a-teammate-as-an-admin.md) - [List team members](https://docs.spenza.com/api-reference/team-members/list-team-members.md): Team members are account **admins** (Auth0-backed dashboard/API login), a different resource from `/api/v1.1/users` (end users who hold SIMs/plans). - [Remove a team member](https://docs.spenza.com/api-reference/team-members/remove-a-team-member.md) - [Update a team member](https://docs.spenza.com/api-reference/team-members/update-a-team-member.md): `email` itself isn't updatable. - [Create a user-group](https://docs.spenza.com/api-reference/user-groups/create-a-user-group.md) - [Delete a user-group](https://docs.spenza.com/api-reference/user-groups/delete-a-user-group.md) - [Get a user-group](https://docs.spenza.com/api-reference/user-groups/get-a-user-group.md) - [List user-groups](https://docs.spenza.com/api-reference/user-groups/list-user-groups.md): A "user-group" is a Department under the hood — a separate collection from SIM/device groups, with its own independent name uniqueness. - [Move a user into this group](https://docs.spenza.com/api-reference/user-groups/move-a-user-into-this-group.md) - [Remove a user from this group](https://docs.spenza.com/api-reference/user-groups/remove-a-user-from-this-group.md): The user's department is cleared (`movedTo` is `null` — unlike sim-groups, there's no default user-group fallback). - [Update a user-group](https://docs.spenza.com/api-reference/user-groups/update-a-user-group.md) - [Create a user](https://docs.spenza.com/api-reference/users/create-a-user.md): Create a user under your account. `department` is created automatically if it doesn't already exist. - [Delete a user](https://docs.spenza.com/api-reference/users/delete-a-user.md): Remove a user. Fails if the user still has devices assigned, or is the account's default user. - [Get a user](https://docs.spenza.com/api-reference/users/get-a-user.md): Get a user by email. A malformed email in the path is treated as not-found, not a validation error. - [List users](https://docs.spenza.com/api-reference/users/list-users.md): List users (end users / employees) on your account, paginated. - [Update a user](https://docs.spenza.com/api-reference/users/update-a-user.md): Update a user. Any subset of the mutable fields — `email` itself is not updatable. Passing an empty `department` clears it. - [Delete a webhook registration](https://docs.spenza.com/api-reference/webhooks/delete-a-webhook-registration.md) - [Get a webhook registration](https://docs.spenza.com/api-reference/webhooks/get-a-webhook-registration.md) - [List webhook deliveries](https://docs.spenza.com/api-reference/webhooks/list-webhook-deliveries.md): List recent webhook delivery attempts, newest first. Never includes the delivered payload, response body, or raw partner-endpoint error text. - [List webhook registrations](https://docs.spenza.com/api-reference/webhooks/list-webhook-registrations.md): List webhook registrations, paginated in memory. - [Redeliver a webhook event](https://docs.spenza.com/api-reference/webhooks/redeliver-a-webhook-event.md): Queue a redelivery of a past event to its original endpoint, using the stored URL and body of the original attempt (not a regenerated event). Runs on a queue consumer, never in the request cycle — poll the deliveries list for the outcome. - [Register or update a webhook](https://docs.spenza.com/api-reference/webhooks/register-or-update-a-webhook.md): Register a webhook for operator SMS/voice events. At most **one registration per (account, operator, network)** — `eventType` is not part of that key, so registering a second event type for the same operator+network replaces the first. Registering again for an existing combination without `update: t… - [Send a test event](https://docs.spenza.com/api-reference/webhooks/send-a-test-event.md): Send a signed synthetic test event to the registered endpoint. One attempt, no retries. The attempt is recorded in `GET /api/v1.1/webhook-deliveries` but deliberately does **not** count toward the 10-consecutive-failure auto-suspend threshold. Target URL priority (fixed, not event-derived): `message… - [Update a webhook registration](https://docs.spenza.com/api-reference/webhooks/update-a-webhook-registration.md) - [Authentication](https://docs.spenza.com/authentication.md): Exchanging your API key and secret for a bearer token, and using it on every request. - [Core Concepts](https://docs.spenza.com/core-concepts.md): The entities, relationships and patterns that repeat across every endpoint. - [Environments & Versioning](https://docs.spenza.com/environments-versioning.md): Base URLs, how endpoint versioning works, and the one path that doesn't follow the standard contract. - [Errors](https://docs.spenza.com/errors.md): The standard error envelope, the full error-code taxonomy, and how to handle each one. - [FAQ & Troubleshooting](https://docs.spenza.com/faq.md): Answers to common setup, authentication, and integration questions. - [Getting Started](https://docs.spenza.com/getting-started.md): Prerequisites, credentials, and configuring your environment before your first call. - [Guides](https://docs.spenza.com/guides.md): Deeper, task-oriented walkthroughs for the most common integration scenarios. - [Introduction](https://docs.spenza.com/introduction.md): What the Spenza Partner API is, who it's for, and what you can build with it. - [Quickstart](https://docs.spenza.com/quickstart.md): Authenticate, browse the catalog, provision an eSIM with a plan, then confirm usage — end to end. - [Rate Limits](https://docs.spenza.com/rate-limits.md): The published per-endpoint and account-wide limits, and how to back off when you hit one. - [SDKs & Code Examples](https://docs.spenza.com/sdks.md): No official client libraries are published yet — here's how to integrate directly and how to generate your own typed client. - [Security & Best Practices](https://docs.spenza.com/security.md): Protecting credentials, handling sensitive data, and building a resilient client. - [Support](https://docs.spenza.com/support.md): How to reach Spenza API support and what to include for a fast resolution. - [Webhooks](https://docs.spenza.com/webhooks.md): Register endpoints to receive operator SMS and voice events, verify their signature, and inspect deliveries. ## OpenAPI Specs - [openapi](https://docs.spenza.com/openapi.yaml)