Skip to main content
How much budget do I have left, and when will my upload finish? Both are readable, and both come with a caveat you should read before you build on them: every number on this page is a live projection of the quota ledger, computed the moment you ask. None of it reserves anything. The four surfaces below exist so you can show a customer what is happening and explain why work is pacing — not so a client can decide whether a call is allowed to go out. That decision is made server-side, at the moment of the call, and never anywhere else. Everything here is scoped to one Domain and readable by any API key in your organization. A Domain belonging to another organization returns 404, never 403.

Remaining budget

One request returns every rate bucket and all three of its windows — 60 seconds, one hour, one day:
cap is the effective budget — the provider’s cap after whatever safety margin you have applied to that bucket — so it can read lower than the limit Five9 publishes. remaining is cap minus what the ledger records as spent. escalated means the bucket is close enough to exhaustion that it has started checking the provider’s own counters before each call, and next_allowed_at is the earliest moment the next call is expected to be permitted, or null when nothing is holding it. as_of is when the counters were read, and is null for a Domain that has never dispatched.
Do not read this and then decide whether to send. A remaining value is a projection, not a reservation: nothing is set aside for you, every credential resolving to this Domain draws on the same allowance, and systems outside GetDialed can spend the same Domain’s provider budget without going through us at all. The value can change between your read and your call. The platform’s own dispatcher performs an atomic check at the moment of the call and is the only arbiter of whether that call may proceed — so a client-side budget check adds nothing except a race and the over-dialling that comes with losing it. Submit the work; let the dispatcher pace it.

How closely it agrees with the provider

GetDialed periodically reconciles the ledger against Five9’s own getCallCountersState counters. The published reconciliation tolerance is 20% of that window’s effective cap: within a window, the used figure on this surface and the provider’s own counter for the same bucket agree to within 20% of cap. On an Upload bucket at Five9’s published caps with an 80% margin — an effective 16 per minute, 320 per hour, 1,600 per day — that is 3 calls in the minute window, 64 in the hour, and 320 in the day. Two structural reasons the two figures are not always identical, both visible rather than hidden:
  • Other callers. Anything else spending the same Domain’s Five9 budget is counted by Five9 and not by us. When the provider reports higher than the ledger, reconciliation clamps the ledger up to the provider’s number — the provider sees callers we cannot, and the safe direction is always to believe the larger figure.
  • Calls made outside the paced dispatch path. A handful of GetDialed’s own synchronous calls — testing a credential, refreshing a Domain’s limits — spend real budget without being attributed to a credential. They show up in attribution as the unattributed remainder.

Queue depth and estimated completion

Depth is reported in three units, because a single “how much is waiting” number would conflate three different things: estimated_calls is labelled an estimate on purpose. Work aimed at the same destination merges into fuller provider calls when it is claimed, so the real call count is usually lower and can only be known at dispatch time. Every completion estimate computed from a non-empty queue carries the machine-readable caveat estimated_calls_pre_coalescing_projection for exactly that reason. Each unit also reports the share currently held by a pause — paused_records, paused_items — and estimated_calls_unpaused is the projected cost of the work that is actually free to run. That last figure is what the completion estimate paces against.

The estimate names what is holding your work

The completion object does not hand you a bare timestamp. It says what constrains it:
binding_window is the window whose limit binds — "60", "3600" or "86400" — so you can tell a customer whether it is the per-minute, the hourly or the daily limit holding their work. A window becomes a candidate for binding when the queued work exceeds what is left in that window — its remaining, not its full cap. One window is always a candidate regardless: the tightest one, because its permitted rate is the spacing floor between consecutive calls. Without that rule the daily window would appear to bind every projection on a Five9 Domain and report half an hour for work that finishes in two minutes. Judging candidacy on remaining matters most on a busy Domain. A window that is mostly spent binds work that would comfortably have fitted its cap — 100 queued calls against an hour with 40 of its 320 left spend those 40 now, and the rest cannot go until the window rolls — so the estimate includes the wait for that roll. It reads later than the naive figure you would get from the cap alone, which is the only safe direction for a number a customer plans around: this surface will tell you later, never earlier. binding_source names the category of constraint: Holds and the spacing floor add to the drain rather than replacing it: the queue still has to drain after a hold lifts, so an estimate that substituted the hold’s expiry for the drain would under-report. Estimates are computed fresh on every read, so nothing here can go stale between requests.

Why completion can be unknown

When completion is genuinely indeterminate, eta_seconds and eta_at read null and unknown_reason always names the cause. unknown is an honest answer, not a failure — a fabricated number that a customer plans around is strictly worse than admitting the drain rate cannot be projected. There are exactly three reasons, and each has something you can do about it:
What this estimate cannot see. Two limits are disclosed as machine-readable tokens in caveats rather than left for you to discover:
  • unreleased_paced_rows_not_visible — rows a paced batch has not released yet sit upstream of the queue, so they are structurally invisible to this read. The pacing term covers what is bound but not yet released; the rest is not counted.
  • legacy_batch_counters_missing — a batch minted before per-row rollup counters existed contributes no pacing term, so a Domain still draining one of those reads slightly optimistic.
