Partner API
The Partner API is for the partner’s servers: it takes a partner secret key (psk_live_…/psk_test_…) as
Authorization: Bearer and refuses browsers (no CORS). The full reference is Partner API; the
Node, PHP, Python and Go helpers include a client.
Stores
Section titled “Stores”Create a store when a business is created on your platform. The call is idempotent on externalRef: repeating it
returns the same store, so retries are safe.
// When a store opens on your platform: idempotent on externalRef, so retrying returns the same store.export async function openStore(shop: { id: string name: string ownerName: string ownerEmail: string}) { const store = await nexafon.stores.create({ externalRef: shop.id, name: shop.name, owner: { name: shop.ownerName, email: shop.ownerEmail }, country: 'SO', timezone: 'Africa/Mogadishu', locale: 'so', }) return store.workspaceId}curl -X POST "https://api.nexafone.so/api/v1/partner/stores" \ -H "Authorization: Bearer $NEXAFON_PARTNER_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{"externalRef": "shop-1", "name": "Shop One", "owner": {"name": "Amina Ali", "email": "[email protected]"}, "country": "SO", "timezone": "Africa/Mogadishu", "locale": "so"}'The new store starts on your default store plan with its subscription running, and answers with its workspaceId.
Then:
| Operation | |
|---|---|
GET /api/v1/partner/stores |
Your stores, paged |
GET /api/v1/partner/stores/{externalRef} |
One store |
PATCH /api/v1/partner/stores/{externalRef} |
Rename it, or reopen a closed store with status: active |
POST /api/v1/partner/stores/{externalRef}/close |
Close it: it becomes read-only and keeps its data |
GET /api/v1/partner |
Your partner profile, status and default plan’s features |
Acting inside a store
Section titled “Acting inside a store”The same key calls the workspace operations of the API for your own stores, by workspaceId:
curl "https://api.nexafone.so/api/v1/workspaces/$WORKSPACE_ID/conversations" \ -H "Authorization: Bearer $NEXAFON_PARTNER_SECRET_KEY"A workspace that is not one of your stores (another partner’s, or a business outside your platform) answers 404,
exactly like one that does not exist. The key’s workspace scopes limit what it may do there.
Staff sign in with partner user tokens, which create or update their membership of each store they list. Leaving a store out of a token does not remove access; tell Nexafon explicitly:
// Staff are managed on your platform: change a role or remove someone from a store when they change there.export async function staffChanged(storeRef: string, userId: string, role: string | null) { if (role === null) await nexafon.members.disable(storeRef, userId) else await nexafon.members.update(storeRef, userId, { role })}| Operation | |
|---|---|
PUT /api/v1/partner/stores/{externalRef}/members/{partnerUserId} |
Change the user’s role (and teams) in that store; their menu updates live |
DELETE /api/v1/partner/stores/{externalRef}/members/{partnerUserId} |
Disable them in that store; their open sessions end within seconds |
The store’s PayPoint key
Section titled “The store’s PayPoint key”Store sales are paid into the store’s own PayPoint account (see store payments):
| Operation | |
|---|---|
PUT /api/v1/workspaces/{workspaceId}/payments/paypoint |
Save the store’s API key and merchant id; answers only “saved” and the last 4 characters |
POST …/payments/paypoint/test |
Check the key with PayPoint without charging anyone |
PUT …/payments/paypoint/wallets |
The wallets customers may pay with |
DELETE …/payments/paypoint |
Remove the key |
The key is encrypted at rest and never returned or logged.
Retries and idempotency
Section titled “Retries and idempotency”Creating operations accept an Idempotency-Key header; see the API overview. Rate limits are
per key (rate limits).