Faktur

Company API

Endpoints bajo el prefijo /v1/company para gestionar la empresa asociada a la API Key: datos de empresa, establecimientos, puntos de emisión, secuenciales y certificado digital. Para base URL, headers y formato de respuesta, ver Introducción.

Alcance y scopes

Todos los endpoints de este documento requieren API Key con uno o ambos scopes:

ScopeUso
company:readGET: empresa, establecimientos, puntos de emisión, secuenciales, certificado (solo metadatos).
company:writePATCH/POST/DELETE: actualizar empresa, CRUD establecimientos, CRUD puntos de emisión, actualizar secuenciales, crear/actualizar/eliminar certificado.

La empresa es siempre la asociada a la API Key (por punto de emisión o por company). Sin el scope adecuado la API responde 403 (INSUFFICIENT_SCOPE).

2. Empresa

2.1 GET /v1/company

Scope: company:read

Devuelve la empresa asociada a la API Key (metadatos). No expone datos sensibles.

Respuesta 200

{
  "success": true,
  "data": {
    "id": "uuid",
    "userId": "uuid",
    "ruc": "0991234560001",
    "razonSocial": "MI EMPRESA S.A.",
    "nombreComercial": "Mi Empresa",
    "direccionMatriz": "Av. Amazonas 123, Quito",
    "obligadoContabilidad": true,
    "regimen": "GENERAL",
    "active": true,
    "defaultIvaRateCode": "4",
    "sendEmailNotifications": false,
    "emailSenderAlias": null,
    "createdAt": "2026-03-16T12:00:00.000Z",
    "updatedAt": "2026-03-16T12:00:00.000Z"
  }
}

Errores: 401 (API Key inválida/ausente), 403 (falta scope company:read).

2.2 PATCH /v1/company

Scope: company:write

Actualiza campos de la empresa. Todos los campos del body son opcionales.

CampoTipoDescripción
razonSocialstringRazón social.
nombreComercialstringNombre comercial.
direccionMatrizstringDirección matriz.
obligadoContabilidadbooleanObligado a llevar contabilidad.
regimenstringGENERAL, RIMPE_NEGOCIO_POPULAR, RIMPE_EMPRENDEDOR.
defaultIvaRateCodestringCódigo IVA por defecto (catálogo iva-rate-codes).
sendEmailNotificationsbooleanEnvío de notificaciones por email.
emailSenderAliasstringAlias del remitente en emails.
logoBase64stringLogo en base64 (opcional con prefijo data URI).

Respuesta 200: Objeto empresa actualizado (mismo formato que GET).

Errores: 400 (validación), 403 (scope).

3. Establecimientos

Base path: /v1/company/establishments. Todos los recursos pertenecen a la empresa de la API Key.

3.1 GET /v1/company/establishments

Scope: company:read

Lista todos los establecimientos de la empresa.

Respuesta 200

{
  "success": true,
  "data": [
    {
      "id": "e1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "companyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "code": "001",
      "address": "Av. Amazonas 123, Quito",
      "active": true,
      "createdAt": "2026-03-16T12:00:00.000Z",
      "updatedAt": "2026-03-16T12:00:00.000Z"
    },
    {
      "id": "e2b2c3d4-e5f6-7890-abcd-ef1234567891",
      "companyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "code": "002",
      "address": "Av. República 456, Guayaquil",
      "active": true,
      "createdAt": "2026-03-16T12:00:00.000Z",
      "updatedAt": "2026-03-16T12:00:00.000Z"
    }
  ]
}

3.2 GET /v1/company/establishments/:id

Scope: company:read

Obtiene un establecimiento por UUID. El id debe pertenecer a la empresa.

Respuesta 200

{
  "success": true,
  "data": {
    "id": "e1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "companyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "code": "001",
    "address": "Av. Amazonas 123, Quito",
    "active": true,
    "createdAt": "2026-03-16T12:00:00.000Z",
    "updatedAt": "2026-03-16T12:00:00.000Z"
  }
}

Errores: 404 ESTABLISHMENT_NOT_FOUND, 403 (scope).

3.3 POST /v1/company/establishments

Scope: company:write

