Examples use fictional data. Every company, person, address and count in them is invented, and their domains use the reserved .example TLD.
Getting started
Credits & metering
Data costs credits. Sending costs cash from a wallet. They are separate balances on purpose, so a runaway export can never stop your campaigns mid-sequence.
Two balances
Credits meter the data platform — every row you look at, enrich or export. 100 credits cost one dollar, and they arrive with a plan or a top-up. The wallet meters Autopilot: 3 cents per email actually delivered to a mailbox, nothing for drafts, retries or bounces. New workspaces start with $30 on the wallet — about 1,000 sent emails.
curl "https://beamro.com/api/v1/billing/summary" \
-H "x-api-key: $SALVO_API_KEY"What each action costs
| Action | Credits | Charged for |
|---|---|---|
company_row | 1 | Company row returned by search, lookalike or export |
person_row | 2 | Person row, including title, seniority and email status |
email_reveal | 3 | Verified email address unmasked on a person row |
phone_reveal | 10 | Direct phone number unmasked on a person row |
ai_criterion_row | 1 | One free-text criterion evaluated against one row |
deep_research | 10 | Deep research pass over one company |
export_row | 1 | Row written into a CSV, XLSX or JSON export |
Counts are charged on rows returned, not rows matched — a query that reports a total of 4,000 and returns 25 rows costs 25 credits. Responses that spend credits echo the amount in credits_charged so you can reconcile without a second call.
What is free
- Segment, industry and geography stats —
/v1/segments,/v1/industries,/v1/geo. - Query interpretation:
/v1/search/interpretparses language into filters without touching a row. - Everything about your own workspace — campaigns, leads, threads, analytics, billing, webhooks.
- Listing the people at a company —
/v1/companies/{company_id}/people— with email and phone masked; revealing an email is a people search. - Totals. Counting how large a segment is never costs credits; reading the rows does.
When billing cannot confirm
A paid result is handed over only once its charge is confirmed. When the billing service does not confirm a charge, a paid endpoint answers 503 service_unavailable and delivers nothing — no rows, no file, no research. The message makes no “nothing was charged” promise: a charge whose answer was lost may still have reached the ledger, where it is reconciled. Retry shortly.
{
"error": {
"code": "service_unavailable",
"message": "The billing service did not confirm the charge, so the result was not delivered. Try again shortly.",
"details": {
"job_id": "job_6r2k9m0v4x8p1t5w7z",
"job_kind": "company_profile"
}
}
}- Enrichment: the work is already done. A
402or503fromPOST /v1/enrich/company,/v1/enrich/deep-researchorGET /v1/enrich/jobs/{job_id}names the finished job indetails.job_idanddetails.job_kind. Top up if you need to, then poll that job — it is charged once and its output returned. Posting again starts, and bills, a new job. - AI-criteria grids: a grid whose charge is refused (
402) or not confirmed (503) is held, and the error names it withjob_kind: "ai_criteria". PollGET /v1/enrich/jobs/{job_id}to collect it: the first poll that can pay charges it once and returns it asoutput.grid. A held grid is kept for an hour; after that, or after a restart of the service, the poll answers410 grid_not_heldand charges nothing. - People search charges two lines (revealed emails, then bare profiles), and delivers nothing unless both go through. When the second is refused, the answer is a
402whosedetails.credits_refundedsays the first was returned. When the second could not be confirmed, or that refund did not go through,details.credits_takensays what was already taken — contact support@salvo.example with thex-request-idto have it returned.
Running out
A request that would overspend is rejected whole — Salvo never returns a partial page and bills you for it. The error names the shortfall so a job can top up and resume.
{
"error": {
"code": "payment_required",
"message": "This export needs 12,000 credits; the workspace has 3,410.",
"details": {
"required": 12000,
"balance": 3410,
"shortfall": 8590,
"kind": "export_row"
}
}
}A search, a lookalike or a company profile the balance cannot pay for is refused the same way: the rows are withheld, not trimmed to what the credits would cover, and nothing is charged for them. details.required is what the refused charge needed — 25 credits for a page of 25 companies — and details.balance what the workspace had.
Subscribe to billing.wallet_low to be told before that happens — see webhooks.