Skip to main content

Billing — Automation Rules

Automation rules define when and how invoices are generated automatically when a service reaches a certain status (e.g., FIN — Finished). These endpoints allow you to inspect rules, simulate their evaluation, and trigger automation manually.

Prerequisites

All endpoints on this page require a valid JWT token, API key, and tenant header. See Authentication for details.

Pending Implementation

These endpoints are documented but not yet implemented in the public API (/apidev/v1/billing/*). The internal billing services exist in geotareas/facturacion/ but have not been wired to the API developers module. This documentation reflects the planned contract — DTOs, controller routes, permissions, and tests are still pending.


List Automation Rules

Retrieve all automation rules configured for the tenant.

GET/apidev/v1/billing/automation-rules
PermissionAPICLI_BILLING_READ
Rate Limit60 req/min
Cache30s

Request Headers

Every request to a protected endpoint requires these headers:

HeaderRequiredDescription
AuthorizationYesBearer token obtained from the Login endpoint. Format: Bearer <token>
X-API-KeyYesCompany integration key provided during onboarding. Format: gtk_xxx...
tenantYesYour company hostname (e.g., yourcompany.geotareas.com)
Content-TypeConditionalapplication/json — required for POST and PUT requests

Query Parameters

ParameterTypeDescription
statusstringFilter by status: ACTIVE or INACTIVE (default: ACTIVE)
typestringFilter by invoice type: PAGAR or COBRAR

Response Fields

FieldTypeDescription
idstringRule unique identifier
namestringRule name
typestringInvoice type: PAGAR or COBRAR
statusstringACTIVE or INACTIVE
currency.idstringCurrency ID
currency.namestringCurrency name
trigger_status.idstringTrigger status ID
trigger_status.namestringService status that triggers the rule (e.g., "Finalizado")
initial_invoice_status.idstringInitial invoice status ID
initial_invoice_status.namestringInitial status assigned to generated invoices
tariffobject | nullFixed tariff, or null if auto-selected
auto_select_tariffbooleanWhether the system auto-selects the best matching tariff
impute_toobjectImputation flags (client, account, provider, vehicle, personal, origin)
concepts_countintegerNumber of concepts in the rule
filtersobjectSummary of active filters with counts and geographic filters

Code Examples

curl -s -X GET "https://api.example.com/apidev/v1/billing/automation-rules?status=ACTIVE" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"

Response Example

{
"success": true,
"data": [
{
"id": "8900123456789",
"name": "TARIFA UNICA PRESTADORES",
"type": "PAGAR",
"status": "ACTIVE",
"currency": { "id": "1", "name": "Pesos Uy" },
"trigger_status": { "id": "5", "name": "Finalizado" },
"initial_invoice_status": { "id": "1", "name": "Pendiente" },
"tariff": null,
"auto_select_tariff": true,
"impute_to": {
"client": false,
"account": false,
"provider": true,
"vehicle": false,
"personal": false,
"origin": true
},
"concepts_count": 2,
"filters": {
"providers_count": 0,
"origins_count": 0,
"prestations_count": 0,
"motives_count": 0,
"vehicles_count": 0,
"personal_count": 0,
"geographic_origin": null,
"geographic_destination": null
}
}
]
}

Automation Rule Detail

Get the full detail of an automation rule including all its filters and concept definitions.

GET/apidev/v1/billing/automation-rules/{id}
PermissionAPICLI_BILLING_READ
Rate Limit60 req/min
Cache30s

Response Example

{
"success": true,
"data": {
"id": "8900123456789",
"name": "TARIFA UNICA PRESTADORES",
"type": "PAGAR",
"status": "ACTIVE",
"currency": { "id": "1", "name": "Pesos Uy" },
"trigger_status": { "id": "5", "name": "Finalizado" },
"initial_invoice_status": { "id": "1", "name": "Pendiente" },
"tariff": null,
"auto_select_tariff": true,
"impute_to": { "client": false, "account": false, "provider": true, "vehicle": false, "personal": false, "origin": true },
"client_id": null,
"account_id": null,
"geographic_filter": {
"origin": { "country_id": null, "department_id": null, "city_id": null, "zone_id": null, "special_place_id": null },
"destination": { "country_id": null, "department_id": null, "city_id": null, "zone_id": null, "special_place_id": null }
},
"filters": {
"providers": [],
"origins": [],
"prestations": [],
"motives": [],
"vehicles": [],
"personal": []
},
"concepts": [
{
"concept_id": "3",
"concept_name": "Movida",
"quantity_type": "FIXED",
"quantity": 1.00,
"price_type": "TARIFF",
"price": null,
"condition_formula": null
},
{
"concept_id": "5",
"concept_name": "Kilometros recorridos",
"quantity_type": "FORMULA",
"quantity_formula": { "id": "101", "name": "Condicion Km Extra" },
"price_type": "TARIFF",
"price": null,
"condition_formula": { "id": "100", "name": "Condicion Km Extra" }
}
]
}
}

Evaluate Rule (Dry Run)

Simulate how an automation rule would apply to a specific service, without creating any invoice. Useful for debugging, QA, and pre-flight checks.

POST/apidev/v1/billing/automation-rules/{id}/evaluate
PermissionAPICLI_BILLING_ADMIN
Rate Limit5 req/min (token bucket — computationally expensive)
CacheNone

Request Body

FieldTypeRequiredDescription
service_idstringYesService/task ID to evaluate against
{ "service_id": "103878" }

Response — Rule Applies

{
"success": true,
"data": {
"rule_id": "8900123456789",
"service_id": "103878",
"applies": true,
"reason": "All filters match",
"tariff_found": {
"id": "1",
"name": "Tarifa General - Prestador",
"selection_level": "GENERAL"
},
"concepts_evaluated": [
{
"concept_id": "3",
"concept_name": "Movida",
"quantity": 1.00,
"unit_price": 900.00,
"subtotal": 900.00,
"tax_percent": 22.00,
"tax_amount": 198.00,
"total": 1098.00,
"quantity_source": "FIXED",
"price_source": "TARIFF"
},
{
"concept_id": "5",
"concept_name": "Kilometros recorridos",
"quantity": 15.0,
"unit_price": 50.00,
"subtotal": 750.00,
"tax_percent": 22.00,
"tax_amount": 165.00,
"total": 915.00,
"quantity_source": "FORMULA",
"formula_detail": {
"formula_name": "Condicion Km Extra",
"condition_passed": true,
"condition_detail": "DISTANCIA_KMS(Base proveedor -> Origen tarea) = 35.0 > 20 -> 35.0 - 20 = 15.0 km"
},
"price_source": "TARIFF"
}
],
"totals": { "subtotal": 1650.00, "tax": 363.00, "total": 2013.00 },
"filters_evaluation": {
"geographic_origin": { "passed": true, "detail": "No geographic filter configured" },
"geographic_destination": { "passed": true, "detail": "No geographic filter configured" },
"providers": { "passed": true, "detail": "No provider filter configured" },
"origins": { "passed": true, "detail": "No origin filter configured" },
"prestations": { "passed": true, "detail": "No presta filter configured" },
"motives": { "passed": true, "detail": "No motive filter configured" },
"vehicles": { "passed": true, "detail": "No vehicle filter configured" },
"personal": { "passed": true, "detail": "No personal filter configured" }
}
}
}

Response — Rule Does Not Apply

{
"success": true,
"data": {
"rule_id": "8900123456789",
"service_id": "103878",
"applies": false,
"reason": "Origin filter mismatch: service.origin='Directa' is not in [Servicios Sura]",
"concepts_evaluated": [],
"totals": null
}
}

Errors

CodeHTTPDescription
BILLING_AUTOMATION_NOT_FOUND404Automation rule not found
BILLING_SERVICE_NOT_FOUND404Service does not exist

Run Automation

Evaluate all active automation rules for a specific service and generate the corresponding invoices. This is the same process that runs automatically when a service reaches the trigger status.

POST/apidev/v1/billing/invoices/automate
PermissionAPICLI_BILLING_ADMIN
Rate Limit5 req/min (token bucket)
CacheNone

Request Body

FieldTypeRequiredDefaultDescription
service_idstringYesService/task ID to automate
asyncbooleanNofalseIf true, returns job_id immediately without waiting
dry_runbooleanNofalseIf true, evaluates all rules without saving any invoice
{
"service_id": "103878",
"async": false,
"dry_run": false
}

Response — 200 OK (synchronous)

{
"success": true,
"data": {
"service_id": "103878",
"dry_run": false,
"rules_evaluated": 3,
"rules_applied": 1,
"invoices_created": [
{
"id": "7234567890123456789",
"rule_id": "8900123456789",
"rule_name": "TARIFA UNICA PRESTADORES",
"total": 1098.00
}
],
"rules_not_applied": [
{
"rule_id": "8900123456790",
"rule_name": "Regla Solo Montevideo",
"reason": "Geographic filter mismatch"
}
]
}
}

Response — 202 Accepted (async mode)

{
"success": true,
"data": {
"job_id": "job_abc123",
"service_id": "103878",
"status": "QUEUED",
"estimated_completion": "2026-04-03T16:00:05"
}
}

Errors

CodeHTTPDescription
BILLING_SERVICE_NOT_FOUND404Service does not exist
BILLING_AUTOMATION_ALREADY_RAN409Automation already ran for this service (use force: true to override)
CodeHTTP StatusDescriptionResolution
VALIDATION_ERROR400Request body or query parameters failed validationCheck the error.details field for specific validation failures
UNAUTHORIZED401Missing, expired, or invalid JWT token or API keyRe-authenticate via Login to get a fresh token
RATE_LIMITED429Too many requests — rate limit exceededWait until the Retry-After header time elapses. See Rate Limits
INTERNAL_ERROR500Unexpected server errorRetry after a brief delay. If persistent, contact support