Get Usage Estimate
curl --request GET \
--url https://api.signa.so/v1/organization/usage/estimate \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/organization/usage/estimate"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/organization/usage/estimate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/organization/usage/estimate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/organization/usage/estimate"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signa.so/v1/organization/usage/estimate")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/organization/usage/estimate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "usage_estimate",
"period": { "from": "2026-08-01T00:00:00.000Z", "to": "2026-09-01T00:00:00.000Z" },
"schedule_version": 2,
"credits": {
"charged": 31500,
"nominal": 33500,
"beta_free": 2000,
"per_month": { "charged": 30484, "nominal": 32419, "beta_free": 1935 }
},
"requests": { "total": 3155, "unrouted": 2, "unmapped": 0 },
"by_action": [
{
"action_id": "search",
"name": "Search",
"requests": 3000,
"quantity": 3000,
"credits": 30000,
"nominal_credits": 30000,
"disposition": "charged"
},
{
"action_id": "read",
"name": "Retrieve",
"requests": 153,
"quantity": 1500,
"credits": 1500,
"nominal_credits": 1500,
"disposition": "charged"
},
{
"action_id": "screen",
"name": "Screening",
"requests": 2,
"quantity": 2,
"credits": 0,
"nominal_credits": 2000,
"disposition": "beta_free"
}
],
"unmapped": [],
"plan_for": {
"id": "growth",
"name": "Growth",
"credits_included": 100000,
"per_month_annual": 399,
"monthly": 529
},
"packs_needed": null,
"above_self_serve": false,
"offer": { "percent_off": 25, "months": 12, "price_per_month": 299.25 },
"coverage": {
"pre_cutover_unmetered_actions": ["class_lookup", "rules_lookup"],
"note": "Class and rules lookups are free reference routes today and are not written to billing_events, so any part of this window before the cutover cannot show their volume."
},
"request_id": "req_abc123"
}
Usage & Credits
Get Usage Estimate
Your recorded traffic priced at the published credit schedule
GET
/
v1
/
organization
/
usage
/
estimate
Get Usage Estimate
curl --request GET \
--url https://api.signa.so/v1/organization/usage/estimate \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/organization/usage/estimate"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/organization/usage/estimate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/organization/usage/estimate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/organization/usage/estimate"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signa.so/v1/organization/usage/estimate")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/organization/usage/estimate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "usage_estimate",
"period": { "from": "2026-08-01T00:00:00.000Z", "to": "2026-09-01T00:00:00.000Z" },
"schedule_version": 2,
"credits": {
"charged": 31500,
"nominal": 33500,
"beta_free": 2000,
"per_month": { "charged": 30484, "nominal": 32419, "beta_free": 1935 }
},
"requests": { "total": 3155, "unrouted": 2, "unmapped": 0 },
"by_action": [
{
"action_id": "search",
"name": "Search",
"requests": 3000,
"quantity": 3000,
"credits": 30000,
"nominal_credits": 30000,
"disposition": "charged"
},
{
"action_id": "read",
"name": "Retrieve",
"requests": 153,
"quantity": 1500,
"credits": 1500,
"nominal_credits": 1500,
"disposition": "charged"
},
{
"action_id": "screen",
"name": "Screening",
"requests": 2,
"quantity": 2,
"credits": 0,
"nominal_credits": 2000,
"disposition": "beta_free"
}
],
"unmapped": [],
"plan_for": {
"id": "growth",
"name": "Growth",
"credits_included": 100000,
"per_month_annual": 399,
"monthly": 529
},
"packs_needed": null,
"above_self_serve": false,
"offer": { "percent_off": 25, "months": 12, "price_per_month": 299.25 },
"coverage": {
"pre_cutover_unmetered_actions": ["class_lookup", "rules_lookup"],
"note": "Class and rules lookups are free reference routes today and are not written to billing_events, so any part of this window before the cutover cannot show their volume."
},
"request_id": "req_abc123"
}
Beta. This is an estimate of what past traffic would cost on the published credit schedule — not a bill, an invoice, or a commitment. The response shape may still change.
Overview
Prices the authenticated organization’s recorded API traffic at the published credit schedule and shows which plan that traffic lands on. Use it to answer “what would last month have cost” before anything is charged. Requests recorded before the credit cutover carry the old placeholder weights, so they are re-priced from their route; requests recorded after it already carry credits and are reported at face value. Traffic the launch beta gives away is metered at its full list price and reported separately undercredits.beta_free, so credits.charged is always what you would actually pay.
plan_for, packs_needed and offer are derived from credits.per_month — the window scaled to 30 days — so a two-day window and a quarter recommend comparable plans rather than plans two sizes apart.
Defaults to the last 30 days. Requires the billing:read scope. Querying the estimate is not billed.
Query Parameters
string
Start of the window (
YYYY-MM-DD). Must be provided together with to. Omit both for the last 30 days.string
End of the window (
YYYY-MM-DD), inclusive. Must be provided together with from, may not be in the future, and the window may not exceed 92 days. Today is accepted; the window then ends at the moment you ask, so the projection divides only by time that has elapsed.Response
string
Always
"usage_estimate".object
integer
Version of the credit schedule used to price the window.
object
Show Credit totals
Show Credit totals
integer
What this traffic would cost you.
integer
The same traffic at list price, including anything the beta waives.
integer
List-price credits waived by the launch beta (
nominal - charged).object
The same three totals scaled to a 30-day month. Everything about the plan is decided on these, because a pooled monthly allowance can only be compared to a monthly figure.
object
object[]
Show Per-action breakdown, most expensive first
Show Per-action breakdown, most expensive first
string
Schedule action id (e.g.
search), or a synthetic bucket: unmapped, unrouted, removed:<path>, unpriced:<path>, free:<type>.string
Human name for the action.
integer
Requests in this bucket.
number
Charged quantity in the action’s own unit (pages, records, items, requests).
integer
Credits you would be charged.
integer
The same rows at list price.
string
charged, beta_free (metered, never debited), free (zero-price or non-billable), mixed (both, for a window spanning a change), or unpriced.object[]
object | null
object | null
boolean
true when the projected month is beyond what the plan ladder plus top-up packs sells; plan_for is then null and the right next step is a conversation.object | null
object
string
Request ID for debugging.
{
"object": "usage_estimate",
"period": { "from": "2026-08-01T00:00:00.000Z", "to": "2026-09-01T00:00:00.000Z" },
"schedule_version": 2,
"credits": {
"charged": 31500,
"nominal": 33500,
"beta_free": 2000,
"per_month": { "charged": 30484, "nominal": 32419, "beta_free": 1935 }
},
"requests": { "total": 3155, "unrouted": 2, "unmapped": 0 },
"by_action": [
{
"action_id": "search",
"name": "Search",
"requests": 3000,
"quantity": 3000,
"credits": 30000,
"nominal_credits": 30000,
"disposition": "charged"
},
{
"action_id": "read",
"name": "Retrieve",
"requests": 153,
"quantity": 1500,
"credits": 1500,
"nominal_credits": 1500,
"disposition": "charged"
},
{
"action_id": "screen",
"name": "Screening",
"requests": 2,
"quantity": 2,
"credits": 0,
"nominal_credits": 2000,
"disposition": "beta_free"
}
],
"unmapped": [],
"plan_for": {
"id": "growth",
"name": "Growth",
"credits_included": 100000,
"per_month_annual": 399,
"monthly": 529
},
"packs_needed": null,
"above_self_serve": false,
"offer": { "percent_off": 25, "months": 12, "price_per_month": 299.25 },
"coverage": {
"pre_cutover_unmetered_actions": ["class_lookup", "rules_lookup"],
"note": "Class and rules lookups are free reference routes today and are not written to billing_events, so any part of this window before the cutover cannot show their volume."
},
"request_id": "req_abc123"
}
Code Examples
curl "https://api.signa.so/v1/organization/usage/estimate?from=2026-08-01&to=2026-08-31" \
-H "Authorization: Bearer sig_xxxxxxxxxxxx"
import { Signa } from "@signa-so/sdk";
const signa = new Signa({ api_key: "sig_xxxxxxxxxxxx" });
const estimate = await signa.organization.usageEstimate({
from: "2026-08-01",
to: "2026-08-31",
});
import requests
resp = requests.get(
"https://api.signa.so/v1/organization/usage/estimate",
headers={"Authorization": "Bearer sig_xxxxxxxxxxxx"},
params={"from": "2026-08-01", "to": "2026-08-31"},
)
estimate = resp.json()
Errors
| Status | Type | Description |
|---|---|---|
| 400 | validation_error | from/to not given together, invalid date, from > to, to in the future, or a window wider than 92 days |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | API key lacks billing:read |
| 429 | rate_limited | Too many requests |
| 504 | timeout | The aggregate did not finish inside the read pool’s statement timeout. Narrow the window and retry — a wide window over a high-volume organization is the usual cause. |
Related Endpoints
- Get Usage Summary — daily breakdown from pre-aggregated rollups
- Get Usage — current billing period totals by endpoint type
- Get Credits — pooled credit balance