Expenses

Descripción General

La API Pública de Gastos (Expenses) expone todos los gastos aprobados y enviados por los usuarios de una subsidiaria. Cada gasto contiene los metadatos contables necesarios (centro de costo, categoría, usuario, montos convertidos, documentos) y puede transicionar a los estados accounted o paid para conciliación con tus sistemas externos.

Estados de un Gasto

Internamente un gasto transita por múltiples estados (draft, pending, approved, accounted, paid, rejected).
La API pública solo permite mover un gasto en los siguientes flujos:

  • approved → accounted
  • approved → paid
  • accounted → paid

Endpoints Disponibles

MétodoEndpointDescripción
GET/public/v1/enterprises/{enterprise_id}/subsidiaries/{subsidiary_id}/expenses/Lista de gastos con filtros y paginación.
GET/public/v1/enterprises/{enterprise_id}/subsidiaries/{subsidiary_id}/expenses/{expense_id}/Detalle de un gasto.
PATCH/public/v1/enterprises/{enterprise_id}/subsidiaries/{subsidiary_id}/expenses/{expense_id}/Actualiza estado (accounted, paid) y campos de tracking externos

Expand Disponibles

Los campos relacionales pueden expandirse mediante ?expand= (separados por coma). Si no se expanden, se entrega únicamente el ID.

Campo (expand)Descripción
cost_centerDatos del centro de costo (id, nombre, internal_id).
categoryCategoría contable asociada.
userUsuario rendidor (nombre, contacto, identificadores).
approved_byLista de aprobadores.
fundFondo relacionado (número de fondo, descripción, status).
fareSolo para gastos tipo kilometraje. expone la tarifa asociada.

El campo additional_file_url solo estará presente si la empresa tiene habilitado el add-on de archivos adicionales.


1. Listar Gastos

Endpoint

GET /public/v1/enterprises/{enterprise_id}/subsidiaries/{subsidiary_id}/expenses/

Query Params

ParámetroDescripción
page, page_sizePaginación (por defecto 100 items, máximo 1000).
stateFiltra por estado interno (pending, approved, accounted, etc.).
created_at_fromFecha (YYYY-MM-DD) mínima de creación, inclusive.
created_at_toFecha (YYYY-MM-DD) máxima de creación, inclusive.
expandCampos a expandir (ver tabla anterior).

Respuesta Ejemplo (sin expand)

{
  "count": 1,
  "next": null,
  "previous": null,
  "status": 200,
  "error": "",
  "results": [
    {
      "id": "4e8b98f4-5719-4316-8142-d3080e476db0",
      "description": "Taxi aeropuerto",
      "expense_type": "invoice",
      "currency": "CLP",
      "amount": 45000.0,
      "usd_amount": null,
      "state": "approved",
      "date": "2025-01-12",
      "expense_number": 10215,
      "content_type": "invoicedata",
      "cost_center_id": "6f14a4e4-3513-4a47-9b5f-8a9fba118db7",
      "category_id": "3a0c33fe-0fb1-4390-9d32-7005bc30c15f",
      "user_id": "bf33075c-cb3b-44e4-9762-b21b16354e74",
      "fund_id": null,
      "is_active": true,
      "created_at": "2025-01-13T14:22:00Z",
      "url": "https://storage.googleapis.com/xpendit-expenses/receipt.pdf",
      "document_id": "F123",
      "expense_document_type": "Factura Afecta",
      "provider": "Transporte S.A.",
      "payment_method": "credit_card",
      "net_amount": 37815.13,
      "tax_amount": 7184.87,
      "tax_rate": 19.0,
      "subsidiary_currency": "CLP",
      "subsidiary_expense_amount": 45000.0,
      "accounted_id": null,
      "paid_id": null,
      "paid_at": null
    }
  ]
}

2. Obtener Detalle

Endpoint

GET /public/v1/enterprises/{enterprise_id}/subsidiaries/{subsidiary_id}/expenses/{expense_id}/

