Skip to content

Clientes (API) ​

Un cliente representa a la persona a la que cobrarás dentro del proyecto. La forma habitual de crear un cliente es capturando su tarjeta con un : Zelta Pay tokeniza la tarjeta y crea el cliente automáticamente, emitiendo el webhook customer.created. También puedes crear clientes directamente por API y adjuntarles una tarjeta vaulteada.

Un cliente vaulteado es aquel que tiene una tarjeta almacenada de forma segura por un procesador de tarjetas (NMI o Emetec). El cliente registra qué procesador la guardó (paymentProvider), y sus cobros posteriores se hacen con ese mismo procesador. Solo los clientes vaulteados pueden ser cobrados con o suscritos con .

Clientes guardados con NMI

Para cobrar a un cliente cuya tarjeta está guardada en NMI, NMI debe estar activo en para el entorno del cobro. Si activas Emetec (lo que desactiva NMI), los cobros a esos clientes fallan hasta que vuelvas a activar NMI.

Todos los endpoints requieren tu API key de proyecto en el header X-API-Key.

Clientes de un proyecto con tarjeta en bóveda

El objeto cliente ​

Todos los endpoints que devuelven un cliente usan el mismo objeto: los de clientes (crear, obtener y adjuntar vault bajo data.customer; listar bajo data.customers como arreglo, junto con total), las respuestas de que incluyen al cliente y expand=customer en y suscripciones. Los campos ligados a la tarjeta (paymentProvider, cardLast4, cardBrand) son null hasta que el cliente queda vaulteado. Este es un cliente vaulteado, como lo devuelve GET /v1/customers/:id:

json
{
  "success": true,
  "data": {
    "customer": {
      "id": "7315555666677778888",
      "projectId": "7301234567890123456",
      "name": "John Doe",
      "email": "[email protected]",
      "phone": "+50760000000",
      "paymentProvider": "nmi",
      "cardLast4": "1111",
      "cardBrand": "visa",
      "status": "active",
      "metadata": null,
      "createdAt": "2026-06-04T00:00:00.000Z",
      "updatedAt": "2026-06-04T00:00:00.000Z",
      "deletedAt": null
    }
  },
  "message": "Operation completed successfully",
  "timestamp": "2026-06-04T00:00:00.000Z"
}
CampoTipoDescripción
idstringIdentificador único del cliente
projectIdstringProyecto al que pertenece el cliente
namestringNombre del cliente
emailstringCorreo del cliente. Puede ser una cadena vacía si el cliente se creó con un link de colección sin capturar su correo
phonestring | nullTeléfono del cliente (null si no se envió)
statusstringactive o inactive
paymentProviderstring | nullProcesador que almacenó la tarjeta (nmi o emetec); null si aún no está vaulteado
cardLast4string | nullÚltimos 4 dígitos de la tarjeta (solo para mostrar)
cardBrandstring | nullMarca de la tarjeta (solo para mostrar)
createdAtstringFecha de creación (ISO 8601)
updatedAtstringFecha de última actualización (ISO 8601)

El objeto también incluye metadata y deletedAt, que puedes ignorar.

El BIN y el vencimiento llegan por webhook

El objeto cliente no incluye la referencia de la bóveda (customerVaultId), el BIN (cardBin) ni el vencimiento (cardExp) de la tarjeta. El BIN y el vencimiento se entregan una sola vez, en el webhook (customer.card.bin y customer.card.exp): guárdalos en tu sistema si los necesitas. Si adjuntas la tarjeta tú mismo con , esos valores son los que envías en la solicitud.

Todos los datos de tarjeta del cliente son solo para mostrar. Los cobros siempre usan la tarjeta guardada en la bóveda del procesador, nunca estos valores.

Listar clientes ​

http
GET /v1/customers

Parámetros de consulta: paginación estándar (lim de 1 a 100, default 10; off) más un filtro opcional status (active, inactive). Los resultados se ordenan del más reciente al más antiguo.

Con fields (lista separada por comas) recibes solo esos campos del ; un campo que no pertenece al objeto devuelve 400 con ERR_INVALID_FIELDS. Este endpoint no admite expand: cualquier valor devuelve 400 con ERR_INVALID_RELATIONS.

bash
curl "https://api-pay.zelta.dev/v1/customers?lim=10" \
  -H "X-API-Key: tu-api-key-de-proyecto"

Crear un cliente ​

http
POST /v1/customers

