curl --request GET \
--url https://www.getsurfaced.ai/api/partner/usage \
--header 'Authorization: Bearer <token>'import requests
url = "https://www.getsurfaced.ai/api/partner/usage"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://www.getsurfaced.ai/api/partner/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://www.getsurfaced.ai/api/partner/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 => [
"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://www.getsurfaced.ai/api/partner/usage"
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://www.getsurfaced.ai/api/partner/usage")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getsurfaced.ai/api/partner/usage")
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{
"period": {
"month": "2026-07",
"from": "2026-07-01T00:00:00.000Z",
"to": "2026-08-01T00:00:00.000Z"
},
"scans": {
"total": 42,
"completed": 39,
"failed": 3,
"by_tier": {
"basic": 30,
"full": 12
}
},
"quota": {
"monthly_scan_quota": 500,
"effective_quota": 500,
"credits": 0,
"included": 500,
"used": 42,
"remaining": 458,
"overage_hard_cap_scans": 100,
"prorated": false
},
"prorated": false,
"rate_limit_per_hour": 200,
"billed_cents": 8400,
"billing": {
"base_fee_cents": 8400,
"included_scans": 42,
"overage_scans": 0,
"overage_cents": 0,
"billed_cents": 8400
}
}{
"error": "Invalid month — must be YYYY-MM",
"code": "invalid_month"
}{
"error": "Unauthorized",
"code": "unauthorized"
}{
"error": "partner_suspended",
"code": "partner_suspended"
}{
"error": "Rate limited",
"code": "rate_limited"
}{
"error": "not_enabled",
"code": "not_enabled"
}Get monthly usage, quota, and billing
Usage rollup for one UTC calendar month: scan counts (total/completed/failed, by tier), remaining quota headroom, this partner’s rate limit, and the amount billed for the period. scans.total — and therefore quota.used — excludes failed scans: failed scans are not billed and do not count toward the quota. The monthly quota itself is soft (informational only, never blocks requests) unless the partner also has quota.overage_hard_cap_scans configured, in which case requests are hard-rejected once usage reaches the quota plus that cap. Defaults to the current in-progress month when ?month is omitted.
curl --request GET \
--url https://www.getsurfaced.ai/api/partner/usage \
--header 'Authorization: Bearer <token>'import requests
url = "https://www.getsurfaced.ai/api/partner/usage"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://www.getsurfaced.ai/api/partner/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://www.getsurfaced.ai/api/partner/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 => [
"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://www.getsurfaced.ai/api/partner/usage"
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://www.getsurfaced.ai/api/partner/usage")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getsurfaced.ai/api/partner/usage")
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{
"period": {
"month": "2026-07",
"from": "2026-07-01T00:00:00.000Z",
"to": "2026-08-01T00:00:00.000Z"
},
"scans": {
"total": 42,
"completed": 39,
"failed": 3,
"by_tier": {
"basic": 30,
"full": 12
}
},
"quota": {
"monthly_scan_quota": 500,
"effective_quota": 500,
"credits": 0,
"included": 500,
"used": 42,
"remaining": 458,
"overage_hard_cap_scans": 100,
"prorated": false
},
"prorated": false,
"rate_limit_per_hour": 200,
"billed_cents": 8400,
"billing": {
"base_fee_cents": 8400,
"included_scans": 42,
"overage_scans": 0,
"overage_cents": 0,
"billed_cents": 8400
}
}{
"error": "Invalid month — must be YYYY-MM",
"code": "invalid_month"
}{
"error": "Unauthorized",
"code": "unauthorized"
}{
"error": "partner_suspended",
"code": "partner_suspended"
}{
"error": "Rate limited",
"code": "rate_limited"
}{
"error": "not_enabled",
"code": "not_enabled"
}Authorizations
Partner API key as a Bearer token: Authorization: Bearer gsk_live_.... Live keys (gsk_live_) run real scans; test keys (gsk_test_) run request validation then return deterministic sandbox mocks (sandbox: true, nothing persisted, no rate-limit consumption). Keys are issued per partner and are revokable.
Query Parameters
Response
Usage summary for the requested (or current) month.
Per-partner usage rollup for one UTC calendar month — scan counts, quota headroom, and the amount billed for the period. scans.total excludes failed scans (failed scans are not billed and do not count toward the quota) and is the same figure used to evaluate the monthly quota, so quota.used always equals scans.total. Billing is base-fee-plus-overage: a partner with a configured monthly allowance (quota.monthly_scan_quota) is charged a monthly base fee plus a metered rate for scans beyond the allowance, counted chronologically by scan creation time within the period; a partner with no allowance configured is billed flat per scan at the same per-surface-package rate, with no base fee. See billing for the full split.
Only scans you requested through this API are counted. If you also send traffic to Surfaced through a referral link, the signups attributed to you are NOT partner-API scans: they do not appear in GET /api/partner/scans, they do not consume your monthly allowance, and they are never billed to you. Referral attribution and API usage are separate ledgers on purpose — one is credit for traffic you sent, the other is what you asked us to run.
True when this period is the partner's first (activation) period, in which case the included allowance and the base fee are scaled by the fraction of the month remaining from activation. Mirrored inside quota for convenience, but authoritative here: quota is null for a partner with no configured allowance, and such a partner can still have a prorated billing.base_fee_cents.