---
title: "Put unsynced usage back on the billing queue"
method: POST
path: "/v1/admin/billing/redrive"
tags: ["billing"]
---

# Put unsynced usage back on the billing queue

`POST /v1/admin/billing/redrive`

## Request

- Base URL: `https://api.hyperresearch.ai`
- URL: `https://api.hyperresearch.ai/v1/admin/billing/redrive`
- Auth: API key in cookie `hr_session`

Re-queues `{ usage_event_id }` messages for ledger rows Stripe has not acknowledged, and RESETS their re-drive counter — the reason an operator presses this is that they have fixed the cause, and a counter that survived the fix would refuse the first retry after it. Idempotent and safe to repeat: the consumer derives the amount, customer and workspace from the persisted row and collapses a row that has since synced to a no-op. Nothing here can change an amount. Every call writes an audit row naming who did it.

## Request body

- BillingRedriveRequest
  - `usage_event_ids` string[]: The exact ledger rows to re-queue. Omit to take the oldest unsynced priced rows instead. An id that is not an unsynced ledger row is reported back under `skipped`, never enqueued.
  - `limit` integer
  - `reconcile` 'charged' | 'not_charged': Your verdict on rows reported under `needs_reconcile` on `GET /v1/admin/billing/unsynced`, after you have read the Stripe meter-event summary for that customer and window. `charged`: Stripe has it — the ledger row is marked synced with no provider call. `not_charged`: Stripe does not — the flag and the attempt instant are cleared, which starts a fresh idempotency window, and the row goes back on the queue. Requires `usage_event_ids`: a verdict is about rows you have looked at, so without them this call does nothing.

## Response `200`

What was re-queued

- BillingRedriveResult
  - `available` boolean, required
  - `requeued` string[], required
  - `reconciled` string[], required: Rows your `reconcile` verdict settled or released (0042).
  - `skipped` object[], required
    - `usage_event_id` string, required
    - `reason` 'unknown' | 'already_synced' | 'complimentary' | 'needs_reconcile' | 'stale_idempotency_window', required

## Other responses

- `400`: Invalid request
- `401`: Authentication failed
- `403`: Insufficient scope or plan
- `404`: Not found
- `429`: Rate limited or over quota
- `500`: Internal error

---

[API](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api.md) · [All operations](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/revisions/726ef831ebf4?raw)
