Portal de Proveedores — Facturas
Estos endpoints permiten a un proveedor (prestador) gestionar sus propias facturas directamente desde la API: listarlas, abrir una para ver el detalle, declarar el monto que está facturando, declarar varias a la vez y verificar un monto contra la tolerancia de la compañía antes de enviarlo. Cada endpoint está acotado a la cuenta de proveedor detrás del token — solo ves y operás sobre tus propias facturas.
Cuenta de proveedor requerida
El usuario autenticado debe estar vinculado a un proveedor (prestador). Las solicitudes desde una cuenta que no sea de proveedor se rechazan con 403 FORBIDDEN. Todos los endpoints requieren un token JWT válido, una clave de API y el encabezado tenant. Ver Autenticación .
Listar facturas
Obtiene una lista paginada de las facturas del proveedor para un rango de fechas, con estado opcional y búsqueda de texto libre. Cada fila incluye el monto del sistema, el monto declarado y la diferencia entre ambos. La respuesta también incluye la tolerancia que aplica al proveedor para que puedas interpretar las diferencias.
GET /apidev/v1/supplier-portal/invoices
Permiso APICLI_PORTALPROVEEDOR_READ
Límite de solicitudes 30 req/min (ventana deslizante)
Every request to a protected endpoint requires these headers:
Header Required Description AuthorizationYes Bearer token obtained from the Login endpoint. Format: Bearer <token> X-API-KeyYes Company integration key provided during onboarding. Format: gtk_xxx... tenantYes Your assigned tenant domain (default: geotareas.com) — always send your assigned tenant Content-TypeConditional application/json — required for POST and PUT requests
Parámetros de consulta
Parámetro Tipo Requerido Descripción startdatestring (ISO 8601) Sí Inicio del rango de fechas enddatestring (ISO 8601) Sí Fin del rango de fechas (el rango no puede exceder los 93 días) statusstring No Filtrar por código de estado de factura: PEN, ENV, APR, REV, REC, AJU, LIQ searchstring No Coincidencia de texto libre en número de servicio, cuenta o número de factura (máx. 120 caracteres) limitinteger No Registros por página. Mín.: 1, Máx.: 100, Predeterminado: 25 offsetinteger No Registros a omitir. Predeterminado: 0
Campos de la respuesta — data.rows[]
Campo Tipo Descripción invoice_idstring Identificador único de la factura invoice_datestring | null Fecha de la factura service_idstring ID del servicio/tarea relacionado service_numberstring | null Número visible del servicio service_call_datestring | null Cuándo se solicitó el servicio account_namestring | null Cuenta a la que pertenece el servicio citystring | null Ciudad del servicio system_amountnumber Monto calculado por el sistema declaration_idstring | null ID de la declaración, si el proveedor ya declaró un monto declared_amountnumber | null Monto declarado por el proveedor declared_notesstring | null Notas que el proveedor agregó en la declaración provider_invoice_numberstring | null Número de factura propio del proveedor provider_invoice_datestring | null Fecha de factura propia del proveedor state_codestring Código de estado de la factura (PEN, ENV, …) state_namestring Nombre del estado de la factura differencenumber | null Monto declarado menos monto del sistema difference_pctnumber | null Diferencia como porcentaje del monto del sistema attachment_urlstring | null URL al archivo de factura adjunto attachment_filenamestring | null Nombre original del archivo del adjunto
Campos de la respuesta — data.tolerance
Campo Tipo Descripción modestring | null Modo de tolerancia: PCT, ABS, AMB, o null cuando no aplica ninguna tolerance_pctnumber | null Diferencia porcentual permitida tolerance_absnumber | null Diferencia absoluta permitida auto_approveboolean Si los montos dentro de la tolerancia se aprueban automáticamente sourcestring De dónde proviene la tolerancia: proveedor, global o ninguna
Ejemplo de código
curl -s "https://$TENANT/apidev/v1/supplier-portal/invoices?startdate=2026-05-01&enddate=2026-05-31&status=PEN&limit=10" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"
const params = new URLSearchParams ( {
startdate : '2026-05-01' ,
enddate : '2026-05-31' ,
status : 'PEN' ,
limit : '10' ,
} ) ;
const response = await fetch (
` https:// ${ TENANT } /apidev/v1/supplier-portal/invoices? ${ params } ` ,
{
headers : {
Authorization : ` Bearer ${ TOKEN } ` ,
'X-API-Key' : APIKEY ,
tenant : TENANT ,
} ,
}
) ;
const { data , meta } = await response . json ( ) ;
console . log ( ` ${ data . rows . length } of ${ meta . total } invoices, tolerance source: ${ data . tolerance . source } ` ) ;
Ejemplo de respuesta
{
"success" : true ,
"data" : {
"rows" : [
{
"invoice_id" : "7234567890123456789" ,
"invoice_date" : "2026-05-03T15:02:00" ,
"service_id" : "103878" ,
"service_number" : "SRV-2026-0042" ,
"service_call_date" : "2026-05-02T09:10:00" ,
"account_name" : "Supermercado Centro" ,
"city" : "Montevideo" ,
"system_amount" : 1098.00 ,
"declaration_id" : "8100000000045" ,
"declared_amount" : 1100.00 ,
"declared_notes" : "Incluye traslado." ,
"provider_invoice_number" : "A-0001-0000123" ,
"provider_invoice_date" : "2026-05-03" ,
"state_code" : "ENV" ,
"state_name" : "Enviada" ,
"difference" : 2.00 ,
"difference_pct" : 0.18 ,
"attachment_url" : "https://files.example.com/inv/123.pdf" ,
"attachment_filename" : "factura-123.pdf"
}
] ,
"tolerance" : {
"mode" : "PCT" ,
"tolerance_pct" : 5.0 ,
"tolerance_abs" : null ,
"auto_approve" : true ,
"source" : "proveedor"
}
} ,
"meta" : {
"total" : 1 ,
"limit" : 10 ,
"offset" : 0
}
}
Detalle de factura
Obtiene una factura individual con su desglose completo: los mismos campos de fila que el listado, más los conceptos de las líneas de detalle y la tolerancia que aplica. Devuelve 404 si la factura no existe o no pertenece al proveedor.
GET /apidev/v1/supplier-portal/invoices/{id}
Permiso APICLI_PORTALPROVEEDOR_READ
Límite de solicitudes 30 req/min (ventana deslizante)
Parámetros de ruta
Parámetro Tipo Requerido Descripción idstring Sí Identificador único de la factura
Campos de la respuesta — data.concepts[]
Campo Tipo Descripción concept_idstring ID del catálogo de conceptos descriptionstring Descripción del concepto unit_amountnumber Monto por unidad quantitynumber Cantidad tax_pctnumber Porcentaje de impuesto aplicado totalnumber Total de la línea
El objeto data también incluye todos los campos listados para una fila del listado y un objeto tolerance (ver Listar facturas ).
Ejemplo de código
curl -s "https://$TENANT/apidev/v1/supplier-portal/invoices/7234567890123456789" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"
const response = await fetch (
` https:// ${ TENANT } /apidev/v1/supplier-portal/invoices/7234567890123456789 ` ,
{
headers : {
Authorization : ` Bearer ${ TOKEN } ` ,
'X-API-Key' : APIKEY ,
tenant : TENANT ,
} ,
}
) ;
const { data } = await response . json ( ) ;
console . log ( ` ${ data . service_number } : ${ data . concepts . length } concepts ` ) ;
Ejemplo de respuesta
{
"success" : true ,
"data" : {
"invoice_id" : "7234567890123456789" ,
"invoice_date" : "2026-05-03T15:02:00" ,
"service_id" : "103878" ,
"service_number" : "SRV-2026-0042" ,
"account_name" : "Supermercado Centro" ,
"city" : "Montevideo" ,
"system_amount" : 1098.00 ,
"declaration_id" : "8100000000045" ,
"declared_amount" : 1100.00 ,
"declared_notes" : "Incluye traslado." ,
"provider_invoice_number" : "A-0001-0000123" ,
"provider_invoice_date" : "2026-05-03" ,
"state_code" : "ENV" ,
"state_name" : "Enviada" ,
"difference" : 2.00 ,
"difference_pct" : 0.18 ,
"attachment_url" : "https://files.example.com/inv/123.pdf" ,
"attachment_filename" : "factura-123.pdf" ,
"concepts" : [
{
"concept_id" : "100" ,
"description" : "Mano de obra" ,
"unit_amount" : 900.00 ,
"quantity" : 1 ,
"tax_pct" : 22.0 ,
"total" : 1098.00
}
] ,
"tolerance" : {
"mode" : "PCT" ,
"tolerance_pct" : 5.0 ,
"tolerance_abs" : null ,
"auto_approve" : true ,
"source" : "proveedor"
}
} ,
"meta" : { }
}
Declarar monto de factura
Declara el monto que el proveedor está facturando para una factura. Es un upsert : si todavía no existe una declaración se crea, de lo contrario se actualiza la existente. La respuesta informa el estado resultante y cómo se compara el monto declarado con la tolerancia de la compañía.
POST /apidev/v1/supplier-portal/invoices/declare
Permiso APICLI_PORTALPROVEEDOR_WRITE
Límite de solicitudes 10 req/min (ventana deslizante)
Cuerpo de la solicitud
Campo Tipo Requerido Descripción invoice_idstring Sí Factura a declarar (cadena numérica) amountnumber Sí Monto declarado. Debe ser >= 0 notesstring No Notas de texto libre para la declaración invoice_numberstring No Número de factura propio del proveedor (máx. 60 caracteres) invoice_datestring (ISO 8601) No Fecha de factura propia del proveedor tax_pctnumber No Porcentaje de impuesto (0–100)
Campos de la respuesta — data.tolerance
Campo Tipo Descripción within_toleranceboolean Si el monto declarado está dentro de la tolerancia differencenumber Monto declarado menos monto del sistema difference_pctnumber Diferencia como porcentaje del monto del sistema difference_absnumber Diferencia absoluta actionstring Acción resultante (por ejemplo, aprobación automática o envío a revisión) config_sourcestring De dónde proviene la tolerancia aplicada
Ejemplo de código
curl -s -X POST "https://$TENANT/apidev/v1/supplier-portal/invoices/declare" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"invoice_id": "7234567890123456789",
"amount": 1100.00,
"notes": "Incluye traslado.",
"invoice_number": "A-0001-0000123",
"invoice_date": "2026-05-03",
"tax_pct": 22
}'
const response = await fetch (
` https:// ${ TENANT } /apidev/v1/supplier-portal/invoices/declare ` ,
{
method : 'POST' ,
headers : {
Authorization : ` Bearer ${ TOKEN } ` ,
'X-API-Key' : APIKEY ,
tenant : TENANT ,
'Content-Type' : 'application/json' ,
} ,
body : JSON . stringify ( {
invoice_id : '7234567890123456789' ,
amount : 1100.0 ,
notes : 'Incluye traslado.' ,
invoice_number : 'A-0001-0000123' ,
invoice_date : '2026-05-03' ,
tax_pct : 22 ,
} ) ,
}
) ;
const { data } = await response . json ( ) ;
console . log ( ` Declared. Within tolerance: ${ data . tolerance . within_tolerance } ` ) ;
Ejemplo de respuesta
{
"success" : true ,
"data" : {
"declaration_id" : "8100000000045" ,
"declared_amount" : 1100.00 ,
"state_id" : 101 ,
"tolerance" : {
"within_tolerance" : true ,
"difference" : 2.00 ,
"difference_pct" : 0.18 ,
"difference_abs" : 2.00 ,
"action" : "AUTO_APPROVE" ,
"config_source" : "proveedor"
}
} ,
"meta" : { }
}
Declarar en lote
Declara montos para muchas facturas en una sola solicitud. Cada ítem se procesa de forma independiente, por lo que la solicitud siempre devuelve 200 con un éxito o fallo por ítem. Usalo para enviar todas las declaraciones de un período de una sola vez.
POST /apidev/v1/supplier-portal/invoices/declare-batch
Permiso APICLI_PORTALPROVEEDOR_WRITE
Límite de solicitudes 10 req/min (ventana deslizante)
Cuerpo de la solicitud
Campo Tipo Requerido Descripción declarationsarray Sí Lista de declaraciones (1–100 ítems)
Cada ítem en declarations[] acepta los mismos campos que Declarar monto de factura :
Campo Tipo Requerido Descripción invoice_idstring Sí Factura a declarar amountnumber Sí Monto declarado (>= 0) notesstring No Notas de texto libre invoice_numberstring No Número de factura propio del proveedor invoice_datestring (ISO 8601) No Fecha de factura propia del proveedor tax_pctnumber No Porcentaje de impuesto (0–100)
Campos de la respuesta — data
Campo Tipo Descripción resultsarray Una entrada por cada ítem enviado, en orden acceptednumber Cuántos ítems se declararon correctamente rejectednumber Cuántos ítems fallaron
Cada entrada de results[] incluye invoice_id y success. En caso de éxito incluye los mismos campos que una declaración individual; en caso de fallo incluye un error que describe el motivo.
Ejemplo de código
curl -s -X POST "https://$TENANT/apidev/v1/supplier-portal/invoices/declare-batch" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"declarations": [
{ "invoice_id": "7234567890123456789", "amount": 1100.00, "invoice_number": "A-0001-0000123" },
{ "invoice_id": "7234567890123456790", "amount": 540.00 }
]
}'
const response = await fetch (
` https:// ${ TENANT } /apidev/v1/supplier-portal/invoices/declare-batch ` ,
{
method : 'POST' ,
headers : {
Authorization : ` Bearer ${ TOKEN } ` ,
'X-API-Key' : APIKEY ,
tenant : TENANT ,
'Content-Type' : 'application/json' ,
} ,
body : JSON . stringify ( {
declarations : [
{ invoice_id : '7234567890123456789' , amount : 1100.0 , invoice_number : 'A-0001-0000123' } ,
{ invoice_id : '7234567890123456790' , amount : 540.0 } ,
] ,
} ) ,
}
) ;
const { data } = await response . json ( ) ;
console . log ( ` ${ data . accepted } accepted, ${ data . rejected } rejected ` ) ;
Ejemplo de respuesta
{
"success" : true ,
"data" : {
"results" : [
{
"invoice_id" : "7234567890123456789" ,
"success" : true ,
"declaration_id" : "8100000000045" ,
"declared_amount" : 1100.00 ,
"state_id" : 101 ,
"tolerance" : {
"within_tolerance" : true ,
"difference" : 2.00 ,
"difference_pct" : 0.18 ,
"difference_abs" : 2.00 ,
"action" : "AUTO_APPROVE" ,
"config_source" : "proveedor"
}
} ,
{
"invoice_id" : "7234567890123456790" ,
"success" : false ,
"error" : {
"code" : "NOT_FOUND" ,
"message" : "Invoice not found or not owned by this supplier."
}
}
] ,
"accepted" : 1 ,
"rejected" : 1
} ,
"meta" : { }
}
Validar monto (verificación previa)
Verifica un monto contra la tolerancia de la compañía antes de declararlo. Este endpoint no escribe nada — solo te dice cómo se trataría el monto. Devuelve 404 si la factura no pertenece al proveedor.
POST /apidev/v1/supplier-portal/invoices/validate
Permiso APICLI_PORTALPROVEEDOR_READ
Límite de solicitudes 30 req/min (ventana deslizante)
Cuerpo de la solicitud
Campo Tipo Requerido Descripción invoice_idstring Sí Factura a verificar amountnumber Sí Monto a probar. Debe ser >= 0
Campos de la respuesta — data
Campo Tipo Descripción invoice_idstring Factura que se verificó system_amountnumber Monto calculado por el sistema declared_amountnumber Monto que enviaste para la verificación within_toleranceboolean Si el monto está dentro de la tolerancia differencenumber Monto enviado menos monto del sistema difference_pctnumber Diferencia como porcentaje del monto del sistema difference_absnumber Diferencia absoluta actionstring Acción que resultaría (por ejemplo, aprobación automática o envío a revisión) config_sourcestring De dónde proviene la tolerancia aplicada
Ejemplo de código
curl -s -X POST "https://$TENANT/apidev/v1/supplier-portal/invoices/validate" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"invoice_id": "7234567890123456789",
"amount": 1500.00
}'
const response = await fetch (
` https:// ${ TENANT } /apidev/v1/supplier-portal/invoices/validate ` ,
{
method : 'POST' ,
headers : {
Authorization : ` Bearer ${ TOKEN } ` ,
'X-API-Key' : APIKEY ,
tenant : TENANT ,
'Content-Type' : 'application/json' ,
} ,
body : JSON . stringify ( {
invoice_id : '7234567890123456789' ,
amount : 1500.0 ,
} ) ,
}
) ;
const { data } = await response . json ( ) ;
if ( ! data . within_tolerance ) {
console . log ( ` Out of tolerance by ${ data . difference_pct } % — would go to review ` ) ;
}
Ejemplo de respuesta
{
"success" : true ,
"data" : {
"invoice_id" : "7234567890123456789" ,
"system_amount" : 1098.00 ,
"declared_amount" : 1500.00 ,
"within_tolerance" : false ,
"difference" : 402.00 ,
"difference_pct" : 36.61 ,
"difference_abs" : 402.00 ,
"action" : "REVIEW" ,
"config_source" : "proveedor"
} ,
"meta" : { }
}
Errores
Código HTTP Aplica a Descripción VALIDATION_ERROR400 Todos Parámetros o cuerpo inválidos (por ejemplo, falta startdate, amount menor a 0, más de 100 declaraciones) INVALID_DATE_RANGE400 Listado El rango de fechas excede los 93 días, o las fechas son inválidas UNAUTHORIZED401 Todos Token JWT / clave de API faltante o inválido TOKEN_EXPIRED401 Todos El JWT era válido pero ha expirado (vigencia de 1 hora) FORBIDDEN403 Todos La cuenta no es de proveedor — "This endpoint requires a supplier account." — o carece del permiso requerido NOT_FOUND404 Detalle, Declarar, Validar La factura no existe o no pertenece a tu cuenta de proveedor RATE_LIMITED429 Todos Se excedió el límite de solicitudes del endpoint