Puedes combinar expand para recuperar información enriquecida en una sola llamada:

GET .../expenses/4e8b98f4-5719-4316-8142-d3080e476db0/?expand=cost_center,category,user,fund

Respuesta (con expand)

{
  "status": 200,
  "error": "",
  "id": "4e8b98f4-5719-4316-8142-d3080e476db0",
  "description": "Taxi aeropuerto",
  "state": "approved",
  "cost_center": {
    "id": "6f14a4e4-3513-4a47-9b5f-8a9fba118db7",
    "name": "Ventas Chile",
    "internal_id": "CC-VEN"
  },
  "category": {
    "id": "3a0c33fe-0fb1-4390-9d32-7005bc30c15f",
    "name": "Transporte",
    "internal_id": "CAT-TRN"
  },
  "user": {
    "id": "bf33075c-cb3b-44e4-9762-b21b16354e74",
    "first_name": "Joshua",
    "last_name": "Murphy",
    "email": "[email protected]",
    "phone": "+56912345678",
    "internal_id": "EMP-202",
    "government_id": "12345678-9"
  },
  "subsidiary_currency": "CLP",
  "subsidiary_expense_amount": 45000.0,
  "additional_questions": [],
  "created_at": "2025-01-13T14:22:00Z",
  "is_active": true
}

3. Actualizar Estado (PATCH)

Usa este endpoint para reflejar en Xpendit que un gasto fue contabilizado o pagado en tus sistemas.

Endpoint

PATCH /public/v1/enterprises/{enterprise_id}/subsidiaries/{subsidiary_id}/expenses/{expense_id}/

Request Body

CampoTipoRequeridoDescripción
statestringaccounted o paid.
accounted_idstringOpcionalID de tu sistema contable. Se puede enviar también cuando el nuevo estado es paid.
paid_idstringOpcionalID del pago (solo válido cuando state = paid).
paid_atdatetimeOpcionalTimestamp ISO8601 del pago (solo válido cuando state = paid).

Validaciones Relevantes

  • Estado actual no puede ser igual al solicitado → 400 Expense is already in {state} state.
  • Solo approved y accounted pueden moverse → otros estados retornan 400 Cannot change state from '{current}'....
  • paid_id y paid_at se ignoran/validan cuando el estado objetivo no es paid.

Ejemplo: Marcar como Accounted

PATCH /.../expenses/4e8b98f4-5719-4316-8142-d3080e476db0/
Authorization: Api-Key en_sk_xxxxx
Content-Type: application/json

{
  "state": "accounted",
  "accounted_id": "ACC-EXP-2025-001"
}

Ejemplo: Marcar como Paid

{
  "state": "paid",
  "accounted_id": "ACC-EXP-2025-001", # Este campo no es necesario al pasar el gasto a pagado
  "paid_id": "PAY-EXP-2025-045",
  "paid_at": "2025-01-20T15:45:00Z"
}

La respuesta devolverá el gasto actualizado con los nuevos campos de tracking y el estado final.


Códigos de Respuesta

CódigoMotivo
200Operación exitosa (GET o PATCH).
400Payload inválido, filtros incorrectos o transición no permitida.
403API Key inválida o pertenece a otra empresa distinta a la del path.
404Gasto inexistente dentro de la subsidiaria especificada.

Mejores Prácticas

  1. Paginar siempre para grandes volúmenes; evita page_size enormes si no son necesarios.
  2. Conservar IDs externos (accounted_id, paid_id) para trazar conciliaciones futuras.
  3. Expand selectivo: solo solicita los campos que necesitas para mantener tiempos de respuesta bajos.
  4. Fechas en UTC: enviar paid_at siempre en formato ISO8601 UTC para evitar problemas de zona horaria.

Con este documento puedes integrar la API pública de gastos en tus procesos contables y de tesorería, manteniendo sincronizados los estados entre tus sistemas y Xpendit.