Usage & Metering
Read aggregated API and webhook usage, request logs, and endpoint metering metadata.
Usage & Metering API
Read aggregated API and webhook usage, browse request log entries, and discover endpoint metering metadata. These meta endpoints support the API Console and external monitoring integrations.
All endpoints in this document require Sanctum bearer authentication and are declared with price weight 0 — they are logged but do not consume weighted metering units.
Unit weighting matrix
Every /api/v1 request consumes a fixed number of units based on the endpoint's declared #[PriceWeight]. Weights reflect the worst-case query plan, not the average request. There are no weights at 5 or 7.
| Weight | Class | Description | Examples |
|---|---|---|---|
| 0 | Meta / introspection | Logged but excluded from weighted totals | GET /usage, GET /endpoints, GET /request_logs, GET /schema |
| 1 | Simple read | Show a resource; index with standard pagination | GET /accounts/{id}, GET /countries |
| 2 | Complex read / simple write | Index with heavy filters/includes; search; POST/PATCH a single resource | GET /catalogue_items, GET /search, POST /addresses |
| 3 | Write with side effects | Fires events, webhooks, or projections | Rental item changes, status transitions, flightcase pack/seal |
| 4 | Compound operation | Multi-entity writes, quote/document generation, bulk reads, semantic / AI search | POST /documents/generate, GET /search/semantic, rental convert / quick book-out |
| 6 | Availability | Scans asset calendars across a date range | GET /availability/calendar, /gantt, /shortages, /timeline, product/asset availability |
| 8 | Heavy computation | Shortage resolution, fleet-wide availability, bulk imports/exports | GET /warehouses/{id}/availability, POST /shortage_resolutions, POST /imports, POST /exports |
Tie-breaker
If an endpoint can be cheap or expensive depending on query parameters, it is priced at its worst-case plan. For example, a list that accepts deep Ransack filters and relation includes is weight 2, even when most callers page a small unfiltered set.
What is metered
Metering covers token-authenticated traffic only: requests to /api/v1 and
calls made through the MCP server, including plugin-bridged MCP tools — every
programmatic surface drains the same per-token unit throughput bucket. Web-UI
sessions are deliberately not metered: a human working the interface is
paced by the interface itself, whereas programmatic callers can issue expensive
work in unbounded loops, and it is that traffic the budget exists to shape.
Commercial metering and plan quotas layer on top of this same enforcement point
rather than introducing a second one, so the scope above holds for them too.
Prefer webhooks over polling
Polling expensive endpoints burns units quickly. Prefer outbound webhooks for change notification.
Example: Polling an availability endpoint at weight 6 every 30 seconds is roughly 17,280 units/day (6 × 2 × 60 × 24) — over 500,000 units/month, before any other traffic. Subscribe to webhook events instead.
Endpoints
| Method | URL | Summary | Ability | Weight |
|---|---|---|---|---|
GET | /api/v1/endpoints | List all registered API endpoints with metering metadata | system:read | 0 |
GET | /api/v1/request_logs | List request log entries with optional filtering and pagination | api-log:read | 0 |
GET | /api/v1/usage | Return grouped API usage aggregates for the requested window | api-usage:read | 0 |
GET | /api/v1/usage/export | Export usage aggregates as CSV (async) | api-usage:read | 0 |
Authentication
Requires a Sanctum bearer token with the ability shown above. Requests without the required ability receive 403.
List Usage
GET /api/v1/usage
Returns grouped aggregates from the usage_daily rollup table.
Query parameters
| Parameter | Default | Description |
|---|---|---|
window |
7d |
Date preset: 24h, 7d, 30d, or custom |
from |
— | Required when window=custom. Start date (Y-m-d) |
to |
— | Required when window=custom. End date (Y-m-d), must be on or after from |
channel |
— | Filter by metering channel: api, webhook_sent, or webhook_received |
dimension |
endpoint |
Grouping: token, endpoint, resource, day, or status |
token_id |
— | Filter API-channel rows to a specific personal access token ID |
Response
{
"usage": [
{
"key": "api.v1.accounts.index",
"label": null,
"request_count": 142,
"weighted_units": 284
}
],
"meta": {
"totals": {
"request_count": 1250,
"weighted_units": 980
},
"window": {
"preset": "7d",
"from": "2026-06-25T00:00:00+00:00",
"to": "2026-07-01T14:30:00+00:00"
},
"dimension": "endpoint"
}
}
| Field | Description |
|---|---|
usage[].key |
Group key — route name, token ID, resource name, date, or status class depending on dimension |
usage[].label |
Human label when available (e.g. token name for token dimension) |
usage[].request_count |
Total requests in the window |
usage[].weighted_units |
Sum of price weights (weight-0 traffic contributes 0) |
meta.totals |
Window totals across all groups |
meta.window |
Resolved date window |
Export Usage
GET /api/v1/usage/export
Accepts the same query parameters as GET /api/v1/usage. Dispatches an ExportApiUsage job and returns 202 Accepted with a job identifier. The CSV is delivered asynchronously (same export pipeline as the Usage dashboard).
List Request Logs
GET /api/v1/request_logs
Returns paginated detail rows from request_logs (API requests, outbound webhook deliveries, and inbound webhook receipts).
Filters (Ransack)
| Parameter | Description |
|---|---|
q[route_name_eq]=api.v1.accounts.index |
Exact route name (API channel) |
q[status_code_eq]=200 |
HTTP status code |
q[personal_access_token_id_eq]=3 |
Token ID (API channel) |
q[channel_eq]=api |
Metering channel: api, webhook_sent, webhook_received |
q[created_at_gteq]=2026-07-01 |
Created on or after |
q[created_at_lteq]=2026-07-01 |
Created on or before |
Sorts
| Parameter | Description |
|---|---|
sort=created_at |
Newest first (default when sort omitted) |
sort=-created_at |
Oldest first |
sort=status_code |
By status |
sort=route_name |
By route name |
Pagination
Standard offset pagination: ?page=2&per_page=20.
Response
{
"request_logs": [
{
"id": 1,
"channel": "api",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"method": "GET",
"uri": "/api/v1/accounts",
"route_name": "api.v1.accounts.index",
"resource": "accounts",
"operation": "index",
"personal_access_token_id": 3,
"user_id": 1,
"ability": "accounts:read",
"status_code": 200,
"duration_ms": 45,
"request_bytes": 0,
"response_bytes": 2048,
"price_weight": 2,
"weighted_units": 2,
"ip_address": "127.0.0.1",
"user_agent": "Signals-Explorer/1.0",
"created_at": "2026-07-01T14:30:00Z"
}
],
"meta": {
"total": 500,
"per_page": 20,
"page": 1
}
}
Detail log CSV export is available from the API Console Request Log UI (not exposed as a REST endpoint).
List Endpoints
GET /api/v1/endpoints
Returns every registered v1 route with metering metadata from ApiEndpointCatalogue and PriceWeightResolver.
Response
{
"endpoints": [
{
"name": "api.v1.accounts.index",
"method": "GET",
"uri": "/api/v1/accounts",
"resource": "accounts",
"operation": "index",
"ability": "accounts:read",
"price_weight": 2
},
{
"name": "api.v1.usage.index",
"method": "GET",
"uri": "/api/v1/usage",
"resource": null,
"operation": null,
"ability": "api-usage:read",
"price_weight": 0
}
]
}
Use this catalogue to discover required abilities and price weights before integrating. Weights of 0 indicate endpoints that are logged but excluded from weighted metering totals. The OpenAPI reference at /docs/api also surfaces each operation's unit cost as Cost: N units and the x-signals-units extension property.
Metering channels
| Channel | Source | Default units |
|---|---|---|
api |
LogApiRequest middleware on /api/v1/* |
Endpoint #[PriceWeight] |
webhook_sent |
DeliverWebhook job (first delivery attempt) |
1 (per event via WebhookEventRegistry) |
webhook_received |
InboundWebhookController (valid signature only) |
Source-configured weight (0–4) |
Related documentation
- API Console (platform) — Explorer, Request Log, Usage dashboard, and Webhooks UI
- Webhooks — outbound subscriptions and inbound receiver