You may also see batch_sample_truncated: the pacing term samples a bounded number of batches, so a pathological queue cannot turn one read into an unbounded series of lookups.
Completion here is Domain-level — when this Domain’s queue should drain. For “how far along is my upload”, read the batch’s own per-row counters; import outcomes is the model for what each row’s answer means.

Pre-flight cost estimate

Ask what an upload would cost before committing to it. This endpoint commits nothing: no records are ingested, no batch is created, no budget is reserved, nothing is written. Give exactly one row source — record_set_id for rows you have already uploaded, or record_count for a hypothetical size — and at least one of bucket or action_id so the estimate knows which provider budget to price against. Supplying both row sources, or neither, is a 422: two sources could disagree and there is no principled way to pick. An action this Domain does not meter, or one that spends more than one of its budgets, is rejected rather than priced against a guess.
Records become calls at the action’s max_records_per_call — a million rows is twenty upload calls at 50,000 each — and pct_of_remaining_day is what that costs as a share of today’s remaining budget.
The percentage and the spill verdict answer different questions. pct_of_remaining_day is this upload’s own cost. spills_past_day_cap also counts queued_estimated_calls — the work already queued ahead of you. That is why a modest upload can read as a small percentage and still be flagged as spilling: the backlog in front of it already consumed the day. Without that, two uploads that individually fit but jointly overflow would both read clean.
day_remaining_calls, pct_of_remaining_day and spills_past_day_cap all read null when the remaining daily budget cannot be read. A share of an unknown budget is unknown, not zero.

A spill warning never blocks a trigger

spills_past_day_cap: true does not mean the work would be refused. It means the work needs more provider calls than today’s remaining budget, so the overflow is delivered at your Domain’s permitted rate and continues into the following day. Multi-day pacing is the product working as designed, not a failure mode — and warning carries customer-ready copy saying so. If you change your mind, the brake is cancelling the batch, not a refused trigger: POST /flows/batches/{batch_id}/cancel stops all future sends and settles everything not yet sent as unprocessed. See stopping a bad upload.

The same estimate, inline on a trigger

A manual trigger — POST /flows/definitions/{definition_id}/trigger — returns the same object inline as estimate, so you get the cost of the work you just committed to without a second call:
estimate is null when the flow does not dispatch through a rate-limited platform budget — there is nothing to price.
The inline estimate appears on the manual trigger response only. A batch started by a schedule, a webhook or an event subscription has no HTTP response for you to read — nobody is waiting on the other end of the call — so it structurally cannot carry one. To know the cost of automated work ahead of time, call POST /platforms/five9/domains/{tenancy_id}/estimate yourself with the row count you expect; the figures are identical because it is the same estimator behind both surfaces.

Per-credential attribution

Several credentials can resolve to the same Domain, and they all draw on one shared provider budget. This surface answers “which credential lane is consuming it?”, broken down per credential for every bucket and all three windows:

The unattributed remainder

Every window carries one entry whose credential_id is null. That is the unattributed remainder, and it is expected rather than an error. Because it is always present, pct_of_used totals 100 within every window — spend nobody can attribute stays visible instead of being quietly spread across your credentials and making the denominator a lie. Two things land there, and a non-zero remainder is normal for both reasons:
  • Other systems spending the same Domain’s budget. Anything outside GetDialed that calls Five9 against this Domain is counted by the provider, and reconciliation clamps our ledger up to the provider’s own counter when it reports higher. That difference cannot belong to any of your credentials, because none of them made those calls.
  • GetDialed’s own synchronous calls. A small number of calls made outside the paced dispatch path — testing a credential, for instance — are not attributed today.
Display names are resolved when you read, so a renamed credential is never stale. A credential you have since deleted keeps its row with a credential_name of null: the calls were really made, and dropping the row would move real spend out of the total. An entry can also name a credential that was retired before the current model — the row keeps its recorded spend and reads with a null name, because a retired identifier is not a display name.

Usage history

The recorded rate-limit usage series for a Domain, newest first. Each row is one downsampled observation for a bucket and window:
used is what GetDialed recorded spending and cap the effective budget at the time. observed is the provider’s own counter when a reconciliation read happened to run in that minute, and drift the difference between the two — both are null in minutes with no reconciliation read. A sustained non-zero drift means something outside GetDialed is also spending the Domain’s budget. Three properties worth knowing before you build a chart on it:
  • Counts only. The series never contains a record value, a phone number or a list name. That is what makes it safe to read and export in bulk.
  • Retained 30 days, on a rolling window. The history is bounded rather than complete — older observations age out and are gone.
  • Cursor-paged. Filter with bucket and window (both optional and additive), then pass the previous response’s next_cursor back verbatim in cursor. The cursor is opaque: do not parse it. next_cursor: null means you have reached the oldest retained row, and total is null on this feed by design — counting a 30-day series on every page would cost more than the page itself.

Next steps

Dispatch pacing

Why work waits: merging, lane order, paced release, and what a pause holds.

Platform tenancy

The Domain record whose rate buckets and safety margins set every budget on this page.

Bulk ingestion

Stage millions of records, trigger by reference, and read the inline estimate.

Import outcomes

Per-row progress for one batch, which is what “how far along is my upload” really means.