Un cliente es una cuenta comercial: una empresa a la que vende, con un código de cuenta, un descuento de cuenta opcional y las personas (compradores) que pueden iniciar sesión para realizar pedidos por su cuenta.
El objeto clienteEnlace a esta sección#
{
"id": "7d2e4f0a-1b3c-4d5e-8f90-a1b2c3d4e5f6",
"accountCode": "OAK01",
"name": "Oakfield Joinery",
"legalName": "Oakfield Joinery Ltd",
"email": "accounts@oakfieldjoinery.co.uk",
"discountBp": 500,
"active": true,
"newsOptOut": false,
"catalogueScope": "all",
"createdAt": "2026-07-02T10:12:44.000Z"
}
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador del cliente. |
accountCode | string | Su código de cuenta. Único en el espacio de trabajo, ignorando mayúsculas. Puede cambiarse en la aplicación, por lo que conserve el id para cualquier cosa de largo plazo. |
name | string | Nombre comercial. |
legalName | string o nulo | Nombre registrado, cuando es diferente. |
email | string o nulo | Correo electrónico principal, en minúsculas. |
discountBp | entero o nulo | El porcentaje propio del cliente sobre el listado completo, en puntos básicos. null para ninguno. |
adjustment | string | discount (eliminado de la lista) o markup (añadido). Los clientes existentes son discount. |
active | booleano | Los clientes inactivos no pueden iniciar sesión ni realizar pedidos. |
newsOptOut | booleano | El cliente desactivó las ofertas y correos electrónicos de noticias. Los correos electrónicos de cambios de precio aún se envían. |
catalogueScope | string | all (ve todo el catálogo) o approved (ve y ordena solo su lista aprobada). Se establece en la página del cliente; de solo lectura en la API. |
createdAt | string | Cuando se agregó al cliente. |
En cualquier lugar donde la API tome un cliente, puede usar el id o el accountCode.
Listar clientesEnlace a esta sección#
GET/api/v1/customers
Todos los clientes, ordenados por nombre.
| Nombre | Tipo | Requerido | Descripción |
|---|---|---|---|
limit | entero | no | 1 a 100. Valor predeterminado 100. |
offset | entero | no | Filas a omitir. Valor predeterminado 0. |
curl "https://tradecatalog.app/api/v1/customers?limit=100" \
-H "Authorization: Bearer $TRADECATALOG_API_KEY"
const res = await fetch('https://tradecatalog.app/api/v1/customers?limit=100', {
headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` },
})
const { data: customers, nextOffset } = await res.json()
{
"data": [
{
"id": "7d2e4f0a-1b3c-4d5e-8f90-a1b2c3d4e5f6",
"accountCode": "OAK01",
"name": "Oakfield Joinery",
"legalName": "Oakfield Joinery Ltd",
"email": "accounts@oakfieldjoinery.co.uk",
"discountBp": 500,
"active": true,
"newsOptOut": false,
"catalogueScope": "all",
"createdAt": "2026-07-02T10:12:44.000Z"
}
],
"nextOffset": null
}
Obtener un clienteEnlace a esta sección#
GET/api/v1/customers/{id}
El cliente más todo lo que afecta a sus precios, y quién puede iniciar sesión por ellos.
| Nombre | En | Tipo | Requerido | Descripción |
|---|---|---|---|---|
id | ruta | string | sí | Identificador del cliente o código de cuenta. |
curl https://tradecatalog.app/api/v1/customers/OAK01 \
-H "Authorization: Bearer $TRADECATALOG_API_KEY"
const res = await fetch('https://tradecatalog.app/api/v1/customers/OAK01', {
headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` },
})
const { data: customer } = await res.json()
{
"data": {
"id": "7d2e4f0a-1b3c-4d5e-8f90-a1b2c3d4e5f6",
"accountCode": "OAK01",
"name": "Oakfield Joinery",
"legalName": "Oakfield Joinery Ltd",
"email": "accounts@oakfieldjoinery.co.uk",
"discountBp": 500,
"priceListId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"priceList": "Standard",
"active": true,
"newsOptOut": false,
"createdAt": "2026-07-02T10:12:44.000Z",
"discountRules": [
{
"id": "d0e1f2a3-4b5c-4d6e-9f7a-8b9c0d1e2f3a",
"scope": "product",
"discountBp": 2000,
"productId": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
"sku": "HX-8510",
"target": "Hex bolt M10 x 50 zinc",
"list": 2280,
"unit": 1824
},
{
"id": "e1f2a3b4-5c6d-4e7f-8a9b-0c1d2e3f4a5b",
"scope": "brand",
"discountBp": 1500,
"productId": null,
"sku": null,
"target": "Northgate",
"list": null,
"unit": null
},
{
"id": "f2a3b4c5-6d7e-4f80-9a1b-2c3d4e5f6a7b",
"scope": "category",
"discountBp": 1250,
"productId": null,
"sku": null,
"target": "Hinges",
"list": null,
"unit": null
}
],
"agreedPrices": [
{
"id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"productId": "6c7d8e9f-0a1b-4c2d-9e3f-4a5b6c7d8e9f",
"price": 1450,
"note": "Contract price to March 2027",
"noteVisible": true,
"internalNote": "Agreed with their buyer",
"sku": "HX-8512",
"name": "Hex bolt M12 x 50 zinc",
"list": 1980,
"unit": 1450
}
],
"buyers": [{ "name": "Sam Patel", "email": "sam@oakfieldjoinery.co.uk" }],
"pendingInvitations": [{ "email": "orders@oakfieldjoinery.co.uk" }]
},
"currency": "GBP"
}
| Campo | Descripción |
|---|---|
priceList | Nombre de la lista de precios de la que compra este cliente. priceListId es el id de esa lista. Un producto sin precio en la lista tiene precio bajo petición. |
discountRules | Porcentajes de producto, categoría y marca. scope es product, category o brand; adjustment es discount o markup; target es su nombre. Las reglas de producto también proporcionan sku, list y unit (lo que pagan). |
agreedPrices | Precios acordados (fijos) válidos ahora, por SKU, en unidades menores, con el precio list actual y el precio unit que pagan. note es el comentario; noteVisible indica si ese cliente lo ve. internalNote es solo para personal y nunca se muestra al cliente. |
buyers | Personas que pueden iniciar sesión y realizar pedidos por este cliente. |
pendingInvitations | Invitaciones enviadas pero no aceptadas, y no caducadas. |
Vea cómo se calculan los precios para ver cómo se combinan.
Crear o actualizar clientesEnlace a esta sección#
PUT/api/v1/customersescribir clave
Envíe hasta 100 clientes por llamada. Cada fila se compara con un cliente existente de la siguiente manera:
- Si se establece
accountCode, por código de cuenta. Sin coincidencia significa un nuevo cliente con ese código. - De lo contrario, si se establece
email, por correo electrónico. Sin coincidencia significa un nuevo cliente. - De lo contrario por nombre, ignorando mayúsculas.
Los nuevos clientes sin código de cuenta reciben uno generado a partir de su nombre.
CuerpoEnlace a esta sección#
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
customers | matriz | sí | 1 a 100 clientes. Los códigos de cuenta deben ser únicos dentro de la llamada. |
customers[].accountCode | cadena o nulo | sí | Máximo 50 caracteres. null para coincidir por correo electrónico o nombre. |
customers[].name | cadena | sí | Nombre comercial, máximo 160 caracteres. |
customers[].email | cadena o nulo | sí | Correo electrónico principal de contacto. null lo borra. |
customers[].discountBp | entero o nulo | sí | Porcentaje de lista completa, 0 a 10.000, para un descuento o recargo. null lo borra. |
customers[].adjustment | discount o markup | no | La forma en que discountBp mueve el precio. Omita para dejar la dirección actual. Los nuevos clientes tienen como predeterminado discount. |
customers[].priceList | cadena o nulo | no | Nombre de una lista de precios existente. Omita para dejar la lista sin cambios. null coloca al cliente en Standard. Un nombre desconocido se rechaza. |
customers[].region | cadena o nulo | no | Nombre de una región existente. Omita para dejar la región sin cambios. null la borra. Un nombre desconocido se rechaza. |
customers[].rep | cadena o nulo | no | Correo electrónico o nombre de usuario de un miembro del personal asignado a este cliente. Omita para dejar al representante sin cambios. null lo borra. Un correo electrónico o nombre de usuario desconocido se rechaza. |
accountCode, name, email y discountBp son obligatorios y se escriben como se envían: null borra email y discountBp. De esta forma, un campo faltante en su código no puede dejar en silencio un porcentaje antiguo en su lugar. adjustment y priceList son opcionales: deje adjustment fuera para mantener un recargo o un descuento como está.
La hoja de cálculo del cliente tiene la misma opción. Junto con el descuento % puede tener una columna de ajuste (discount o markup), una columna de lista de precios y una columna de representante de ventas. La celda del representante es el correo electrónico de esa persona, o su nombre de usuario cuando se inicia sesión sin correo electrónico. Una celda en blanco deja ese campo como está. Un nombre de lista desconocido o un representante es un error en esa fila.
Actualizar un cliente no envía correos electrónicos ni invita a compradores. Invite a compradores desde la página del cliente en la aplicación. El nombre registrado, el estado activo, las reglas de descuento y los precios acordados también se cambian en la aplicación.
curl -X PUT https://tradecatalog.app/api/v1/customers \
-H "Authorization: Bearer $TRADECATALOG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customers": [
{
"accountCode": "OAK01",
"name": "Oakfield Joinery",
"email": "accounts@oakfieldjoinery.co.uk",
"discountBp": 500
},
{
"accountCode": "BRK07",
"name": "Brookside Builders",
"email": null,
"discountBp": null
}
]
}'
const res = await fetch('https://tradecatalog.app/api/v1/customers', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ customers }),
})
const { data } = await res.json()
console.log(`${data.created} new, ${data.updated} updated`)
{
"data": { "created": 1, "updated": 1 }
}
El cambio aparece en el registro de actividad como el nombre de la clave.