Cuerpo de la solicitud:

CampoTipoRequeridoDescripción
namestringSíNombre del cliente (1-120 caracteres)
emailstringSíCorreo del cliente (formato de email válido)
phonestringNoTeléfono del cliente (máx. 40 caracteres)
bash
curl -X POST https://api-pay.zelta.dev/v1/customers \
  -H "X-API-Key: tu-api-key-de-proyecto" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "[email protected]",
    "phone": "+50760000000"
  }'

Responde 201 con el mensaje "Customer created" y el cliente en data.customer. Un cliente creado así aún no tiene tarjeta almacenada. Para poder cobrarle debes adjuntarle una tarjeta vaulteada (ver abajo) o capturarla con un , que crea un cliente nuevo. Crear un cliente por API no envía el webhook customer.created, y la API no evita clientes duplicados con el mismo email.

Obtener un cliente ​

http
GET /v1/customers/:id
bash
curl "https://api-pay.zelta.dev/v1/customers/7315555666677778888" \
  -H "X-API-Key: tu-api-key-de-proyecto"

Si el cliente no existe en el proyecto, responde 404 con ERR_CUSTOMER_NOT_FOUND.

Adjuntar una tarjeta vaulteada ​

Asocia al cliente una tarjeta ya tokenizada por el procesador indicado, pasando el id de la bóveda (customerVaultId) que ese procesador devolvió al tokenizarla. Esto convierte al cliente en vaulteado y habilita cobros y suscripciones.

http
POST /v1/customers/:id/vault

Cuerpo de la solicitud:

CampoTipoRequeridoDescripción
customerVaultIdstringSíId de la bóveda que devolvió el procesador al tokenizar la tarjeta
paymentProviderstringNoProcesador que almacenó la tarjeta: nmi o emetec. Por defecto nmi, incluso si el cliente ya tenía una tarjeta de Emetec
cardLast4stringNoÚltimos 4 caracteres de la tarjeta, exactamente 4 (solo para mostrar)
cardBrandstringNoMarca de la tarjeta (máx. 40 caracteres, solo para mostrar)
cardBinstringNoBIN de la tarjeta (6-8 dígitos, solo para mostrar)
cardExpstringNoVencimiento en formato MMYY (solo para mostrar)

Los campos card* son metadata de facturación solo para mostrar: los cobros siempre usan la referencia de la bóveda, nunca estos valores. Responde 200 con el mensaje "Vault attached" y el actualizado en data.customer. Zelta Pay guarda customerVaultId, cardBin y cardExp, pero la respuesta no los repite: guárdalos en tu sistema al enviarlos si los necesitas.

Reemplazar la tarjeta

Si el cliente ya tenía una tarjeta, esta llamada reemplaza customerVaultId y paymentProvider. Los campos card* que no envíes conservan su valor anterior, así que envíalos todos al reemplazar la tarjeta. Zelta Pay no verifica el customerVaultId con el procesador en este paso ni envía un webhook.

bash
curl -X POST https://api-pay.zelta.dev/v1/customers/7315555666677778888/vault \
  -H "X-API-Key: tu-api-key-de-proyecto" \
  -H "Content-Type: application/json" \
  -d '{
    "paymentProvider": "nmi",
    "customerVaultId": "1234567890",
    "cardLast4": "1111",
    "cardBrand": "visa",
    "cardBin": "411111",
    "cardExp": "1028"
  }'

Las colecciones son solo tarjeta

El vaulteo solo aplica a tarjetas (NMI o Emetec). Yappy y PayPal no pueden almacenar una tarjeta para cobros posteriores, por lo que no pueden usarse para crear clientes vaulteados.

Errores ​

CódigoHTTPCuándo
ERR_CUSTOMER_NOT_FOUND404El cliente no existe en el proyecto
ERR_API_KEY_NOT_PROJECT_SCOPED403Usaste una API key de la cuenta en lugar de la del proyecto
ERR_INVALID_FIELDS400fields en GET /v1/customers incluye un campo que no pertenece al objeto cliente
ERR_INVALID_RELATIONS400Enviaste expand en GET /v1/customers

Los cuerpos o parámetros inválidos devuelven 400 con el formato de .

Siguientes pasos ​

  • — captura la tarjeta y crea el cliente en un solo paso
  • — cobra a un cliente vaulteado
  • — suscribe a un cliente vaulteado a un plan
  • — el evento customer.created

Documentación oficial de Zelta