Clientes
Con estos endpoints tu tienda busca a sus compradores entre los clientes del comercio, los registra y corrige sus datos. El cliente de una venta es a quien se le emite la factura electrónica, así que sus datos fiscales tienen que estar completos.
| Endpoint | Permiso |
|---|---|
GET /customers | customers:read |
GET /customers/{id} | customers:read |
POST /customers | customers:write |
PATCH /customers/{id} | customers:write |
POST /customers/{id}/companies | customers:write |
DELETE /customers/{id}/companies/{companyId} | customers:write |
Los clientes son los mismos que ve el comercio en Clientes: uno creado por la API aparece ahí, y uno creado en el POS se encuentra por la API. Por la API no se eliminan clientes.
El cliente y sus compañías
fiscalCategorydice qué clase de comprador es:no_contribuyente(consumidor final),contribuyente_natural,contribuyente_juridicooextranjero.companyes la compañía principal a la que se le factura: su tipo, nombre, RUC y DV. Unno_contribuyenteno tiene; los demás la necesitan.additionalCompaniesson otras compañías a las que también se le puede facturar al mismo cliente, por ejemplo una persona que a veces compra para su empresa. Para facturarle a una de ellas, envía suidcomocompanyIden .
company.type | Para |
|---|---|
natural | Persona natural con RUC (cédula) |
juridica | Empresa |
gobierno | Entidad del Estado |
extranjero_natural, extranjero_juridico | Extranjero: en ruc va el pasaporte o el ID fiscal de su país, y lleva country (código ISO de dos letras, como US) |
Buscar clientes
GET /customers| Parámetro | Tipo | Descripción |
|---|---|---|
search | texto, hasta 120 caracteres | Busca por nombre, correo, teléfono, identificación o el RUC de cualquiera de sus compañías |
email | texto | Solo el cliente con ese correo exacto, sin importar mayúsculas |
ruc | texto | Solo los clientes que tienen una compañía con ese RUC exacto. Da igual si lo escribes con o sin guiones: 8-123-456 encuentra 8123456 |
page | entero | Página, desde 1. Por defecto 1 |
limit | entero | De 1 a 100. Por defecto 50 |
Antes de crear un cliente, búscalo por email o ruc para no duplicarlo.
curl "https://api.zenci.app/public/v1/customers?ruc=155612345-2-2015" \
-H "Authorization: Bearer $ZENCI_API_KEY"{
"data": [
{
"id": "u3i7o1p5a9s2d6f0g4h8j2k6",
"fullName": "Ana Pérez",
"fiscalCategory": "contribuyente_juridico",
"email": "ana@ejemplo.com",
"phone": "+507 6000-0000",
"identification": null,
"address": "Calle 50",
"province": "Panamá",
"city": "Panamá",
"district": "San Francisco",
"company": {
"id": "t5y9u3i7o1p4a8s2d6f0g4h8",
"type": "juridica",
"name": "Distribuidora ABC, S.A.",
"ruc": "155612345-2-2015",
"dv": "45",
"country": null
},
"additionalCompanies": [],
"createdAt": "2026-09-14T15:02:11.000Z",
"updatedAt": "2026-10-02T21:15:40.000Z"
}
],
"pagination": { "page": 1, "limit": 50, "total": 1, "totalPages": 1 }
}GET /customers/{id} devuelve un cliente con la misma forma. Uno que no existe, o de otro comercio, responde 404.
Crear un cliente
POST /customers| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
fullName | texto | Sí | Nombre del cliente |
fiscalCategory | texto | Sí | Ver |
company | objeto | Según fiscalCategory | Obligatoria para contribuyentes y extranjeros; se omite para no_contribuyente |
company.type | texto | Sí | Ver la tabla de arriba |
company.name | texto | Sí | Razón social o nombre con el que se factura |
company.ruc | texto | Sí | RUC, cédula o, para extranjeros, pasaporte o ID fiscal |
company.dv | texto | No | Dígito verificador. Si no lo envías, Zenci lo toma de la DGI |
company.country | texto | Para extranjeros | Código ISO de dos letras |
email | texto | Para extranjeros | Correo del cliente. Si lo tiene, la DGI le envía las facturas |
phone, identification | texto | No | Teléfono e identificación |
address, province, city, district | texto | No | Dirección |
curl -X POST https://api.zenci.app/public/v1/customers \
-H "Authorization: Bearer $ZENCI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fullName": "Ana Pérez",
"fiscalCategory": "contribuyente_juridico",
"email": "ana@ejemplo.com",
"company": {
"type": "juridica",
"name": "Distribuidora ABC, S.A.",
"ruc": "155612345-2-2015"
}
}'Responde 201 con el cliente, ya con el dv que puso la DGI.
El RUC y el DV
La DGI rechaza una factura sin DV, y la factura de una venta por API se emite sola, lejos de quien puede corregir el dato. Por eso Zenci revisa la compañía al guardarla:
- Consulta el RUC en el registro de la DGI. Si no está registrado, responde
400(RUC "…" is not registered with the DGI). - Si no enviaste
dv, guarda el que tiene la DGI. - Si enviaste un
dvdistinto del de la DGI, responde400y dice cuál es el correcto. - Si la DGI no responde en ese momento, el cliente se guarda solo si enviaste el
dv; si no, responde400y puedes reintentar.
Las compañías extranjeras no pasan por la DGI.
Corregir un cliente
PATCH /customers/{id}Envía solo los campos que cambian; los que no envías quedan como estaban. address, province, city y district aceptan null para borrarlos.
companycorrige la compañía principal, con la misma revisión de RUC y DV que al crear.- Para pasar a contribuyente a un
no_contribuyente, envíafiscalCategoryycompanyjuntos. - Para pasar a
no_contribuyente, envía solofiscalCategory: la compañía principal se quita.
No pisar un cambio del comercio
Alguien del comercio puede estar editando el mismo cliente en el POS. Para no pisar su cambio, envía expectedUpdatedAt con el updatedAt que leíste:
{
"expectedUpdatedAt": "2026-10-02T21:15:40.000Z",
"phone": "+507 6111-1111"
}Si el cliente cambió desde entonces, la respuesta es 409 conflict y no se guarda nada: vuelve a leerlo y decide. Sin expectedUpdatedAt, tu cambio se aplica sobre lo que haya.
Compañías adicionales
POST /customers/{id}/companies
DELETE /customers/{id}/companies/{companyId}El cuerpo de POST es el mismo objeto que company y pasa por la misma revisión de RUC y DV. Responde 201 con la compañía. Un RUC que el cliente ya tiene responde 409.
DELETE quita una compañía adicional y responde 204. La compañía principal no se quita por aquí: se cambia con PATCH o pasando el cliente a no_contribuyente.
Errores frecuentes
| HTTP | Mensaje | Causa |
|---|---|---|
400 | "company" is required for fiscalCategory "…" | Un contribuyente o extranjero sin compañía |
400 | "ruc" is required for a company of type "…" | Una compañía nacional sin RUC |
400 | RUC "…" is not registered with the DGI | El RUC no existe en la DGI |
400 | "dv" does not match the DGI registry… | El DV enviado no es el de la DGI |
400 | email is required for extranjero customers | Un extranjero sin correo |
409 | Customer with this email already exists | Ya hay un cliente con ese correo: búscalo con ?email= |
409 | This customer already has a company with this RUC | La compañía adicional repite un RUC del cliente |
409 | The record changed since you read it… | El cliente cambió desde tu expectedUpdatedAt |
Siguientes pasos
- — Vende a nombre del cliente y de su compañía.
- — Entérate si una factura no se pudo emitir por datos del cliente.