Crea un establecimiento.

CampoTipoObligatorioDescripción
codestringCódigo de 3 dígitos numéricos (ej. "001").
addressstringDirección. Longitud 1–300.

Respuesta 201

{
  "success": true,
  "data": {
    "id": "e3b2c3d4-e5f6-7890-abcd-ef1234567892",
    "companyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "code": "003",
    "address": "Av. Naciones Unidas 789, Quito",
    "active": true,
    "createdAt": "2026-03-16T12:10:00.000Z",
    "updatedAt": "2026-03-16T12:10:00.000Z"
  }
}

Errores: 400 ESTABLISHMENT_CODE_EXISTS (código duplicado), 403 (scope).

3.4 PATCH /v1/company/establishments/:id

Scope: company:write

Actualiza un establecimiento. Campos opcionales: address, active.

Respuesta 200

{
  "success": true,
  "data": {
    "id": "e1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "companyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "code": "001",
    "address": "Av. Amazonas 123 y República, Quito",
    "active": true,
    "updatedAt": "2026-03-16T12:15:00.000Z"
  }
}

Errores: 404 ESTABLISHMENT_NOT_FOUND, 403 (scope).

3.5 DELETE /v1/company/establishments/:id

Scope: company:write

Desactiva el establecimiento (soft delete). Respuesta 204 sin cuerpo (no se devuelve JSON).

Errores: 404, 403.

4. Puntos de emisión

Base path: /v1/company/establishments/:establishmentId/emission-points. El establishmentId debe ser un establecimiento de la empresa.

4.1 GET .../emission-points?environment=PRUEBAS|PRODUCCION

Scope: company:read

Query param obligatorio: environment = PRUEBAS o PRODUCCION. Devuelve los puntos de emisión del establecimiento; los secuenciales incluidos se filtran por el ambiente indicado.

Respuesta 200

{
  "success": true,
  "data": [
    {
      "id": "p1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "establishmentId": "e1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "code": "001",
      "description": "Punto de emisión principal",
      "active": true,
      "createdAt": "2026-03-16T12:00:00.000Z",
      "updatedAt": "2026-03-16T12:00:00.000Z",
      "sequences": [
        { "id": "s1", "documentType": "INVOICE", "ambiente": "PRUEBAS", "lastSequential": 5, "nextSequential": 6 },
        { "id": "s2", "documentType": "CREDIT_NOTE", "ambiente": "PRUEBAS", "lastSequential": 0, "nextSequential": 1 }
      ]
    }
  ]
}

Errores: 400 INVALID_AMBIENTE, 404 ESTABLISHMENT_NOT_FOUND, 403 (scope).

4.2 GET .../emission-points/:id

Scope: company:read

Devuelve un punto de emisión por UUID (incluye secuenciales). Respuesta 200: mismo formato pero data es un solo objeto.

Errores: 404 EMISSION_POINT_NOT_FOUND, 403 (scope).

4.3 POST .../emission-points

Scope: company:write

Crea un punto de emisión con sus secuenciales iniciales por tipo de documento y ambiente.

CampoTipoObligatorioDescripción
codestringCódigo de 3 dígitos (ej. "001").
descriptionstringNoDescripción. Máx. 100 caracteres.
sequencesarrayAl menos un elemento. Ver tabla abajo.

Cada elemento de sequences:

CampoTipoDescripción
documentTypestringINVOICE o CREDIT_NOTE.
ambientestringPRUEBAS o PRODUCCION.
nextSequentialnumberPróximo número a emitir (entero ≥ 1).

Ejemplo body

{
  "code": "002",
  "description": "Caja 2",
  "sequences": [
    { "documentType": "INVOICE", "ambiente": "PRUEBAS", "nextSequential": 1 },
    { "documentType": "INVOICE", "ambiente": "PRODUCCION", "nextSequential": 1 },
    { "documentType": "CREDIT_NOTE", "ambiente": "PRUEBAS", "nextSequential": 1 },
    { "documentType": "CREDIT_NOTE", "ambiente": "PRODUCCION", "nextSequential": 1 }
  ]
}

Respuesta 201

