Compañía
Objeto compañía
ID tributario de la empresa, para Perú número de RUC
Nombre oficial de la empresa, para Perú Razón social
Nombre comercial o de marca de la empresa.
Número de teléfono de contacto de la empresa.
Correo electrónico de contacto de la empresa.
Código del país de la empresa
Dirección de la empresa
Metadatos y configuración adicional de la compañía. Se usa para valores operativos como impuesto por defecto o credenciales GRE cuando aplique.
URL del webhook para notificaciones
La API de Facturación permite obtener información correspondiente sobre las compañías que una cuenta maneja.
Alta completa de compañía
Este endpoint permite registrar una compañía emisora y configurar en la misma operación sus credenciales tributarias, certificado digital, logo opcional y webhook.
POST /api/company/create
Host: invoice.test.tandia.io
Authorization: Bearer token-de-api
Content-Type: multipart/form-data
Payload form-data
tax_id=20606335670
business_name=Empresa Demo S.A.C.
trade_name=Empresa Demo
country=PE
tax_user=USUARIO_SOL_SUNAT
tax_password=PASSWORD_SOL_SUNAT
phone=+51999999999
email=facturacion@empresa.com
address={"postal_zone":"150101","country":"PE","country_subentity":"LIMA","city":"LIMA","district":"LIMA","city_subdivision":"","address":"Av. Demo 123"}
metadata={"client_id":"12345678-1234-1234-1234-123456789012","client_secret":"s3cr3tGuiaSUNAT2026AbcXy"}
web_hook=https://cliente.com/webhooks/tandia
certificate=@certificado.p12
certificate_phrase=frase-del-certificado
logo=@logo.png
Campos del payload
| Campo | Tipo | Requerido | Restricciones | Descripción |
|---|---|---|---|---|
tax_id | string | Sí | RUC de 11 caracteres | RUC de la compañía emisora. |
business_name | string | Sí | máximo 100 caracteres | Razón social. |
trade_name | string | Sí | máximo 100 caracteres | Nombre comercial. |
country | string | Sí | mínimo 2, máximo 2; valores soportados: PE | País de la compañía. |
tax_user | string | Sí | máximo 32 caracteres | Usuario tributario/SUNAT. |
tax_password | string | Sí | máximo 32 caracteres | Contraseña tributaria/SUNAT. |
phone | string | Sí | máximo 15 caracteres | Teléfono de contacto. |
email | string | Sí | máximo 100, debe ser email válido | Correo de contacto. |
address | JSON string | Sí | debe ser JSON válido | Dirección fiscal de la compañía. |
metadata | JSON string | No | si se envía: JSON válido | Configuración adicional, por ejemplo credenciales GRE. |
metadata.client_id | string | Opcional | requerido si se envía metadata; mínimo 10, máximo 40 | Client ID de SUNAT para guías. |
metadata.client_secret | string | Opcional | requerido si se envía metadata; mínimo 10, máximo 30 | Client secret de SUNAT para guías. |
web_hook | string | No | máximo 255 caracteres | Webhook específico de la compañía. |
certificate | file | Sí | máximo 2048 KB; extensiones permitidas: pfx, p12 | Certificado digital de la compañía. |
certificate_phrase | string | Sí | máximo 255 caracteres | Frase o contraseña del certificado. |
logo | image file | No | máximo 2048 KB; extensiones permitidas: jpeg, jpg, png, svg | Logo de la compañía. |
Estructura de address
El campo address se envía como string JSON dentro del form-data.
{
"postal_zone": "150101",
"country": "PE",
"country_subentity": "LIMA",
"city": "LIMA",
"district": "LIMA",
"city_subdivision": "",
"address": "Av. Demo 123"
}
| Campo | Tipo | Requerido | Restricciones | Descripción |
|---|---|---|---|---|
postal_zone | string | Sí | exactamente 6 caracteres | Ubigeo o zona postal. |
country | string | Sí | exactamente 2 caracteres | Código ISO del país. |
country_subentity | string | Sí | máximo 15 caracteres | Departamento o región. |
city | string | Sí | máximo 25 caracteres | Provincia o ciudad. |
district | string | Sí | máximo 40 caracteres | Distrito. |
city_subdivision | string | No | máximo 50 caracteres | Urbanización o zona. |
address | string | Sí | máximo 100 caracteres | Dirección fiscal. |
Estructura de metadata
El campo metadata se envía como string JSON dentro del form-data. Es opcional, pero si se envía durante el alta completa, el backend valida que incluya client_id y client_secret.
{
"client_id": "12345678-1234-1234-1234-123456789012",
"client_secret": "s3cr3tGuiaSUNAT2026AbcXy"
}
| Campo | Tipo | Requerido | Restricciones | Descripción |
|---|---|---|---|---|
client_id | string | Opcional | maximo 40 caracteres | Client ID de SUNAT para guías de remisión electrónicas. |
client_secret | string | Opcional | maximo 30 caracteres | Client secret de SUNAT para guías de remisión electrónicas. |
default_tax | string | Opcional | se usa en configuración/actualización; ejemplo IGV | Impuesto por defecto usado por la operación cuando aplique. |
Para actualizaciones posteriores, metadata también puede incluir valores operativos como default_tax, siempre que el modelo de compañía lo acepte.
Recomendaciones para credenciales
Estas recomendaciones vienen de las validaciones usadas por el dashboard de Tandia. Sirven como guía de captura para integraciones, aunque el backend de alta completa valida rangos más amplios.
| Campo | Recomendación de captura |
|---|---|
metadata.client_id | Enviar exactamente 36 caracteres. |
metadata.client_secret | Enviar exactamente 24 caracteres. |
tax_user | Enviar exactamente 8 caracteres y en mayúsculas. |
tax_password | Enviar al menos 3 caracteres cuando se configura tax_user. |
Respuesta
{
"id": "com_b2ad4cfce3be408fb100062b06f8dc0b",
"business_name": "Empresa Demo S.A.C.",
"trade_name": "Empresa Demo",
"tax_id": "20606335670",
"country": "PE",
"phone": "+51999999999",
"email": "facturacion@empresa.com",
"address": {
"postal_zone": "150101",
"country": "PE",
"country_subentity": "LIMA",
"city": "LIMA",
"district": "LIMA",
"city_subdivision": "",
"address": "Av. Demo 123",
"reference": null,
"type_code": null
},
"metadata": {
"client_id": "12345678-1234-1234-1234-123456789012",
"client_secret": "s3cr3tGuiaSUNAT2026AbcXy"
},
"logo": "https://ruta-del-logo/logo.png",
"web_hook": "https://cliente.com/webhooks/tandia"
}
Validaciones y comportamiento
| Regla | Descripción |
|---|---|
| Cuenta asociada | La compañía se registra bajo la cuenta identificada por el Bearer enviado en Authorization. |
| Unicidad | No se puede registrar dos veces el mismo tax_id bajo la misma cuenta. |
| Certificado | El certificado se convierte internamente. Si la conversión falla, la API devuelve error de validación en certificate. |
| Archivos | certificate y logo se reciben por multipart/form-data. |
| Modelo de cliente | El cliente emisor se registra como company; no es obligatorio crear una cuenta de usuario independiente por cada compañía. |
Configuración de credenciales y logo
Con POST /api/company/create, el certificado digital y usuario secundario SUNAT son obligatorios: no se puede completar esa alta sin enviar certificate, certificate_phrase, tax_user y tax_password.
Las alternativas de esta sección aplican cuando la compañía ya existe porque fue registrada previamente con el alta básica documentada en Inicio rápido, por una operación interna de Tandia, o porque se necesita reemplazar/configurar nuevamente el certificado de una compañía existente.
Alternativa 1: Certificado junto con credenciales y logo
POST /api/company/init
Host: invoice.test.tandia.io
Authorization: Bearer token-de-api
Content-Type: multipart/form-data
Payload form-data
tax_id=20606335670
country_code=PE
tax_user=USUARIO_SOL_SUNAT
tax_password=PASSWORD_SOL_SUNAT
certificate=@certificado.p12
certificate_phrase=frase-del-certificado
logo=@logo.png
Alternativa 2: Certificado separado y logo
POST /api/company/setup
Host: invoice.test.tandia.io
Authorization: Bearer token-de-api
Content-Type: multipart/form-data
Payload form-data
tax_id=20606335670
country_code=PE
tax_user=USUARIO_SOL_SUNAT
tax_password=PASSWORD_SOL_SUNAT
cert_file=@certificado.crt
key_file=@llave.key
logo=@logo.png
Campos usados en ambas alternativas
| Campo | Tipo | Requerido | Restricciones | Descripción | Contexto |
|---|---|---|---|---|---|
tax_id | string | Sí | RUC de 11 caracteres | RUC de la compañía emisora. | Ambos |
country_code | string | Sí | mínimo 2, máximo 2; valores soportados: PE | País de la compañía. | Ambos |
tax_user | string | Sí | máximo 32 caracteres | Usuario tributario/SUNAT. | Ambos |
tax_password | string | Sí | máximo 32 caracteres | Contraseña tributaria/SUNAT. | Ambos |
certificate | file | Sí | máximo 2048 KB; extensiones permitidas: pfx, p12 | Certificado digital de la compañía. | /init |
certificate_phrase | string | Sí | máximo 255 caracteres | Frase o contraseña del certificado. | /init |
cert_file | file | Sí | máximo 2048 KB; extensiones admitidas: cer, crt, key | Certificado público de la compañía. | /setup |
key_file | file | Sí | máximo 2048 KB; extensión key | Llave privada del certificado. | /setup |
logo | image file | Sí | máximo 2048 KB; extensiones permitidas: jpeg, jpg, png, svg | Logo de la compañía. | Ambos |
Validaciones y comportamiento
| Regla | Descripción |
|---|---|
| Compañía existente | La compañía debe existir bajo la cuenta identificada por el Bearer. |
| Certificado inválido | Si la extensión o conversión del certificado falla, la API devuelve error de validación. |
| Tamaño de archivo | El backend valida archivos de hasta 2048 KB. |
| Formato recomendado | Para integraciones nuevas, usar .p12 o .pfx con certificate_phrase. |
| Fuente SUNAT | El trámite de certificado y usuario secundario ocurre fuera de Tandia, en SUNAT; la API solo recibe los archivos/credenciales ya emitidos. |
Búsqueda y validación previa de RUC
Antes de crear una compañía, consulta si el RUC ya existe para la cuenta autenticada. Esto evita duplicidades y errores de creación.
GET /api/company/search/country/{countryCode}/taxId/{taxId}?limit=1
Host: invoice.test.tandia.io
Authorization: Bearer token-de-api
Content-Type: application/json
Parámetros
| Parámetro | Ubicación | Tipo | Requerido | Restricciones | Descripción |
|---|---|---|---|---|---|
countryCode | path | string | Sí | 2 caracteres; ejemplo PE | País de la compañía. |
taxId | path | string | Sí | RUC de 11 dígitos para Perú | RUC que se desea validar. |
limit | query | number | Sí | mayor a 0, máximo 50 | Cantidad máxima de resultados. Para validar existencia usa 1. |
next_token | query | string | No | máximo 1500 caracteres | Token de paginación si existen más resultados. |
Respuesta cuando existe
{
"data": [
{
"id": "com_61a80925017e4",
"tax_id": "20606335670",
"country": "PE",
"business_name": "Empresa Demo S.A.C.",
"trade_name": "Empresa Demo",
"web_hook": "https://cliente.com/webhooks/tandia"
}
],
"meta": {
"next_token": null
}
}
Alcance de permisos
| Regla | Descripción |
|---|---|
| Cuenta autenticada | La búsqueda se limita a compañías asociadas a la cuenta identificada por el Bearer. |
| Cuenta administradora | Si Tandia habilita una cuenta administrativa para la integración, su api_key permite buscar las compañías asociadas a esa cuenta. |
| Sin búsqueda global pública | La documentación general no expone endpoints privados de búsqueda global entre cuentas. |
Lista de compañías
El servicio trae todas las compañías que se encuentren registradas con el usuario que haya iniciado sesión.
GET /api/account/companies
Host: invoice.test.tandia.io
Content-Type: application/json
Authorization: Bearer token-de-api
Query Params
- limit: indica el límite de cuántos registros de compañías se quiere obtener por solicitud.
- next_token: token requerido para acceder a la siguiente página de registros. Este es enviado tras la primera solicitud si es que hubiera más registros en la siguiente página, considerando el límite previamente establecido.
Ejemplo de solicitud
GET https://invoice.test.tandia.io/api/account/companies?limit=2&next_token=abcd12345
Respuesta
Al realizar la solicitud GET, la API responderá con un estado 200 si la solicitud fue exitosa y devolverá la respuesta en formato JSON. A continuación, la estructura de la respuesta.
{
"data": [
{
"business_name": "Tandia Test 0 S.A.C.",
"country": "PE",
"metadata": null,
"address": {
"country": "PE",
"address": "SAN MIGUEL DE MIRAFLORES",
"city_subdivision": "MIRAFLORES",
"city": "LIMA",
"district": "MIRAFLORES",
"postal_zone": "12345",
"country_subentity": "LIMA",
"type_code": null
},
"web_hook": "https://invoice.tandia.local/test/webhook/",
"tax_id": "011223344",
"trade_name": "Tandia Test 0 S.A.C.",
"environment": "TEST",
"account_id": "acc_7449a64d83b17ba",
"entity_type": "company",
"phone": "+51 986187825",
"logo": null,
"id": "com_61a80925017e4",
"email": "cuenta_test@tandia.pe"
}
],
"meta": {
"next_token": "next_token_aqui"
}
}
Búsqueda de compañías por País y RUC
Este endpoint está documentado de forma consolidada en la sección Búsqueda y validación previa de RUC, que incluye parámetros, proceso recomendado, respuesta y alcance de permisos.
A continuación se mantienen únicamente los detalles de paginación para consultas con múltiples resultados.
Query Params
- limit: indica el límite de cuántos registros de compañías se quiere obtener por solicitud.
- next_token: token requerido para acceder a la siguiente página de registros. Se obtiene del campo
meta.next_tokenen la respuesta anterior.
Ejemplo de solicitud con paginación
GET https://invoice.test.tandia.io/api/company/search/country/PE/taxId/01234567891?limit=10&next_token=abcd12345
La respuesta sigue la misma estructura documentada en la sección de validación previa.