docs get started
Credits
What costs credits, plans and rollover, expiry, dry runs, 402, and idempotency.
Credits are prepaid. Sourcing spends them. Outreach does not: a connected account is €49 per month.
Prices
| Action | Credits | Confirm |
|---|---|---|
| Lookups, intents, search plans, seen register, lists, usage, events | 0 | no |
| Lead returned by raw search or a run (a page holds up to 25; empty is free) | 1 | yes |
| Live profile, found | 2 | yes |
| Cached profile, a profile that does not exist, or a suppressed person | 0 | yes, then no charge |
| Name + company match with exactly one person | 1, once | yes |
| Live company lookup | 1 | yes |
| Company lookup for an unknown company, a cache hit, or a known company | 0 | yes, then no charge |
| Found email or phone (sourcing add-on) | 25 | yes, and only when a contact is found |
| Contact lookup with nothing found, or a stored contact | 0 | yes |
| Outreach sends | 0 | yes, and not billed in credits |
A lead is charged once per workspace, so the same person is free the next time a search returns them. There is no per-page fee, and an empty page costs nothing. A cached profile is free. A profile that no longer exists is free. A suppressed person is not fetched and is not charged. A company lookup is free when the company is unknown. Personal email and phone are a sourcing add-on: 25 credits when a contact is found, and a miss is free. The lookup runs only after confirm.
Reading is always free: GET /v1/people/{profile_id} serves your cache and never charges, and lookups, intents, search plans, the seen register, lists, usage, and events cost nothing.
Plans and rollover
A monthly plan grants credits at the start of every billing cycle, once the invoice is paid.
| Plan | Credits each month | Price |
|---|---|---|
| Starter | 5,000 | €49 / month |
| Growth | 25,000 | €149 / month |
| Scale | 125,000 | €399 / month |
A cycle grant is added when the invoice total is at least that plan's monthly price. If the invoice has no total, the subtotal is used, then the amount paid. A Stripe customer balance can lower the amount paid, even to zero, without skipping the grant. A total of zero, including a coupon that zeroes the invoice, grants nothing. Growth and Scale at their current prices still receive the full monthly credits. An older invoice above the current price still grants as well.
Every grant is its own bucket with a source and an expiry:
| Source | Expires |
|---|---|
plan | At the end of the cycle that granted it, plus 2 more cycles (3 in total) |
topup | 12 months after purchase |
free | 30 days after the signup grant |
admin | Never, unless support sets a date |
refund | Goes back into the bucket the charge came from. If that bucket has expired, a new bucket that never expires |
legacy | Never. A balance carried over from before buckets existed |
A charge spends the bucket that expires soonest first, then the next one. Credits that never expire are spent last. The worker expires buckets once a minute, and each expiry writes one credit_expiry row to the ledger. Expired credits are not usage and do not count toward a daily cap.
An upgrade mid-cycle adds the monthly difference times the share of the cycle that is left, once that proration invoice is paid. The credits are plan credits with the same expiry as the current cycle. A downgrade takes nothing back. The lower amount applies from the next invoice. A plan change that is not paid does not add credits.
GET /v1/billing/balance returns the balance by source, the live buckets in the order they are spent, and the expiries ahead. GET /v1/usage and the MCP tool get_account_overview include the same summary under credits. GET /v1/billing/plans is public and returns the plans and rules.
POST /v1/billing/subscriptions with { "plan": "growth" } starts a subscription checkout. POST /v1/billing/subscription/plan switches plan with proration. Both return mode: "unconfigured" on a server without payments set up.
Top-up pack
One pack, paid once by card at checkout. It costs more per credit than a monthly plan. Top-up credits expire after 12 months:
| Pack | Credits | Price |
|---|---|---|
| Top-up | 7,500 | €99 |
POST /v1/billing/checkout with { "pack": "topup" } returns a checkout URL, or mode: "unconfigured" on a server without payments set up. Credits are granted when the payment succeeds, never in that mode. The checkout saves the card so it can be charged again off-session.
Auto-refill buys that same pack when the balance falls below a threshold you set. You also set a monthly cap on the number of refills and on the euro amount. GET /v1/billing/auto-refill reads the settings. PUT /v1/billing/auto-refill turns it on or changes the caps. DELETE /v1/billing/auto-refill turns it off and keeps the card. The MCP tools are get_auto_refill and set_auto_refill. A customer-bound key cannot use them. Credits are added only after the off-session payment succeeds. If the card is declined or needs authentication, auto-refill turns off and the workspace email is notified.
Estimate, then confirm
Every call that spends accepts ?dry_run=true: raw search, people fetch and match, contact lookups, company resolution, runs, and extending a run. A dry run is free and returns an estimate (credits_min, credits_max, requires_confirm: true). Omit dry_run and send an Idempotency-Key header to execute; without the header the call is 400 idempotency_key_required.
MCP tools do the same with confirm=true. A repeated confirmed call with the same arguments replays the first answer.
402 insufficient_credits means stop. Add credits, then retry. A 402 is not stored on the idempotency key, so the retry with the same key can succeed. 402 daily_credit_cap_reached means a key or customer cap is spent for today; see Rate limits.
The same key and body within 24 hours returns the original response and does not charge again. The same key with a different body is 409 idempotency_key_reused. A key whose first request is still running is 409 idempotency_in_progress with Retry-After.
#!/usr/bin/env bash
set -euo pipefail
DOMAIN="${RECRUITMCP_DOMAIN:-recruitmcp.com}"
BASE="${RECRUITMCP_BASE:-https://api.${DOMAIN}}"
MCP="${RECRUITMCP_MCP:-https://mcp.${DOMAIN}/mcp}"
WS=$(curl -fsS -X POST "$BASE/v1/workspaces" -H 'content-type: application/json' -d '{"name":"Northwind Search","email":"ada@northwind.example"}')
KEY=$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).api_key)' "$WS")
BODY='{"job_description":"Senior backend engineer in Gent, Belgium. Go, 5+ years.","target":40,"budget":{"max_credits":10}}'
ONE=$(curl -fsS -X POST "$BASE/v1/runs" -H "authorization: Bearer $KEY" -H 'content-type: application/json' -H 'idempotency-key: rerun-gent' -d "$BODY")
BAL1=$(curl -fsS "$BASE/v1/workspace" -H "authorization: Bearer $KEY")
TWO=$(curl -fsS -X POST "$BASE/v1/runs" -H "authorization: Bearer $KEY" -H 'content-type: application/json' -H 'idempotency-key: rerun-gent' -d "$BODY")
BAL2=$(curl -fsS "$BASE/v1/workspace" -H "authorization: Bearer $KEY")
node -e 'const [one,two,a,b]=process.argv.slice(1).map((v)=>JSON.parse(v)); if(!one.run?.id||one.run.id!==two.run?.id) process.exit(1); if(a.balance_credits!==b.balance_credits) process.exit(2);' "$ONE" "$TWO" "$BAL1" "$BAL2"
Profile cache TTL is 30 days. Company cache TTL is 180 days.
GET /v1/usage?group_by=customer (or day, purpose, run, api_key) splits spend for reporting.
Reference: API reference schemas Estimate and Cost.