{
  "success": true,
  "data": {
    "id": "p2b2c3d4-e5f6-7890-abcd-ef1234567891",
    "establishmentId": "e1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "code": "002",
    "description": "Caja 2",
    "active": true,
    "sequences": [
      { "documentType": "INVOICE", "ambiente": "PRUEBAS", "lastSequential": 0, "nextSequential": 1 },
      { "documentType": "INVOICE", "ambiente": "PRODUCCION", "lastSequential": 0, "nextSequential": 1 },
      { "documentType": "CREDIT_NOTE", "ambiente": "PRUEBAS", "lastSequential": 0, "nextSequential": 1 },
      { "documentType": "CREDIT_NOTE", "ambiente": "PRODUCCION", "lastSequential": 0, "nextSequential": 1 }
    ]
  }
}

Errores: 400 EMISSION_POINT_CODE_EXISTS, 404 ESTABLISHMENT_NOT_FOUND, 403 (scope).

4.4 PATCH .../emission-points/:id

Scope: company:write

Actualiza un punto de emisión. Campos opcionales: description, active.

Respuesta 200

{
  "success": true,
  "data": {
    "id": "p1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "establishmentId": "e1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "code": "001",
    "description": "Punto de emisión principal — actualizado",
    "active": true,
    "updatedAt": "2026-03-16T12:20:00.000Z"
  }
}

Errores: 404 EMISSION_POINT_NOT_FOUND, 403 (scope).

4.5 DELETE .../emission-points/:id

Scope: company:write

Desactiva el punto de emisión. Respuesta 204 sin cuerpo (no se devuelve JSON).

Errores: 404, 403.

5. Secuenciales

Se identifican por punto de emisión + tipo de documento + ambiente. Se crean al crear el punto (array sequences). La consulta y actualización se hacen por el ID del punto de emisión.

5.1 GET /v1/company/emission-points/:id/sequences

Scope: company:read

Lista los secuenciales del punto de emisión. El :id es el UUID del punto de emisión (no del establecimiento).

Query param opcional: environment = PRUEBAS o PRODUCCION para filtrar por ambiente.

Respuesta 200

{
  "success": true,
  "data": [
    {
      "id": "s1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "emissionPointId": "p1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "documentType": "INVOICE",
      "ambiente": "PRUEBAS",
      "lastSequential": 5,
      "nextSequential": 6,
      "updatedAt": "2026-03-16T12:00:00.000Z"
    },
    {
      "id": "s2b2c3d4-e5f6-7890-abcd-ef1234567891",
      "emissionPointId": "p1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "documentType": "CREDIT_NOTE",
      "ambiente": "PRUEBAS",
      "lastSequential": 0,
      "nextSequential": 1,
      "updatedAt": "2026-03-16T12:00:00.000Z"
    }
  ]
}

Errores: 400 (environment inválido), 403 EMISSION_POINT_NOT_IN_COMPANY, 403 (scope).

5.2 PATCH /v1/company/emission-points/:id/sequences/:documentType

Scope: company:write

Actualiza el próximo número a emitir para un secuencial. El ambiente va en el body (no en header).

Parámetros de ruta: id = UUID del punto de emisión; documentType = INVOICE o CREDIT_NOTE.

CampoTipoObligatorioDescripción
ambientestringPRUEBAS o PRODUCCION.
nextSequentialnumberPróximo secuencial a usar. Debe ser mayor que lastSequential.

Ejemplo body

{
  "ambiente": "PRODUCCION",
  "nextSequential": 201
}

Respuesta 200

{
  "success": true,
  "data": {
    "id": "s1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "emissionPointId": "p1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "documentType": "INVOICE",
    "ambiente": "PRODUCCION",
    "lastSequential": 100,
    "nextSequential": 201,
    "updatedAt": "2026-03-16T12:25:00.000Z"
  }
}

Errores: 400 INVALID_SEQUENTIAL (nextSequential ≤ lastSequential), 404 SEQUENCE_NOT_FOUND, 403 EMISSION_POINT_NOT_IN_COMPANY o scope.

6. Certificado

La API nunca devuelve el archivo .p12 ni la contraseña. Solo metadatos (fecha de expiración, subject, etc.).

