Skip to content

Customers

Customer objects let you create a persistent customer profile that you can associate with transactions, payment methods, subscriptions, and invoices.

Using Customers gives you a consolidated view of each customer’s activity in your dashboard, and lets you automatically send receipts without having to specify the email on every payment.

Customer vs. anonymous payment

You can create PaymentIntents without a Customer (anonymous payments), but associating a Customer enriches your data: full history, saved payment methods, automatic receipts, and improved fraud detection.

Endpoints

MéthodeEndpointDescription
POST/customers/Create a new Customer
GET/customers/List Customers (paginated, filterable)
GET/customers/{id}/Retrieve a Customer by its ID
PATCH/customers/{id}/Update a Customer's data
DELETE/customers/{id}/Permanently delete a Customer
GET/customers/{id}/transactions/List the Customer's transactions
GET/customers/{id}/payment-methods/List the Customer's payment methods

Object schema

ResponseCustomer object
Full structure returned by all endpoints of this resource.
json
{
  "id": "cust_3Nx8mLKZ2eZvKYlo",
  "object": "customer",
  "app": "app_xxxxxxxx",
  "email": "client@email.com",
  "firstname": "Madeleine",
  "lastname": "Nguema",
  "phone": "+24177654321",
  "address": null,
  "status": "active",
  "is_blacklisted": false,
  "transactions_count": 14,
  "total_spent": 245000,
  "currency": "XAF",
  "metadata": {
    "internal_id": "USER-00123"
  },
  "created_at": "2026-01-15T08:30:00Z",
  "updated_at": "2026-03-01T10:00:00Z"
}

Create a Customer

Creates a new customer profile associated with your App. The email is the Customer’s unique identifier — two customers of the same App cannot share the same email.

POSTRequest body
emailRequis
stringemailex :client@email.com

Unique email address of the Customer within your App. Used for automatically sending receipts and as a deduplication key.

If you attempt to create a Customer with an email that already exists for the same App, the API returns a 409 Conflict error — it does not create a duplicate. Use PATCH to update an existing Customer.

nameRequis
stringex :Madeleine Nguema

Full name of the Customer. The backend automatically splits this field into firstname and lastname (split on the first space). The returned object exposes both fields separately.

For compound names (e.g. “Jean-Claude” or “Madeleine Nguema Obame”), the split happens on the first space. “Jean-Claude Ondo” → firstname: Jean-Claude, lastname: Ondo.

phoneOptionnel
stringE.164ex :+24177654321

Phone number in international E.164 format. Required for Mobile Money payments associated with this Customer.

En savoir plus

The E.164 format starts with + followed by the country code and the local number without spaces or dashes. Valid examples: +24177000001 (Gabon), +237612345678 (Cameroon). Local formats (e.g. 077 000 001) are rejected.

metadataOptionnel
object

Key/value dictionary for storing your own identifiers — user ID from your database, contract number, customer segment, etc.

En savoir plus

Metadata is returned in all webhooks related to this Customer. Max 50 keys, 500 characters per value. Not indexed — cannot be used as a search criterion via the API.

Create a Customer

bash
curl -X POST https://api.sangho.ga/v1/customers/ \
  -H "Authorization: Bearer sk_prod_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@email.com",
    "name": "Madeleine Nguema",
    "phone": "+24177654321",
    "metadata": { "internal_id": "USER-00123" }
  }'
Response201 Created
The Customer is created. The firstname and lastname fields are automatically derived from the provided name field.
json
{
  "id": "cust_3Nx8mLKZ2eZvKYlo",
  "object": "customer",
  "app": "app_xxxxxxxx",
  "email": "client@email.com",
  "firstname": "Madeleine",
  "lastname": "Nguema",
  "phone": "+24177654321",
  "address": null,
  "status": "active",
  "is_blacklisted": false,
  "transactions_count": 0,
  "total_spent": 0,
  "metadata": { "internal_id": "USER-00123" },
  "created_at": "2026-03-01T10:00:00Z",
  "updated_at": "2026-03-01T10:00:00Z"
}
Response409 Conflict — Email already in use
A Customer with this email already exists for this App. Use GET /customers/?search={email} to find it, then PATCH to update it.
Sangho never creates a duplicate. The conflict is returned cleanly so you can handle deduplication server-side.
json
{
  "error": {
    "type": "conflict_error",
    "code": "customer_email_exists",
    "message": "A Customer with this email already exists.",
    "param": "email"
  }
}

List Customers

GETQuery parameters
statusOptionnel
string

Filter by status. Values: active, inactive, blocked.

orderingOptionnel
stringdéfaut :-created_at

Sort order of results. Available fields: created_at, email, total_spent.

pageOptionnel
integerdéfaut :1

Page number (offset pagination, starts at 1).

page_sizeOptionnel
integerdéfaut :20

Results per page. Minimum: 1. Maximum: 100.

Update a Customer

Modifies one or more fields of an existing Customer. All fields are optional — only the fields provided are updated.

PATCHUpdate body (PATCH)
emailOptionnel
stringemail

New email. Must be unique among the App’s Customers. Returns 409 if already in use.

nameOptionnel
string

New full name. Re-split into firstname / lastname on the backend.

phoneOptionnel
stringE.164

New phone number in E.164 format. Pass null to remove it.

metadataOptionnel
object

Merges metadata. Existing keys not mentioned are kept. Pass a key with value null to remove it.

En savoir plus

Example: if the Customer has { "a": "1", "b": "2" } and you send { "b": null, "c": "3" }, the result will be { "a": "1", "c": "3" }.

Delete a Customer

Permanently deletes a Customer (hard delete). This action is irreversible.

Permanent deletion

Deleting a Customer is permanent. Their past transactions are retained in the logs for OHADA legal compliance reasons, but the customer profile itself is destroyed. In-progress PaymentIntents associated with this Customer remain valid but lose the Customer reference.

Search Customers

bash
curl "https://api.sangho.ga/v1/customers/?search=madeleine&status=active" \
  -H "Authorization: Bearer sk_prod_xxxx"

Update a Customer

bash
curl -X PATCH https://api.sangho.ga/v1/customers/cust_xxx/ \
  -H "Authorization: Bearer sk_prod_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+24166000001",
    "metadata": { "plan": "premium", "legacy_id": null }
  }'
Response200 OK — Customer updated
Returns the full Customer object with the modified fields. Metadata reflects the applied merge.
json
{
  "id": "cust_3Nx8mLKZ2eZvKYlo",
  "object": "customer",
  "email": "client@email.com",
  "firstname": "Madeleine",
  "lastname": "Nguema",
  "phone": "+24166000001",
  "status": "active",
  "metadata": {
    "internal_id": "USER-00123",
    "plan": "premium"
  },
  "updated_at": "2026-03-15T14:00:00Z"
}

Delete a Customer

bash
curl -X DELETE https://api.sangho.ga/v1/customers/cust_xxx/ \
  -H "Authorization: Bearer sk_prod_xxxx"
Response204 No Content — Deleted
The deletion succeeded. No response body is returned.