Clientes y grupos
Crea y actualiza clientes, direcciones y grupos desde tu CRM o ERP.
Sincroniza a Andrea Ramos desde tu CRM: búscala por email, créala si no existe, mantén sus datos al día y agrégala al grupo «Mayoristas».
Requisitos
- Un token de Admin en
ECOMIQ_TOKEN. Ver Inicio rápido. - Los permisos
customer:read,customer:createycustomer:updatepara clientes y direcciones;customer_group:read,customer_group:createycustomer_group:updatepara grupos. - Una URL HTTPS pública, para recibir
customer.created.
Los ejemplos de JavaScript y Python usan esta función, que envía el token y
falla si la respuesta no es 2xx:
export async function ecomiq(method, path, body) {
const init = {
method,
headers: {
Authorization: `Bearer ${process.env.ECOMIQ_TOKEN}`,
"Content-Type": "application/json",
},
};
if (body !== undefined) init.body = JSON.stringify(body);
const response = await fetch(`https://api.ecomiq.pe/api${path}`, init);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
if (response.status === 204) return null;
return response.json();
}Busca por email
El email es único en la tienda, sin distinguir mayúsculas. search busca en
email, nombre y apellido, con coincidencias parciales.
curl -G https://api.ecomiq.pe/api/v1/customers \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
--data-urlencode "search=andrea.ramos@example.com"{
"data": [],
"hasNextPage": false,
"nextCursor": null,
"totalCount": 0
}Compara el email completo en los resultados. Si encuentras al cliente, guarda su
id y actualízalo; si no, créalo.
Crea un cliente
Envía email, firstName, lastName, customerType y countryIsoCode. Usa
metadata para guardar el ID de tu CRM.
{
"email": "andrea.ramos@example.com",
"firstName": "Andrea",
"lastName": "Ramos",
"customerType": "individual",
"countryIsoCode": "PE",
"phone": "+51987654321",
"identificationType": "DNI",
"identificationNumber": "72654321",
"consent": true,
"metadata": { "crmId": "CRM-1042" }
}curl -X POST https://api.ecomiq.pe/api/v1/customers \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
--data @cliente.json{
"id": "7204558912004325301",
"status": "pendingVerification",
"isVerified": false
}Guarda el id como string en tu CRM. Un cliente individual empieza en
pendingVerification. consent: true indica que aceptó recibir correos de
marketing. El mismo documento de identidad no puede repetirse en la tienda.
Crea una empresa
Envía customerType: "business" y la razón social en entityName. firstName
y lastName son de la persona de contacto.
curl -X POST https://api.ecomiq.pe/api/v1/customers \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "compras@example.com",
"firstName": "Lucía",
"lastName": "Torres",
"customerType": "business",
"countryIsoCode": "PE",
"phone": "+5115550142",
"identificationType": "RUC",
"identificationNumber": "20123456789",
"entityName": "Comercial Lima SAC"
}'La empresa empieza en pendingApproval. Apruébala para pasarla a active; la
respuesta es 204:
curl -X POST https://api.ecomiq.pe/api/v1/customers/7204558912004325302/approve \
-H "Authorization: Bearer $ECOMIQ_TOKEN"Actualiza un cliente
PATCH cambia solo los campos que envías y responde 204. null borra un
campo opcional. metadata reemplaza el objeto guardado.
curl -X PATCH https://api.ecomiq.pe/api/v1/customers/7204558912004325301 \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "andrea.ramos.p@example.com",
"phone": "+51912345678"
}'El consentimiento se reinicia
Cambiar email pone consent en false, y cambiar phone pone
smsConsent en false.
Si el cliente tiene userId, su cuenta está vinculada y el email no se cambia
por esta vía.
Reemplaza las etiquetas
tags reemplaza todas las etiquetas: para agregar una, envía la lista actual
más la nueva. [] o null las borra. Acepta hasta 100 etiquetas de hasta 100
caracteres, y quita espacios sobrantes y duplicados.
curl -X PATCH https://api.ecomiq.pe/api/v1/customers/7204558912004325301 \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "tags": ["mayorista", "lima"] }'Guarda una dirección
La primera dirección queda como predeterminada; con isDefault: true, la nueva
pasa a serlo. La respuesta 201 trae su id.
curl -X POST https://api.ecomiq.pe/api/v1/customers/7204558912004325301/addresses \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"addressKey": "casa",
"countryIsoCode": "PE",
"addressLine": "Av. Larco 1234",
"department": "Lima",
"province": "Lima",
"district": "Miraflores",
"phone": "+51987654321",
"isDefault": true
}'Para editarla, envía la dirección completa a
PUT /: los campos que omitas
quedan vacíos.
Crea un grupo manual
Un grupo manual tiene los clientes que eliges. El nombre es único en la
tienda.
curl -X POST https://api.ecomiq.pe/api/v1/customers/groups \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Mayoristas", "type": "manual" }'Agrega miembros con sus IDs:
curl -X POST https://api.ecomiq.pe/api/v1/customers/groups/7204558912004325310/members \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "customerIds": ["7204558912004325301", "7204558912004325302"] }'{
"customerGroupId": "7204558912004325310",
"addedCount": 2,
"existingCount": 0,
"requestedCount": 2
}Los clientes que ya estaban suman en existingCount, así que puedes repetir la
llamada. Para quitar miembros, envía sus IDs a
POST /; el cliente no se borra.
Crea un grupo dinámico
Un grupo dynamic incluye a los clientes que cumplen sus conditions: con
match: "all", todas; con "any", alguna. Necesita al menos una condición y no
acepta miembros a mano.
Campo (field) | Operadores | Valor |
|---|---|---|
amountSpent, orderCount | atLeast, atMost, between | numbers |
lastOrderDate, firstOrderDate, createdDate, abandonedCheckoutDate | withinLastDays, moreThanDaysAgo, betweenDates | numbers (días) o dates |
paymentMethod | in (usó), notIn (no usó), lastOrderIn | values: códigos de método |
department, province, district | in, notIn | values: IDs de / |
country | in, notIn | values: códigos ISO |
productPurchased, categoryPurchased, salesChannel, group, tag, status, customerType, emailSubscription, smsSubscription | in, notIn | values |
amountSpent está en la moneda de la tienda y descuenta reembolsos. Varios
valores en una condición cuentan como «cualquiera de ellos».
curl -X POST https://api.ecomiq.pe/api/v1/customers/groups \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Clientes frecuentes",
"type": "dynamic",
"conditions": {
"match": "all",
"conditions": [
{ "field": "orderCount", "operator": "atLeast", "numbers": [3], "dates": null, "values": null },
{ "field": "paymentMethod", "operator": "in", "numbers": null, "dates": null, "values": ["yape", "plin"] }
]
}
}'Para probar las reglas sin guardar el grupo, envía match y conditions en la
raíz del body a POST /:
curl -X POST https://api.ecomiq.pe/api/v1/customers/groups/preview \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"match": "all",
"conditions": [
{ "field": "orderCount", "operator": "atLeast", "numbers": [3], "dates": null, "values": null }
],
"includeSample": true,
"limit": 10
}'La respuesta trae count (clientes que cumplen), total (clientes de la
tienda) y sample. limit va de 1 a 20 (10 por defecto); con
includeSample: false, sample llega vacío.
Lista los miembros
groupId en GET / y GET / evalúa las reglas
del grupo en vivo; en un grupo manual, trae sus miembros. Los demás filtros se
suman con AND:
GET /v1/customers?groupId=7204558912004325311&minOrderCount=3
GET /v1/customers/count?groupId=7204558912004325311&minOrderCount=3Descuentos y campañas usan las membresías guardadas, igual que la condición
group y los filtros memberOfGroupIds y excludeMemberOfGroupIds. Se
calculan al crear el grupo y se recalculan con cada pedido. customerCount
muestra el último cálculo; lastMaterializedOn es null hasta el primero.
Para exportar o editar en hoja la misma selección, envía esos filtros en el body
de POST / o en filters de
POST /. En JSON, status, excludeStatus,
customerType y excludeCustomerType van en plural: statuses,
excludeStatuses, customerTypes y excludeCustomerTypes.
PUT reemplaza el grupo
PUT / espera todos los campos. Si omites type, el
grupo pasa a manual. Con isActive: false, deja de recalcularse.
Recibe customer.created
customer.created llega por cada cliente nuevo, también por los que crea tu
CRM. Registra tu URL:
curl -X POST https://api.ecomiq.pe/api/v1/webhooks/endpoints \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Clientes al CRM",
"url": "https://crm.example.com/webhooks/ecomiq",
"eventTypes": ["customer.created"],
"secret": "whsec_replace_with_a_random_secret"
}'Verifica la firma y responde 2xx como en
Pedidos entrantes. El cuerpo es un
CustomerWebhookModel
con el ID del cliente.
La entrega es al menos una vez. Si el ID ya está en tu CRM, ignora el evento; si no, lee el cliente y regístralo:
export async function handleCustomerCreated(customerId) {
if (await crmHasCustomer(customerId)) return;
const customer = await ecomiq("GET", `/v1/customers/${customerId}`);
await createCrmContact(customer);
}crmHasCustomer y createCrmContact son funciones de tu CRM.
Errores
code | Estado | Qué hacer |
|---|---|---|
Common.Validation | 400 | Revisa errors: falta un campo o tiene otro formato. |
CustomerGroup.DynamicMembership | 400 | El grupo es dinámico: cambia sus condiciones, no sus miembros. |
Common.Forbidden | 403 | Agrega a tu app el permiso que falta. |
Customer.NotFound | 404 | El cliente no existe en la tienda. |
CustomerGroup.CustomersNotFound | 404 | Ninguno de los customerIds es de la tienda. |
Customer.EmailAlreadyExists | 409 | Otro cliente usa ese email: búscalo y actualízalo. |
Customer.IdentificationAlreadyExists | 409 | Otro cliente tiene ese documento. |
Customer.LinkedAccountEmail | 409 | El cliente tiene cuenta: el email lo cambia él desde su cuenta. |
Customers.ApprovalRequiresPending | 409 | Solo se aprueba un cliente en pendingApproval. |
CustomerGroup.AlreadyExists | 409 | Ya hay un grupo con ese nombre. |
Siguientes pasos
Última actualización: