Support & documentation
Everything you need to connect your APIs, set budgets and get alerted before you overspend.
Getting started
Create your account
APIPurse tracks what you spend on APIs such as OpenAI, Anthropic, Stripe, AWS and Twilio in one place, and warns you before you pass a budget.
- 1Open the sign-up page, enter your email and a password, tick the box to accept the Terms and Privacy Policy, and click Sign up.
- 2Open the confirmation email and click the link. If you cannot find it within a couple of minutes, check your spam folder.
- 3Log in. You will see an empty dashboard. The next step is to connect your first provider.
Reading your dashboard
The dashboard shows your total spend for the current month and one card per provider.
- The top figure is the total across all providers, converted into your display currency, with a daily bar chart below it.
- Each provider card shows spend so far, its budget, the number of requests and a progress bar. The bar turns amber when you pass your lowest alert threshold and red when you pass the highest.
- Cards reset at the start of every calendar month. The Recent activity table lists individual line items.
Connect your APIs
Connect OpenAI
APIPurse reads your organisation's cost data through an Admin API key. A regular project key cannot read costs.
- 1Ask the owner of your OpenAI organisation to create an Admin API key at platform.openai.com under Settings, Organization, Admin keys.
- 2In APIPurse, go to Settings and open Connect OpenAI. Give the connection a name, paste the key and optionally set a monthly budget and an alert threshold.
- 3Click Connect. The key is encrypted immediately and is never shown again.
- 4Usage syncs automatically every 6 hours. The first data can take up to 6 hours to appear.
Connect Anthropic
Same idea as OpenAI: you need an Admin API key, which starts with sk-ant-admin-.
- 1An organisation owner or admin creates the key at console.anthropic.com under Settings, Admin keys.
- 2In APIPurse, go to Settings, open Connect Anthropic, name the connection and paste the key.
- 3Click Connect. Usage syncs automatically every 6 hours.
Connect Stripe
APIPurse tracks Stripe's own processing fees, meaning the amount Stripe keeps from each charge. It does not track your customers' payments.
- 1In your Stripe Dashboard go to Developers, API keys and create a restricted key.
- 2Give it only the permission Balance Transactions: Read. Do not use a full secret key.
- 3In APIPurse, go to Settings, open Connect Stripe and paste the restricted key.
- 4For instant tracking, click Set up real-time webhook on your Stripe provider. Copy the URL shown into Stripe under Developers, Webhooks, Add endpoint, select the charge.succeeded event, then paste the signing secret (starts with whsec_) back into APIPurse.
Connect AWS
APIPurse reads your total AWS bill (all services combined) through Cost Explorer. Use a dedicated IAM user, never your root account.
- 1In the AWS Console go to IAM, Users, Create user (for example apipurse-readonly). Skip console access.
- 2Attach a custom policy with only the permission shown below.
- 3Open the user, go to Security credentials and create an access key. Copy the Access key ID and the Secret access key straight away, because the secret is shown only once.
- 4In APIPurse, go to Settings, open Connect AWS and paste both values.
Note: The code examples on this page are sample code for illustration and general support only, provided as is without warranty. Review, test and secure them yourself before using them in production. See section 9 of the Terms of Service.
IAM policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ce:GetCostAndUsage",
"Resource": "*"
}
]
}Connect Twilio
APIPurse reads calls, SMS and other usage-based charges through Twilio's usage API.
- 1In the Twilio Console, copy the Account SID and the Auth token from the main dashboard.
- 2In APIPurse, go to Settings, open Connect Twilio and paste both.
- 3Usage syncs automatically every 6 hours.
Add a custom or internal API
For any API that APIPurse does not connect to natively, add it manually and send usage from your own code.
- 1Go to Settings, Add a provider (manual / custom). Enter a name, choose the type custom and optionally set a budget.
- 2Copy the provider ID from the list of providers, and your personal ingest token from the box near the top of Settings.
- 3Send usage from your code, a script or a scheduled job with a request like the one below. Send it per call, per batch or on any schedule. APIPurse simply adds up what you send.
Note: The code examples on this page are sample code for illustration and general support only, provided as is without warranty. Review, test and secure them yourself before using them in production. See section 9 of the Terms of Service.
curl
curl -X POST https://www.apipurse.com/api/ingest \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_INGEST_TOKEN" \
-d '{"provider_id": "YOUR_PROVIDER_ID", "cost_usd": 0.42, "request_count": 12}'Tracking & data
Real-time trackingPro and Team plans
The connectors sync every 6 hours. For instant costs and alerts, report usage yourself right after each API call.
- Send the model name and token counts. APIPurse looks up the current price for that model and calculates the cost, so you never maintain pricing yourself.
- This works for any model in LiteLLM's price list, including Mistral, Groq, Cohere, Bedrock, Azure OpenAI and Gemini. Add a custom provider with that name and send its model name.
- Behind an API gateway or middleware? Buffer records and flush up to 1000 per request to the batch endpoint instead of one request per call.
- Your prompts and completions never pass through APIPurse. Only the final cost report is sent.
Note: The code examples on this page are sample code for illustration and general support only, provided as is without warranty. Review, test and secure them yourself before using them in production. See section 9 of the Terms of Service.
curl
curl -X POST https://www.apipurse.com/api/track/completion \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_INGEST_TOKEN" \
-d '{"provider_id": "YOUR_PROVIDER_ID", "model": "gpt-4o", "input_tokens": 512, "output_tokens": 128}'batch
curl -X POST https://www.apipurse.com/api/ingest/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_INGEST_TOKEN" \
-d '{"records": [
{"provider_id": "...", "cost_usd": 0.42, "request_count": 12},
{"provider_id": "...", "cost_usd": 0.08, "request_count": 3}
]}'SDKsPro and Team plans
Official SDKs exist for 7 languages. They remove the need to write the request yourself.
- TypeScript, Python and Ruby: wrap your OpenAI or Anthropic client once at startup and every later call is reported automatically.
- Java, C#, Go and PHP: create the client once and add one line after each completion call.
- Each package has its own README with copy-and-paste examples.
| Language | After setup | Install |
|---|---|---|
| TypeScript | Automatic: wrap your client once | npm install @apipurse/sdk |
| Python | Automatic: wrap your client once | pip install apipurse-sdk |
| Ruby | Automatic: wrap your client once | gem install apipurse-sdk |
| Java | One line after each completion call | io.github.yelmorab:apipurse-sdk:0.1.0 (Maven) |
| C# / .NET | One line after each completion call | dotnet add package Apipurse.Sdk |
| Go | One line after each completion call | go get github.com/yelmorab/apipurse-sdks/sdk-go/apipurse@v0.1.0 |
| PHP | One line after each completion call | composer require apipurse/apipurse-sdk |
›TypeScript
import OpenAI from "openai";
import { APIPurse, wrapOpenAI } from "@apipurse/sdk";
const apipurse = new APIPurse({
ingestToken: process.env.APIPURSE_INGEST_TOKEN!,
providerId: process.env.APIPURSE_PROVIDER_ID!,
baseUrl: "https://www.apipurse.com",
});
// Wrap the client ONCE, at startup:
const openai = wrapOpenAI(new OpenAI(), apipurse);
// Every call is now tracked automatically, nothing else to add:
const completion = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
});
// Anthropic works the same way:
// import { wrapAnthropic } from "@apipurse/sdk";
// const anthropic = wrapAnthropic(new Anthropic(), apipurse);›Python
import os
from openai import OpenAI
from apipurse import APIPurse, wrap_openai
apipurse = APIPurse(
ingest_token=os.environ["APIPURSE_INGEST_TOKEN"],
provider_id=os.environ["APIPURSE_PROVIDER_ID"],
base_url="https://www.apipurse.com",
)
# Wrap the client ONCE, at startup:
client = wrap_openai(OpenAI(), apipurse)
# Every call is now tracked automatically, nothing else to add:
completion = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
)
# Anthropic works the same way:
# from anthropic import Anthropic
# from apipurse import wrap_anthropic
# client = wrap_anthropic(Anthropic(), apipurse)›Ruby
require "apipurse"
require "openai"
apipurse = Apipurse::Client.new(
ingest_token: ENV["APIPURSE_INGEST_TOKEN"],
provider_id: ENV["APIPURSE_PROVIDER_ID"],
base_url: "https://www.apipurse.com"
)
# Wrap the client ONCE, at startup:
client = Apipurse::WrapOpenAI.call(OpenAI::Client.new, apipurse)
# Every call is now tracked automatically, nothing else to add:
completion = client.chat.completions.create(
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }]
)
# Anthropic works the same way:
# client = Apipurse::WrapAnthropic.call(Anthropic::Client.new, apipurse)›Java
import com.apipurse.sdk.APIPurse;
// Create the client ONCE, at startup:
APIPurse apipurse = new APIPurse(
System.getenv("APIPURSE_INGEST_TOKEN"),
System.getenv("APIPURSE_PROVIDER_ID"),
"https://www.apipurse.com",
true // silent: never throws if APIPurse is unreachable
);
// Right after each of your own completion calls, add ONE line:
ChatCompletion completion = client.chat().completions().create(params);
apipurse.trackCompletion(
completion.model(),
completion.usage().promptTokens(),
completion.usage().completionTokens()
);›C# / .NET
using Apipurse.Sdk;
// Create the client ONCE, at startup:
var apipurse = new ApiPurse(
ingestToken: Environment.GetEnvironmentVariable("APIPURSE_INGEST_TOKEN")!,
providerId: Environment.GetEnvironmentVariable("APIPURSE_PROVIDER_ID")!,
baseUrl: "https://www.apipurse.com"
);
// Right after each of your own completion calls, add ONE line:
ChatCompletion completion = await client.CompleteChatAsync(messages);
await apipurse.TrackCompletionAsync(
completion.Model,
completion.Usage.InputTokenCount,
completion.Usage.OutputTokenCount
);›Go
import (
"context"
"os"
"github.com/yelmorab/apipurse-sdks/sdk-go/apipurse"
)
// Create the client ONCE, at startup:
client := apipurse.New(os.Getenv("APIPURSE_INGEST_TOKEN"), os.Getenv("APIPURSE_PROVIDER_ID"))
client.BaseURL = "https://www.apipurse.com"
// Right after each of your own completion calls, add ONE call:
client.TrackCompletion(context.Background(), apipurse.TrackCompletionInput{
Model: resp.Model,
InputTokens: resp.Usage.PromptTokens,
OutputTokens: resp.Usage.CompletionTokens,
})›PHP
<?php
use Apipurse\ApiPurse;
// Create the client ONCE, at startup:
$apipurse = new ApiPurse(
ingestToken: getenv("APIPURSE_INGEST_TOKEN"),
providerId: getenv("APIPURSE_PROVIDER_ID"),
baseUrl: "https://www.apipurse.com"
);
// Right after each of your own completion calls, add ONE line:
$completion = $client->chat()->completions()->create($params);
$apipurse->trackCompletion(
$completion->model,
$completion->usage->promptTokens,
$completion->usage->completionTokens
);Note: The code examples on this page are sample code for illustration and general support only, provided as is without warranty. Review, test and secure them yourself before using them in production. See section 9 of the Terms of Service.
Reports
The Reports page lists your raw usage records, filtered by date range and provider.
- 1Open Reports in the sidebar and choose a date range and, optionally, a provider.
- 2Costs appear in your display currency. The original amount is shown underneath when it differs.
Export your data and connect a BI toolPro and Team plans
Download your usage as a file or pull it into a reporting tool.
- 1On the Reports page, click Download CSV to export everything that matches your filters. The file contains the original and the converted amounts.
- 2To feed Power BI, Tableau, Looker or a similar tool, use the web or JSON data source with the URL below and an Authorization header set to Bearer YOUR_INGEST_TOKEN.
- 3Add from, to or provider_id to the URL to filter on the server. Refresh in your tool whenever you want the latest numbers.
Note: The code examples on this page are sample code for illustration and general support only, provided as is without warranty. Review, test and secure them yourself before using them in production. See section 9 of the Terms of Service.
BI / export URL
https://www.apipurse.com/api/export?format=json&from=2026-01-01&to=2026-01-31Budgets & alerts
Budgets and alerts
Every provider can have a monthly budget in USD and one or more alert thresholds, for example 50%, 80% and 100%.
- 1Go to Settings, Your providers, and click Set budget (or Edit budget) next to the provider.
- 2Enter the monthly limit and choose one or more thresholds. Click Clear budget to remove a budget again.
- 3When your spend for the calendar month crosses a threshold, you receive an email and the card on your dashboard turns amber or red.
- Each threshold fires at most once per month, so you are not warned every hour.
- Budgets are always set in USD. A provider that bills in another currency is converted at the day's exchange rate before comparing.
- On the Team plan, alerts are also posted to Slack, and every team member gets the email.
Budgets per API keyPro and Team plans
Split one provider by team, project or environment by giving each its own budget on top of the overall one.
- 1In Settings, click Add key-scoped budget next to the provider and type a label of your choice, such as prod, staging or team-a.
- 2Set the monthly limit and threshold for that label.
- 3Send the same label as api_key_label when you report usage, as shown below.
Note: The code examples on this page are sample code for illustration and general support only, provided as is without warranty. Review, test and secure them yourself before using them in production. See section 9 of the Terms of Service.
curl
curl -X POST https://www.apipurse.com/api/ingest \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_INGEST_TOKEN" \
-d '{"provider_id": "YOUR_PROVIDER_ID", "cost_usd": 0.42, "api_key_label": "prod"}'Spend-spike alertsPro and Team plans
Once a day APIPurse compares each provider's spend from yesterday with its normal 7-day average, even if you set no budget.
- If yesterday was at least 3 times the usual level and the amounts are large enough to matter, you receive an email.
- This catches runaway prompt loops and leaked keys early, usually within a day.
- You get at most one spike email per provider per day.
Alert History
Alert History lists every budget and spend-spike alert sent for your account.
- See when each alert was sent, for which provider, of what kind, and whether it reached you by email and by Slack.
- A checkmark means delivered, a dash means not sent, and n/a means the alert is older than per-channel tracking.
- On Pro and Team you can download the whole log as CSV.
Slack alertsTeam plan
Post every budget and spend-spike alert to a Slack channel as well as by email.
- 1At api.slack.com/apps, create an app, enable Incoming Webhooks and choose Add New Webhook to Workspace. Copy the webhook URL.
- 2In APIPurse, go to Settings and paste the URL into the Slack field.
- 3Click Send test to confirm the message arrives in your channel.
Account & team
Invite your teamTeam plan
On the Team plan you can invite as many colleagues as you like at no extra cost. They get the same access as you.
- 1Go to Settings, Team, and enter a colleague's email.
- 2They receive an email with a sign-in link, set a password and immediately see the same providers, budgets, alerts and settings.
- 3If an invite link expired or was already used, remove the person and send a fresh invite. The newest email always works.
Display currency
Choose the currency in which the dashboard shows your totals.
- 1Go to Settings and pick a currency under Display currency.
- 2Every provider's spend stays stored in its real currency. The dashboard converts it for display using a daily exchange rate.
Change the language
APIPurse is available in English, Dutch, French, German, Spanish, Portuguese and Japanese.
- 1Open the language menu at the bottom of the sidebar. On the home page it is in the header.
- 2Your choice is saved straight away and also decides the language of your alert emails.
Plans, billing and cancelling
Manage your subscription under Settings, in the plan section.
- Free: 1 provider, 30 days of history and budget alerts by email.
- Pro (59 euro per month): unlimited providers, 365 days of history, real-time tracking, spend-spike alerts, per-key budgets and export.
- Team (299 euro per month): everything in Pro plus unlimited history, Slack alerts and unlimited team members.
- To upgrade, change plan or cancel, click Manage billing. This opens the billing portal of our payment provider.
- Cancelling takes effect at the end of the current billing period, so you keep access until then.
- For refunds and your right of withdrawal, see section 5 of the Terms of Service.
Frequently asked questions
›I connected a provider but I see no data yet.
Connected providers sync every 6 hours, so the first data can take a while. Data you send yourself through the ingest, batch or real-time endpoints appears immediately.
›Is APIPurse really real-time?
Usage you push yourself, and Stripe with the webhook set up, is real-time. The OpenAI and Anthropic connectors check every 6 hours, and the providers do not finalise a day's cost instantly either. Use real-time tracking if instant alerts matter.
›Why does cost data for the last day or two sometimes change?
OpenAI, Anthropic and Stripe finalise costs after the fact. APIPurse re-reads the last 8 days on every sync so the numbers stay accurate.
›Is my API key safe?
Keys are encrypted before they are stored and are never shown again after you paste them. If you suspect a key was exposed, revoke it with the provider itself. Removing it from APIPurse does not invalidate it.
›Do you read my prompts or customer data?
No. APIPurse only receives cost, token-count and amount figures. Your prompts and completions go straight to your provider.
›Can I remove a provider?
Yes. In Settings, find it under Your providers and choose Remove. This deletes its usage history and budget.
›Is old usage data ever deleted?
Data older than 90 days is rolled up into one summary line per provider per day. Totals stay exactly the same, only per-call detail is condensed.
›Can a team member see everything I see?
Yes, on the Team plan. Members share providers, budgets, alerts and settings. Managing the subscription and inviting or removing members stays with the owner.
›How do I cancel my subscription?
Go to Settings, click Manage billing and cancel there. You keep access until the end of the billing period you already paid for.
›Can I get a refund?
See section 5 of the Terms of Service. Consumers in the EU have a 14-day right of withdrawal. Write to support and we will help.
›Where is my data stored and who processes it?
In the EU (Frankfurt), with a few providers for hosting, email and monitoring. The Privacy Policy lists them all, and businesses can use our Data Processing Agreement.
›How do I delete my account and data?
Email privacy@apipurse.com from your account address. We answer within one month. Billing records are kept for the period required by tax law.
Troubleshooting
ProblemUnauthorized when connecting a provider.
SolutionCheck you use the right kind of key. OpenAI and Anthropic need an Admin key, not a regular key. For Stripe, the restricted key needs the permission Balance Transactions: Read.
ProblemI did not receive an alert email.
SolutionCheck your spam folder and mark the message as not spam. Each threshold fires only once per month, so a threshold that already fired will not repeat. Alert History shows whether the email was sent.
ProblemThe ingest request returns an error.
SolutionCheck the Authorization header (Bearer, then your ingest token), that provider_id is the ID from Settings, and that the body is valid JSON with cost_usd as a number.
ProblemA Slack alert did not arrive but the email did.
SolutionUse Send test in Settings. If it fails, create a new Incoming Webhook in Slack and save it again. Alert History shows the status per channel.
ProblemMy budget percentage looks wrong or shows a missing rate.
SolutionBudgets are in USD and other currencies are converted with a daily exchange rate. If a rate has not synced yet, the card says so. It resolves itself after the next daily sync.
ProblemThe confirmation or invite email did not arrive.
SolutionCheck spam. For a team invite, remove the person in Settings and send a new invite. The newest email always works.
ProblemMy plan did not change after paying.
SolutionRefresh the page or log out and in again. If the plan is still wrong after a few minutes, email support with your account address.
ProblemReal-time tracking returns a plan error.
SolutionReal-time tracking, spend-spike alerts, per-key budgets and export need Pro or Team. Upgrade under Settings.
Still need help?
Write to us and include your account email and a short description of what you see. Please never send API keys or passwords.
General support: support@apipurse.com
Privacy and data requests: privacy@apipurse.com
We usually reply within one to two business days.