Skip to content

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.

Check both balances
curl "https://beamro.com/api/v1/billing/summary" \
  -H "x-api-key: $SALVO_API_KEY"

What each action costs

ActionCreditsCharged for
company_row1Company row returned by search, lookalike or export
person_row2Person row, including title, seniority and email status
email_reveal3Verified email address unmasked on a person row
phone_reveal10Direct phone number unmasked on a person row
ai_criterion_row1One free-text criterion evaluated against one row
deep_research10Deep research pass over one company
export_row1Row 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/interpret parses 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.

503 service_unavailable
{
  "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 402 or 503 from POST /v1/enrich/company, /v1/enrich/deep-research or GET /v1/enrich/jobs/{job_id} names the finished job in details.job_id and details.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 with job_kind: "ai_criteria". Poll GET /v1/enrich/jobs/{job_id} to collect it: the first poll that can pay charges it once and returns it as output.grid. A held grid is kept for an hour; after that, or after a restart of the service, the poll answers 410 grid_not_held and 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 402 whose details.credits_refunded says the first was returned. When the second could not be confirmed, or that refund did not go through, details.credits_taken says what was already taken — contact support@salvo.example with the x-request-id to 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.

402 payment_required
{
  "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.