Skip to content

Create Usage Revocation

Creates a revocation request that refunds fund debits and marks analytics facts as revoked. The original usage event rows stay immutable.

POST /v1/projects/:project_id/usage/revocations
Terminal window
Authorization: Bearer <api-key>

Requires usage:revocation.

Field Required Description
project_id Yes Project that owns the events.

Provide exactly one selector: raw_event_ids or filter.

Field Required Description
raw_event_ids No Revoke usage events for these raw event IDs. Max 1000.
filter No Whitelisted filter object used to discover candidate events. occurred_at.from and occurred_at.to are required (unix seconds, second precision) inside filter; all other keys are optional. Max 100,000 matching usage events per request; create counts first and rejects oversized filters.
purpose Yes revoke or reprice. Reprice-purpose requests unlock Continue reprice.
reason Yes Human-readable reason recorded on the request and audit log.
idempotency_key No Tenant/project scoped create idempotency key.

Filter discovery is capped at 100,000 usage events. Call Estimate Usage Revocation with the same filter to preview event_count before create. Oversized filters return an error instead of silently truncating.

By raw event IDs:

Terminal window
curl -X POST 'http://127.0.0.1:8080/v1/projects/proj_gateway/usage/revocations' \
-H 'Authorization: Bearer <api-key>' \
-H 'Content-Type: application/json' \
-d '{
"raw_event_ids": ["raw_001", "raw_002"],
"purpose": "revoke",
"reason": "duplicate gateway report",
"idempotency_key": "revoke-batch-001"
}'

By whitelisted filter (async discovery against Doris usage facts):

Terminal window
curl -X POST 'http://127.0.0.1:8080/v1/projects/proj_gateway/usage/revocations' \
-H 'Authorization: Bearer <api-key>' \
-H 'Content-Type: application/json' \
-d '{
"filter": {
"occurred_at": { "from": 1704067200, "to": 1706745600 },
"subject_type": "user",
"subject_id": "user_001",
"billing_account_id": "acct_001",
"source": "gateway",
"metrics": ["input_tokens"],
"extractor_rule_set_id": "ers_old",
"dimensions": { "model": "gpt-4o" }
},
"purpose": "revoke",
"reason": "test data cleanup",
"idempotency_key": "revoke-filter-001"
}'

Allowed filter keys: occurred_at, subject_type, subject_id, billing_account_id, source, external_event_id, extractor_rule_set_id, extractor_version, metrics, dimensions.

occurred_at is required and must provide both from and to as unix seconds (second precision); to must be strictly after from. All other filter keys are optional.

Use top-level raw_event_ids for explicit ID lists. Singular metric, raw_event_id, and raw_event_id are not accepted inside filter.

202 Accepted

{
"revocation_id": "urv_001",
"status": "enqueueing"
}

The request is durable before the worker queue publish is attempted. If the queue publish fails, the API still returns 202 with "status": "enqueue_failed"; the request exists and can be re-published via the retry endpoint (or by re-sending this request with the same idempotency_key).

Poll GET /v1/projects/:project_id/usage/revocations/:revocation_id for progress. Targets and fund/Doris entries are available on the nested list endpoints.