6.1 GET /v1/company/certificate

Scope: company:read

Devuelve la información del certificado de la empresa (sin archivo ni contraseña).

Respuesta 200

{
  "success": true,
  "data": {
    "id": "uuid",
    "companyId": "uuid",
    "subjectCn": "0991234560001",
    "expiresAt": "2027-12-31T23:59:59.000Z",
    "uploadedAt": "2026-03-16T12:00:00.000Z",
    "updatedAt": "2026-03-16T12:00:00.000Z"
  }
}

Errores: 404 CERTIFICATE_NOT_FOUND, 403 (scope).

6.2 POST /v1/company/certificate — Crear o reemplazar

Scope: company:write

Sube un certificado digital (.p12) y su contraseña. Si ya existe certificado para la empresa, lo reemplaza. El archivo y la contraseña se almacenan cifrados y nunca se devuelven.

Content-Type: multipart/form-data

CampoTipoObligatorioDescripción
filefileArchivo .p12.
passwordstringContraseña del .p12.

Respuesta 201

{
  "success": true,
  "data": {
    "id": "c1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "companyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "subjectCn": "0991234560001",
    "expiresAt": "2027-12-31T23:59:59.000Z",
    "uploadedAt": "2026-03-16T12:00:00.000Z",
    "updatedAt": "2026-03-16T12:00:00.000Z"
  }
}

Errores: 400 FILE_REQUIRED (falta archivo), 400 (archivo inválido o contraseña incorrecta), 403 (scope).

6.3 PATCH /v1/company/certificate

Scope: company:write

Mismo formato que POST: multipart/form-data con file y password. Reemplaza el certificado existente. Si no existía, lo crea. Respuesta 200: metadatos del certificado actualizado (mismo formato que 6.1).

6.4 DELETE /v1/company/certificate

Scope: company:write

Elimina el certificado de la empresa. Respuesta 204 sin cuerpo (no se devuelve JSON).

Errores: 404 CERTIFICATE_NOT_FOUND, 403 (scope).

7. Resumen de rutas

MétodoRutaScope
GET/v1/companycompany:read
PATCH/v1/companycompany:write
GET/v1/company/establishmentscompany:read
GET/v1/company/establishments/:idcompany:read
POST/v1/company/establishmentscompany:write
PATCH/v1/company/establishments/:idcompany:write
DELETE/v1/company/establishments/:idcompany:write
GET/v1/company/establishments/:establishmentId/emission-points?environment=company:read
GET.../emission-points/:idcompany:read
POST.../emission-pointscompany:write
PATCH.../emission-points/:idcompany:write
DELETE.../emission-points/:idcompany:write
GET/v1/company/emission-points/:id/sequencescompany:read
PATCH/v1/company/emission-points/:id/sequences/:documentTypecompany:write
GET/v1/company/certificatecompany:read
POST/v1/company/certificatecompany:write
PATCH/v1/company/certificatecompany:write
DELETE/v1/company/certificatecompany:write

8. Códigos de error (Company API)

CódigoHTTPDescripción
INVALID_AMBIENTE400Query/body environment requerido o valor distinto de PRUEBAS/PRODUCCION.
ESTABLISHMENT_NOT_FOUND404Establecimiento no encontrado o no pertenece a la empresa.
ESTABLISHMENT_CODE_EXISTS400Ya existe un establecimiento con ese código en la empresa.
EMISSION_POINT_NOT_FOUND404Punto de emisión no encontrado.
EMISSION_POINT_CODE_EXISTS400Código de punto de emisión duplicado en el establecimiento.
EMISSION_POINT_NOT_IN_COMPANY403El punto de emisión no pertenece a la empresa de la API Key.
SEQUENCE_NOT_FOUND404No existe secuencial para ese documentType/ambiente en el punto.
INVALID_SEQUENTIAL400nextSequential debe ser mayor que lastSequential.
CERTIFICATE_NOT_FOUND404No hay certificado para la empresa.
FILE_REQUIRED400Falta el archivo .p12 en la petición multipart.
INSUFFICIENT_SCOPE403Falta scope company:read o company:write.