Skip to main content

Customers

End-customers are the users of your store. You create them when your billing system records a successful subscription.

Base URL: https://genvoris.org/api/v1 — all endpoints require Authorization: Bearer <store_api_key>.

Create or upsert

POST /customers
{
"externalId": "user_42",
"email": "shopper@example.com",
"planId": "pln_xxxxxxxx",
"metadata": { "stripe_subscription_id": "sub_..." }
}
FieldTypeRequiredNotes
externalIdstringyesYour stable id. Unique per store — re-POSTing upserts and rolls the period forward.
emailstringnoOptional, for your reporting
planIdstringnoPlan id; unset = no quota = every try-on returns 402
metadataobjectnoFree-form JSON, returned on read

The endpoint is idempotent — call it on every subscribe / renew without checking existence first.

List customers

GET /customers?status=ACTIVE&limit=50&cursor=ec_abc
ParamDefaultDescription
statusnoneACTIVE, PAUSED, or CANCELLED
limit501–200
cursornonePagination cursor returned by the previous page
{
"data": [/* customers, includes nested plan */],
"next_cursor": "ec_xyz"
}

Read one customer

GET /customers/{id}

Includes the plan and the last 12 usage rows.

Update a customer

PATCH /customers/{id}
{
"email": "new@example.com",
"planId": "pln_other",
"status": "PAUSED",
"resetPeriod": true
}
FieldNotes
emailPass null to clear
planIdPass null to detach the plan (subsequent try-ons → 402 no_plan)
statusACTIVE / PAUSED / CANCELLEDPAUSED and CANCELLED block try-ons
metadataPass null to clear
resetPeriodWhen true, sets periodStart=now, periodEnd=now+30d

Cancel a customer

DELETE /customers/{id}

Soft cancel — preserves usage history. Future try-ons return 402 cancelled.

Read usage

GET /customers/{id}/usage

Returns the customer's plan, current-period quota state, and the last 24 usage buckets.

{
"data": {
"customer_id": "ec_abc",
"external_id": "user_42",
"plan": { "id": "pln_xxxx", "name": "Pro", "monthlyTryOns": 100 },
"status": "ACTIVE",
"period_start": "2026-04-28T00:00:00.000Z",
"period_end": "2026-05-28T00:00:00.000Z",
"current": { "used": 32, "limit": 100, "remaining": 68, "ok": true },
"history": [/* per-period */]
}
}