curl --request GET \
--url https://api.runpulse.com/usage \
--header 'x-api-key: <api-key>'import requests
url = "https://api.runpulse.com/usage"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.runpulse.com/usage', 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.runpulse.com/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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.runpulse.com/usage"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
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.runpulse.com/usage")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.runpulse.com/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"from": "2023-11-07T05:31:56Z",
"to": "2023-11-07T05:31:56Z",
"group_by": "day",
"generated_at": "2023-11-07T05:31:56Z",
"billing": {
"billing_type": "<string>",
"credits_used": 123,
"overage_credits": 123,
"limit_exceeded": true,
"is_metered": true,
"plan_name": "<string>",
"period_start": "2023-11-07T05:31:56Z",
"period_end": "2023-11-07T05:31:56Z",
"credit_allowance": 123,
"credits_remaining": 123,
"usage_percentage": 123,
"metered_rate": 123,
"estimated_cost": 123,
"overage_cost": 123
},
"totals": {
"documents": 123,
"pages": 123,
"credits": 123
},
"by_period": [
{
"period": "2023-11-07T05:31:56Z",
"documents": 123,
"pages": 123,
"credits": 123
}
]
}Get Usage
Programmatic counterpart to the platform usage dashboard. Returns the calling organization’s current billing-period credit status plus document, page, and credit totals with a bucketed timeline over the requested window (default: the last 30 days; maximum window: 366 days).
The response is always scoped to the organization the credentials belong to. There is no way to request another organization’s usage: any organization identifier supplied by the caller is ignored, and the response contains no identifiers of any kind.
curl --request GET \
--url https://api.runpulse.com/usage \
--header 'x-api-key: <api-key>'import requests
url = "https://api.runpulse.com/usage"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://api.runpulse.com/usage', 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.runpulse.com/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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.runpulse.com/usage"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
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.runpulse.com/usage")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.runpulse.com/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"from": "2023-11-07T05:31:56Z",
"to": "2023-11-07T05:31:56Z",
"group_by": "day",
"generated_at": "2023-11-07T05:31:56Z",
"billing": {
"billing_type": "<string>",
"credits_used": 123,
"overage_credits": 123,
"limit_exceeded": true,
"is_metered": true,
"plan_name": "<string>",
"period_start": "2023-11-07T05:31:56Z",
"period_end": "2023-11-07T05:31:56Z",
"credit_allowance": 123,
"credits_remaining": 123,
"usage_percentage": 123,
"metered_rate": 123,
"estimated_cost": 123,
"overage_cost": 123
},
"totals": {
"documents": 123,
"pages": 123,
"credits": 123
},
"by_period": [
{
"period": "2023-11-07T05:31:56Z",
"documents": 123,
"pages": 123,
"credits": 123
}
]
}Overview
Retrieve your organization’s usage programmatically — the same figures shown on the platform usage dashboard. One call returns three things:billing— where your current billing period stands: plan, credit allowance, credits used and remaining, overage, and metered-cost estimates.totals— documents, pages, and credits consumed over the requested window.by_period— the same consumption bucketed byday,week, ormonth, ready to chart or feed into internal reporting.
x-api-key), and the response is always scoped to the organization that key belongs to — organization identifiers supplied in the query string are ignored, and the response contains no identifiers of any kind.
billing reflects your current billing period regardless of the requested window. totals and by_period cover exactly the from→to window.Choosing a window
- Both dates accept
YYYY-MM-DDor a full ISO 8601 datetime. - With no parameters, the window is the last 30 days.
- A date-only
tois inclusive:to=2026-07-14covers all of July 14 (UTC). - The maximum window is 366 days; longer windows return a
400. by_periodbuckets are UTC calendar periods, sorted ascending. Periods with no usage are omitted rather than returned as zero rows — pad them client-side if your charting needs continuous axes.
Response
{
"from": "2026-07-10T00:00:00+00:00",
"to": "2026-07-14T23:59:59.999999+00:00",
"group_by": "day",
"generated_at": "2026-07-15T18:04:11+00:00",
"billing": {
"plan_name": "Growth",
"billing_type": "subscription",
"period_start": "2026-07-01T00:00:00+00:00",
"period_end": "2026-08-01T00:00:00+00:00",
"credits_used": 12451.5,
"credit_allowance": 50000.0,
"credits_remaining": 37548.5,
"overage_credits": 0.0,
"usage_percentage": 24.9,
"limit_exceeded": false,
"is_metered": false,
"metered_rate": null,
"estimated_cost": null,
"overage_cost": null
},
"totals": {
"documents": 611,
"pages": 3720,
"credits": 4184.0
},
"by_period": [
{ "period": "2026-07-10T00:00:00+00:00", "documents": 130, "pages": 708, "credits": 803.0 },
{ "period": "2026-07-11T00:00:00+00:00", "documents": 136, "pages": 814, "credits": 887.5 },
{ "period": "2026-07-12T00:00:00+00:00", "documents": 136, "pages": 814, "credits": 887.5 },
{ "period": "2026-07-13T00:00:00+00:00", "documents": 111, "pages": 666, "credits": 720.0 },
{ "period": "2026-07-14T00:00:00+00:00", "documents": 98, "pages": 718, "credits": 886.0 }
]
}
billing fields
| Field | Type | Description |
|---|---|---|
plan_name | string | null | Name of your plan. |
billing_type | string | subscription, pay_as_you_go, free, or unknown. |
period_start / period_end | string | null | Billing period bounds (ISO 8601, UTC), when the plan defines them. |
credits_used | number | Credits consumed in the current billing period. |
credit_allowance | number | null | Credits included in the plan; null when unlimited. |
credits_remaining | number | null | Allowance left; null when unlimited. |
overage_credits | number | Credits consumed beyond the allowance. |
usage_percentage | number | null | Share of the allowance consumed; null when the plan has no allowance. |
limit_exceeded | boolean | Whether the allowance has been reached or exceeded. |
is_metered | boolean | Whether the plan bills per credit consumed. |
metered_rate | number | null | Price per credit. null unless is_metered is true. |
estimated_cost | number | null | Estimated period cost on metered plans with no allowance. null unless is_metered is true. |
overage_cost | number | null | Estimated cost of overage credits. null unless is_metered is true. |
null: credit_allowance on pure metered billing, and every metered pricing field whenever is_metered is false.
totals and by_period fields
| Field | Type | Description |
|---|---|---|
documents | integer | Documents processed. |
pages | integer | Pages processed. |
credits | number | Credits consumed — see Credit Usage for how each pipeline step is billed. |
period | string | Bucket start (ISO 8601, UTC). by_period entries only. |
Examples
Last 30 days at daily resolution (all defaults):curl -H "x-api-key: $PULSE_API_KEY" "https://api.runpulse.com/usage"
curl -H "x-api-key: $PULSE_API_KEY" \
"https://api.runpulse.com/usage?from=2026-06-01&to=2026-06-30&group_by=week"
import requests
usage = requests.get(
"https://api.runpulse.com/usage",
headers={"x-api-key": PULSE_API_KEY},
).json()
billing = usage["billing"]
if billing["usage_percentage"] and billing["usage_percentage"] > 80:
alert(f"{billing['credits_remaining']} credits left this billing period")
for bucket in usage["by_period"]:
print(f"{bucket['period'][:10]}: {bucket['documents']} docs, {bucket['credits']} credits")
Errors
| Status | Meaning |
|---|---|
400 | Malformed from/to, window end before start, window longer than 366 days, or unknown group_by. Details are included in the response body. |
401 | Missing or invalid API key. |
429 | Organization rate limit exceeded. |
500 | Usage aggregation failed. |
Authorizations
Query Parameters
Window start as YYYY-MM-DD or an ISO 8601 datetime. Defaults to 30 days before to.
"2026-07-10"
Window end as YYYY-MM-DD or an ISO 8601 datetime. A date-only value is inclusive — it extends to the end of that day (UTC). Defaults to the current time.
"2026-07-14"
Bucket size for the by_period timeline.
day, week, month Response
Usage summary for the calling organization
Organization usage summary: current billing-period credit status plus totals and a bucketed timeline for the requested window. Matches the figures shown on the platform usage dashboard.
Resolved window start (UTC).
Resolved window end (UTC, inclusive).
Bucket size used for by_period.
day, week, month When this summary was computed.
Where the organization's current billing period stands. Reflects the active plan and billing cycle regardless of the requested window. Fields that don't apply to the plan are null — the allowance on pure metered billing, and every metered pricing field (metered_rate, estimated_cost, overage_cost) unless is_metered is true.
Show child attributes
Show child attributes
Consumption over exactly the requested from→to window.
Show child attributes
Show child attributes
Usage bucketed by group_by, ascending. Periods with no usage are omitted rather than returned as zero rows.
Show child attributes
Show child attributes