Uso multi-compañía

Una API key puede tener acceso a varias compañías. Cómo elegir sobre cuál opera cada llamada y cómo leer las respuestas.

Guía

Una API key no siempre corresponde a una sola compañía. En los grupos empresariales con varias razones sociales, una misma key puede tener acceso a varias compañías, cada una identificada por su uniqueCode. Esta guía explica qué hace cada endpoint en ese caso y cómo indicar sobre qué compañía quieres operar.

Reglas en breve

  1. Consulta GET /api/public/v1/companies para conocer las compañías a las que tiene acceso tu key. El valor que va en todo parámetro o campo companyCode es el uniqueCode de la compañía (en el objeto de la compañía, companyCode tiene ese mismo valor). Para ubicar una compañía por su identificación fiscal, filtra con taxIdentificationValue.
  2. Envía siempre companyCode en los endpoints que lo aceptan, también en las lecturas. Así el resultado no depende de cómo esté configurada la key.
  3. Sin companyCode, las lecturas devuelven datos de todas tus compañías juntas. Usa el companyCode de cada elemento para distinguirlos.
  4. En las altas, la API no elige una compañía por ti: la mayoría responde 400 si no la indicas. Algunas tienen reglas propias, detalladas más abajo.
  5. Un filtro companyCode sobre una compañía a la que la key no tiene acceso devuelve una página vacía, no un error. En la mayoría de las altas devuelve 403.
  6. Las consultas por {code} encuentran recursos de cualquiera de tus compañías. Si el recurso es de otra, la respuesta es 404, igual que si no existiera.

Conocer tus compañías

GET /companies devuelve todas las compañías a las que tiene acceso tu key. Guarda el uniqueCode de cada una: es el valor que vas a usar como companyCode en el resto de la API.

curl -X GET 'https://{HOST}/api/public/v1/companies' \
  -H 'X-API-KEY: tu_api_key_aqui'

Si en tu sistema ya identificas a cada compañía por su identificación fiscal (RFC, CUIT, RUT), búscala directamente por ese valor con taxIdentificationValue. Es la forma más simple de mapear tus compañías a sus uniqueCode:

curl -X GET 'https://{HOST}/api/public/v1/companies?taxIdentificationValue=XAXX010101000' \
  -H 'X-API-KEY: tu_api_key_aqui'

La búsqueda es por coincidencia exacta y solo devuelve compañías a las que tu key tiene acceso. Si varias compañías comparten la identificación fiscal y se diferencian por sucursal, agrega branchCode para quedarte con una. La identificación fiscal de cada compañía viene en legalInformation.taxIdentificationValue y su sucursal en legalInformation.branchCode.

Para traer solo algunas compañías que ya conoces, pasa sus uniqueCode en include (se puede repetir).

Cómo queda asociada una key a sus compañías

Las compañías de una API key se fijan cuando se crea, a partir de las compañías a las que tiene acceso la persona que la genera. Hay dos variantes:

Tipo de keyCómo se comporta
Con compañía principalLas lecturas y las altas operan, por defecto, sobre esa compañía.
Multi-compañía (sin compañía principal)Las lecturas consolidan todas sus compañías; las altas necesitan que indiques la compañía.

Ningún endpoint indica de qué tipo es tu key: si no lo sabes, consulta con tu contacto de onboarding. Esta guía describe el comportamiento de una key multi-compañía. Si envías siempre companyCode, como recomienda la regla 2, tu integración funciona igual con los dos tipos.

Las compañías de la key no se actualizan solas

Si la persona que creó la key gana o pierde acceso a una compañía, la key no lo refleja: conserva las compañías que tenía al crearse, y renovarla no lo cambia. Para operar sobre una compañía nueva, genera una key nueva. Los cambios sobre una key, como deshabilitarla, pueden tardar unos minutos en aplicarse.

No existe un header ni un parámetro global para elegir la compañía de una llamada. La única forma es el companyCode de los endpoints que lo aceptan, en el query o en el body según el caso.

Lecturas: la vista consolidada

Los listados no se limitan a una compañía: devuelven los elementos de todas las compañías de la key en una sola colección. La paginación y el orden son globales, así que una misma página puede mezclar compañías.

# Todas las transacciones de todas tus compañías
curl -X GET 'https://{HOST}/api/public/v1/purchases?page=0&size=50' \
  -H 'X-API-KEY: tu_api_key_aqui'

# Solo las de una compañía
curl -X GET 'https://{HOST}/api/public/v1/purchases?companyCode=CODIGO_COMPANIA' \
  -H 'X-API-KEY: tu_api_key_aqui'

# Las de dos compañías: repite el parámetro
curl -X GET 'https://{HOST}/api/public/v1/purchases?companyCode=CODIGO_A&companyCode=CODIGO_B' \
  -H 'X-API-KEY: tu_api_key_aqui'

Para ordenar y recorrer las páginas, sigue la guía de Paginación: el orden se envía con la forma indexada sort[0].property=…&sort[0].direction=….

EndpointSin companyCodePara filtrarCada elemento trae companyCode
GET /purchasesTodas tus compañíascompanyCode (admite varios)Sí
GET /statementsTodas tus compañíascompanyCodeSí
GET /budgetsTodas tus compañíascompanyCodeSí
GET /projectsTodas tus compañíascompanyCodeSí
GET /cost-centersTodas tus compañíascompanyCodeSí
GET /peopleTodas tus compañíascompanyCode (admite varios)Sí
GET /cost-center-account-typesTodas tus compañíasNo admite filtroNo
GET /purchase-approval-workflowsTodas tus compañíasNo admite filtroSí
GET /purchase-approval-workflows/eventsTodas tus compañíasNo admite filtroSí
GET /purchases/filesTodas tus compañíasPor purchaseCodesNo: usa purchaseCode
GET /billing-documentsLas transacciones que pidas, si son de tus compañíaspurchaseCodes, obligatorio (hasta 100)No: usa purchaseUniqueCode
GET /companiesTodas tus compañías—Es la compañía misma

En las respuestas, el companyCode de cada elemento es el uniqueCode de su compañía. Cuando los elementos de transacciones no traen companyCode, como en archivos y documentos de facturación, cruza el purchaseCode con GET /purchases para saber a qué compañía pertenece cada uno.

Endpoints que necesitan una compañía

Algunos catálogos son propios de cada compañía y no se pueden consolidar:

EndpointComportamiento
GET /account-typescompanyCode es obligatorio. Sin él responde 400.
GET /account-types/selectablecompanyCode es obligatorio. Sin él responde 400.
GET /company-custom-fieldsEnvía companyCode. Sin él, una key multi-compañía recibe una página vacía. Con una key de compañía principal se devuelven los campos de esa compañía.
GET /merchant-categoriesNo admite companyCode. Una key multi-compañía recibe el catálogo general de categorías, sin las categorías propias de cada compañía.

GET /people y la compañía principal de cada persona

Una persona puede pertenecer a varias compañías, pero tiene una compañía principal. El filtro companyCode de GET /people, los filtros por identificación fiscal de la compañía y la búsqueda por {code} usan esa compañía principal. Una persona cuya compañía principal no está entre las de tu key no aparece, aunque también pertenezca a una compañía que sí lo está.

Consultas por {code}

GET, PATCH y DELETE sobre un recurso concreto encuentran el recurso en cualquiera de las compañías de tu key, sin que indiques cuál. Si el recurso es de una compañía a la que la key no tiene acceso, la API responde como si no existiera. Esto evita revelar recursos de otras compañías.

CasoRespuesta
La mayoría de los recursos (/purchases/{code}, /budgets/{code}, /projects/{code}, …)404
GET /purchases/{code}/files200 con listas vacías
DELETE /cost-center-account-types/{code}400
PATCH /projects/bulk, PATCH /cost-centers/bulkCada elemento ajeno se informa en failed con NOT_FOUND; un mismo lote puede incluir elementos de varias de tus compañías

Altas: indica siempre la compañía

Al crear recursos, la API no elige una compañía por ti. Con una key multi-compañía, indica en cuál se crea cada recurso:

EndpointDónde va la compañíaSin compañíaCompañía sin acceso
POST /projects (JSON)companyCode en el body400403
POST /cost-centers (JSON)companyCode en el body400403
POST /budgets (JSON)companyCode en el body400Error (valida antes contra GET /companies)
POST /cost-center-account-typescompanyCode en el body400403
POST /projects (CSV)companyCode en el query400403
POST /cost-centers (CSV)companyCode en el query400403
curl -X POST 'https://{HOST}/api/public/v1/projects' \
  -H 'X-API-KEY: tu_api_key_aqui' \
  -H 'Content-Type: application/json' \
  -d '{ "companyCode": "CODIGO_COMPANIA", "name": "Expansión regional" }'

En POST /cost-center-account-types, la cuenta contable y el centro de costos que vinculas tienen que pertenecer a la misma compañía que indicas.

Altas con reglas propias

Estos endpoints no deciden la compañía con companyCode:

  • POST /people (JSON): con una key multi-compañía, la persona queda asociada a todas las compañías de la key. companyCodes en el body no restringe ese conjunto. No hay forma de elegir su compañía principal.
  • POST /people (CSV): la compañía de cada fila sale de la columna NRO_IDENTIFICADOR_FISCAL_EMPRESA (o RFC_EMPRESA), que tiene que coincidir con una de tus compañías. Una fila sin coincidencia se rechaza. Las personas que ya existen conservan sus compañías.
  • POST /account-types (CSV): la compañía de cada fila sale de NRO_IDENTIFICADOR_FISCAL_EMPRESA y, si hace falta distinguir sucursales, de CODIGO_IDENTIFICADOR. El parámetro companyCode no decide en qué compañía se crean las cuentas. Con una key multi-compañía, incluye esas columnas en todas las filas: si una fila no identifica su compañía, se rechaza el archivo entero.
  • POST /account-types (JSON) y POST /budgets (CSV): no permiten elegir compañía, así que hoy no están disponibles para keys multi-compañía. Usa la carga por CSV de cuentas contables y el alta JSON de presupuestos.

Miembros de presupuestos

POST /budgets/{code}/members no valida que las personas que agregas pertenezcan a la compañía del presupuesto, y los personCode que la key no puede ver se omiten sin error. Con una key multi-compañía, verifica la compañía de cada persona con GET /people/{code} antes de agregarla.

Recorrido recomendado

Este es el flujo que conviene seguir para leer datos de varias compañías sin mezclarlos ni perder ninguno:

Mapea tus compañías

Llama a GET /companies (o búscalas por taxIdentificationValue) y guarda el uniqueCode de cada una junto con el identificador que usas en tu sistema.

Consulta compañía por compañía

Para cada uniqueCode, llama al endpoint con companyCode=<uniqueCode> y recorre todas sus páginas. Si el endpoint acepta varios companyCode, puedes pedir varias compañías en una sola consulta.

Asigna cada elemento por su companyCode

Guarda cada elemento según el companyCode que trae, no según la consulta que lo devolvió. Usa su uniqueCode como clave para no duplicarlo.

Crea siempre con la compañía explícita

En las altas, envía el companyCode de la compañía destino, aunque la key tenga una sola compañía.

Errores y resultados vacíos

Lo que recibesQué significa
400 con el campo companyCodeLa operación necesita una compañía y no la indicaste, o no se pudo determinar.
403Indicaste una compañía a la que tu key no tiene acceso.
200 con una página vacía al filtrar por companyCodeNo hay datos o la key no tiene acceso a esa compañía. La API no distingue los dos casos.
404 en una consulta por {code}El recurso no existe o es de una compañía a la que la key no tiene acceso.

Un 400 por falta de compañía señala el campo companyCode en key cuando el parámetro es obligatorio:

{
  "errors": [
    { "category": "must not be blank", "key": "companyCode", "parameters": [] }
  ],
  "status": 400
}

Cuando la compañía es necesaria pero no se puede determinar, el campo viaja en parameters:

{
  "errors": [
    { "category": "AppErrorType", "key": "INVALID_REQUEST", "parameters": ["companyCode"] }
  ]
}

En los dos casos, la solución es la misma: envía companyCode.

Como una página vacía no indica si tienes acceso, valida los companyCode contra GET /companies antes de usarlos en filtros. Así un código mal escrito no pasa por "esa compañía no tiene datos".

En esta página