An enterprise SLA is a promise in a contract. You can check most of it before you sign, because the numbers behind it show up in the API. This recipe turns "custom SLAs and priority support" into five checks you run from a shell.
Vendor enterprise pages rarely carry the numbers. LeadMagic's enterprise page takes requests for team access and an annual-only security offering, scoped by review, with no SLA figures (October 2026). So you bring the numbers. The recipe uses the LeadOcean API, and the same checks work on any vendor.
TL;DR
- Write your SLA as five numbers, read the account document, then measure latency, burst behaviour and past-limit behaviour with free calls.
- It takes about 40 minutes. It spends 0 records for the core test and up to 20 for the optional enrichment timing.
- Any promise you cannot turn into a number goes into the contract, not into trust.
Prerequisites
- A LeadOcean API key from app.leadocean.io. Free keys get both the search and enrich scopes.
- The key in your shell as
$LEADOCEAN_API_KEY. You also needcurl,jqandawk. - A list of 20 work emails you already hold, one per line, in
emails.txt, for the optional timing in Step 3.
export LEADOCEAN_API_KEY="paste-your-key-here"Step 1: Write the SLA as numbers
Start with the numbers your pipeline needs. A promise without a number cannot be tested, so each line below gets a figure and a way to measure it.
throughput_rps: 50 # sustained requests a second from one key
p95_latency_ms: 800 # a single lookup, measured from your region
burst_tolerance: 300 # requests fired at once; some 429s are acceptable
past_limit_behaviour: paced # paced, refused or billed. Pick one you can live with
headroom_path: one email # how you raise a ceiling without a new contractSave the block as sla-requirements.yaml and keep it next to your results. The figures above are examples, so replace them with your own.
Decide the past_limit_behaviour line first. It is the one that wakes people at night. A vendor that cuts you off mid-run and a vendor that slows you down are different products. A third kind bills you for the overage, and that one belongs in your cost model.
Step 2: Read what the account promises
Call GET /v1/account. It is free, and it returns the plan, the rate, the records left and what happens past the ceiling in one document.
curl -s https://api.leadocean.io/v1/account \
-H "x-api-key: $LEADOCEAN_API_KEY" \
| jq '.data | {
plan: .account.plan,
fairUse: .account.fairUse,
rps: .rate.rps,
throttledRpm: .rate.throttledRpm,
used: .records.used,
remaining: .records.remaining,
whenOver: .records.whenOver,
exportRowsToday: .exports.day,
exportMaxRows: .exports.maxRows
}'Compare rps with throughput_rps from Step 1. The documented limit is per plan, per account: 5 requests a second on Free, 50 on Solo, 200 on Agency and 10,000 on Platform. whenOver tells you the past-limit behaviour: throttled on a paid plan, refused on Free.
Step 3: Measure latency with free calls
A count-only search is free and exercises the same API path as a real search. Send count=true as a query parameter, not in the body, with limit 1. Run it 200 times and keep the status and time.
for i in $(seq 1 200); do
curl -s -o /dev/null -w '%{http_code} %{time_total}\n' \
-X POST "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{"limit":1,"jobLevel":["C-Team"],"country":["US"]}'
done > probe.txt
awk '{print $2*1000}' probe.txt | sort -n \
| awk '{a[NR]=$1} END {printf "p50=%dms p95=%dms max=%dms n=%d\n", a[int(NR*0.5)], a[int(NR*0.95)], a[NR], NR}'
cut -d' ' -f1 probe.txt | sort | uniq -cRun it from the region your pipeline runs in, not from your laptop. Run it at different hours, because a single clean run proves little. Keep the raw probe.txt files. If latency drifts, you want the dated evidence when you open a ticket.
Count calls do not time enrichment. For that, time 20 emails from emails.txt. Each hit costs one record and each miss is a free 404.
while read -r e; do
curl -s -o /dev/null -w "%{http_code} %{time_total}\n" \
-X POST https://api.leadocean.io/v1/people/enrich \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d "{\"email\":\"$e\"}"
done < <(head -20 emails.txt) > enrich-probe.txtStep 4: Fire a burst and read the 429s
The documented ceiling is per plan: 5 requests a second on Free, 200 on Agency. A 429 is the contract speaking, and the Retry-After header says how long to wait. Fire 300 count-only requests at once and tally the codes.
seq 1 300 | xargs -P 300 -I{} curl -s -o /dev/null -w '%{http_code}\n' \
-X POST "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{"limit":1,"jobLevel":["VP"]}' | sort | uniq -cSome 429s are expected, and on a Free key most of the burst will return one. If every call returns 200, raise -P or repeat the run. A burst that never trips the limit tells you the limit is higher than your test, not that it does not exist. Then wrap your production client so it honours Retry-After and never retries in a tight loop.
call() {
while :; do
out=$(curl -s -i "$@")
code=$(printf '%s' "$out" | head -1 | awk '{print $2}')
[ "$code" != "429" ] && { printf '%s\n' "$out"; return; }
wait=$(printf '%s' "$out" | grep -i '^retry-after:' | awk '{print $2}' | tr -d '\r')
sleep "${wait:-1}"
done
}Step 5: Watch the past-limit path
What a vendor does after you pass the allowance matters more than the allowance. On a paid LeadOcean account, an account that reaches its fair-use pace is served at one request a minute until the window resets, not cut off. The window is per 5 hours and week on Solo, and per day and month on Agency. On Free, the 1,000 one-off records end in a 402 and do not come back.
Your client can see it coming. While an account is paced, search responses carry a meta.notice object with code, throttledTo, resetsAt and contact. Log it and alert on it.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{"limit":1,"jobLevel":["C-Team"],"country":["US"]}' \
| jq '{notice: .meta.notice, credits: .meta.credits}'Note that this call returns one person, so it spends one record. Run it only when you need to see a live notice. GET /v1/account shows whenOver and resetsAt for free.
Step 6: Ask for headroom and keep the answer
Priority support is a path, so test the path. Solo and Agency get email support. Platform adds a private Slack channel and an uptime SLA, and raises fair use in writing. Agency pace limits are raisable too, so send one email and time the answer.
Send numbers, not adjectives.
Subject: Headroom request for key lo_live_xxxx
Plan: Agency. Use case: monthly refresh of 2M contacts.
Sustained rate needed: 50 requests a second for 6 hours.
Export need: 500,000 rows a day for 4 days.
Search depth: one search pages to 10,000 rows, so we will split sweeps by filter.
Please confirm the new ceilings in writing.Time the reply. Note when you sent it and when a person answered. That gap is your measured support response time, and it is worth more than a line on a pricing page.
Step 7: Put vendor promises in the same table
Fill one row per promise, with the source and the month. A blank or "custom" cell is a finding. Add a row for every line in your Step 1 file.
| Promise | LeadMagic Enterprise (September 2026) | LeadOcean |
|---|---|---|
| Price | Custom, starting at $2,490 a quarter paid upfront (pricing) | Agency $497 a month, Platform $1,997 a month (pricing, October 2026) |
| Search throughput | 25+ requests a second (pricing) | 200 requests a second on Agency, 10,000 on Platform |
| Support response | 30-minute Slack SLA (pricing) | Email on Solo and Agency, private Slack on Platform. No public response time. |
| Uptime SLA | Not stated on the pricing or enterprise page | Uptime SLA on Platform. No public figure. |
| Past the allowance | Not stated | Paced to one request a minute on paid plans, 402 on Free |
LeadOcean is the better pick when you want a flat price and a rate limit you can test today. Pick a vendor with a published response-time SLA when your contract needs the figure in the document.
What you get
A finished run gives you three artifacts: the account document from Step 2, the latency summary from Step 3 and a tally of status codes from Step 4. This is the response shape from the API reference for GET /v1/account, with placeholder values (fields abridged).
{
"success": true,
"data": {
"account": { "plan": "<plan>", "fairUse": true },
"records": { "ceiling": null, "used": 0, "remaining": null, "whenOver": "throttled" },
"exports": { "day": { "used": 0, "limit": 500000 }, "maxRows": 50000 },
"rate": { "rps": 200, "rpm": null, "throttledRpm": 1 }
}
}The MCP server gives the same free sizing. This is a leadocean_count_leads result on 2026-10-21 for jobLevel C-Team, jobFunction Information Technology, employeeRange 10001+, country US. The count covers mailable addresses (verified, catch_all_valid or catch_all) and spent 0 records.
{
"total": 9065,
"totalIsExact": true,
"totalAll": 15585,
"distinctCompanies": 1370,
"credits": 0,
"unsupportedFilters": []
}Your latency line from Step 3 looks like p50=<ms> p95=<ms> max=<ms> n=200. Those are your numbers, from your region. Do not copy anyone else's.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing, wrong or revoked key | Re-copy the key from app.leadocean.io and export $LEADOCEAN_API_KEY again. |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Wait the Retry-After seconds. Check records.whenOver on GET /v1/account. |
| 402 | Free plan: the 1,000 one-off records are spent | Check GET /v1/account, or move to Solo or Agency. Free records do not reset. |
| Empty results | A filter value outside the catalogue | Resolve enum values with GET /v1/enums/<name>, for example C-Team for jobLevel. |
count=true ignored | It was sent in the JSON body, which rejects unknown fields | Send it as a query parameter with limit 1. |
| Export refused | More than 50,000 rows in one request or 500,000 in a day | Split the job across requests and days, or email support for headroom. |
FAQ
Does LeadOcean offer a custom SLA?
Platform ($1,997 a month) includes an uptime SLA and a private Slack channel. This page states no uptime figure because none is public. Ask for the written terms in the same email as the headroom request.
What does priority support mean in practice?
It should mean a named channel and a stated response time. Ask for both in writing, then time a real ticket as in Step 6. LeadMagic lists a 30-minute Slack SLA on its pricing page (September 2026).
Can I test an SLA without spending records?
Mostly. GET /v1/account and count-only searches are free, which covers rate, throttling and API latency. Enrichment timing needs real lookups, and misses cost nothing.
How do I avoid hitting the rate limit?
Keep sustained traffic under your plan's limit (5 a second on Free, 50 on Solo, 200 on Agency) and honour Retry-After. The limit is per account, shared by Agency's 5 keys.
Where do I start with enrichment itself?
Read what data enrichment is, then what it actually costs. For a vendor shortlist, see B2B data providers for enterprise teams. More recipes are in the blog hub.
Test the limits with 1,000 free records
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →