Developers

Sell our services from your own platform.

Two APIs, one key, one balance. Numbers speak the SMS-Activate protocol, SMM speaks the standard panel protocol - so in most cases you point existing code at us and it just works. Top up in Mobile Money and resell at your own prices.

v1  SMS numbers v2  SMM services 230  countries SMS-Activate  compatible 0  integration fee

Getting started

Three steps, and none of them need us to approve you.

01

Get your keys

Create an account and open API keys. Both are already there — one for numbers, one for SMM.

02

Top up

Fund the balance with MTN Mobile Money or Orange Money, from 2,500 XAF. API orders spend the same balance as the website.

03

Call it

One HTTPS request. No SDK to install, no OAuth dance, no sandbox key to swap out later.

Your first call — what is my balance?
curl "https://kamiverify.com/api/v2" \
  -d "key=YOUR_API_KEY" \
  -d "action=balance"

# {"balance":"12.4400","currency":"USD"}

Authentication

You have two keys, not one. A different key opens each API:

api_keyv1, SMS numbers. Your SMS key. Works on /api/v1 and /stubs/handler_api.php.
keyv2, SMM services. Your SMM key. Works on /api/v2.

They are deliberately separate. You can give a developer or a child panel access to your SMM catalogue without handing over the ability to spend your balance on numbers, and you can rotate one after a leak without breaking the other integration.

A key only opens its own API. Presenting the SMM key to /api/v1 fails exactly as an unknown key would, and the reverse is true too — that is the whole point of having two.

Both live on your API keys page, with a button to replace either one. There is no signature and no token to refresh.

v2 expects a POST form field. v1 accepts GET or POST — the SMS-Activate convention is GET, and most client libraries use it. Be aware that a key in a URL ends up in server logs, browser history and referrer headers, so prefer POST wherever your library allows it.

Your key is your balance. Anyone holding it can spend every franc on your account. Keep it on your server, never in a mobile app, never in browser JavaScript, never in a public repository. If it leaks, press Generate API key again — the old one stops working the moment the new one is made.

Balance and pricing

API orders and website orders draw on the same balance. There is no separate developer wallet to keep topped up, and no minimum monthly spend.

Balances are held in USD and converted at a fixed 611 XAF to the dollar. The rate does not move between your top-up and your order, so a price quoted by the API is the price charged.

You set your own prices for your own customers. What you charge them is between you and them — we bill you the API price and nothing else. There is no revenue share and no per-call fee.

Insufficient balance fails the order, it does not queue it. An add or getNumber call against an empty balance returns an error immediately. Poll balance on a schedule and top up before you run dry — an order that fails at 2am is a customer you lose.

v1 — SMS numbers

Rent a real SMS-capable number in any of 230 countries, read the code it receives, and release it. The whole lifecycle is usually under two minutes.

v1 speaks the SMS-Activate protocol, not JSON. If you have integrated V1, or anything in that family before, this will already be familiar: the credential is api_key, replies are plain colon-delimited strings like ACCESS_NUMBER:880412:237650112233, and setStatus takes numbers rather than words. Three actions return JSON instead — that inconsistency is in the protocol itself, and we copy it so existing client libraries keep working.

Base URL  https://kamiverify.com/api/v1

The conventional path https://kamiverify.com/stubs/handler_api.php reaches exactly the same handler. Most SMS-Activate client libraries hard-code that path, so pointing one at KamiVerify is usually a one-line hostname change.

GET or POST/api/v1 · action=getBalanceWhat is on the account
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal getBalance.

Replies ACCESS_BALANCE:12.44.

GET or POST/api/v1 · action=getCountriesCountries with stock
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal getCountries.

Replies JSON: {"18":{"id":18,"eng":"Cameroon"}}.

GET or POST/api/v1 · action=getNumbersStatusHow many numbers are free
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal getNumbersStatus.
countryintegerRestrict to one country.

Replies JSON keyed service_country: {"wa_18":"12"}.

GET or POST/api/v1 · action=getPricesPrices and stock
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal getPrices.
countryintegerRestrict to one country.
servicestringRestrict to one service.

Replies JSON: {"18":{"wa":{"cost":0.31,"count":12}}}.

GET or POST/api/v1 · action=getNumberRent a number
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal getNumber.
servicerequiredstringService code, e.g. wa for WhatsApp, tg for Telegram.
countryintegerCountry id. Omit, leave empty, or send any to take the cheapest anywhere.
maxPricedecimalRefuse the rental above this price.

Replies ACCESS_NUMBER:880412:237650112233 — the id first, then the number. Keep that id; every later call needs it.

GET or POST/api/v1 · action=getStatusHas the code arrived?
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal getStatus.
idrequiredintegerThe id from getNumber.

Replies STATUS_WAIT_CODE, then STATUS_OK:438201 once the code lands, or STATUS_CANCEL if the rental ended.

GET or POST/api/v1 · action=setStatusMove the rental on
ParameterTypeWhat it is
api_keyrequiredstringYour API key.
actionrequiredstringThe literal setStatus.
idrequiredintegerThe id from getNumber.
statusrequiredinteger1 ready · 3 ask for another code · 6 finish · 8 cancel and refund.

Replies ACCESS_READY, ACCESS_RETRY_GET, ACCESS_ACTIVATION or ACCESS_CANCEL respectively.

A full rental, start to finish

Rent a WhatsApp number in Cameroon
# 1. rent it
curl "https://kamiverify.com/api/v1?api_key=KEY&action=getNumber&service=wa&country=18"
# ACCESS_NUMBER:880412:237650112233

# 2. poll every 5s
curl "https://kamiverify.com/api/v1?api_key=KEY&action=getStatus&id=880412"
# STATUS_WAIT_CODE
# STATUS_OK:438201

# 3. finish (or status=8 to cancel and be refunded)
curl "https://kamiverify.com/api/v1?api_key=KEY&action=setStatus&id=880412&status=6"
# ACCESS_ACTIVATION

Every reply v1 can give you

ACCESS_NUMBER:id:phoneRented. The id comes first.
STATUS_WAIT_CODENo code yet. Keep polling.
STATUS_OK:codeThe code arrived. Stop polling.
STATUS_CANCELCancelled, expired, or already finished.
ACCESS_READYstatus=1 accepted.
ACCESS_RETRY_GETstatus=3 accepted — another code requested.
ACCESS_ACTIVATIONstatus=6 accepted — rental closed.
ACCESS_CANCELstatus=8 accepted — refunded to your balance.

And every error

BAD_KEYMissing, wrong, or the account is suspended.
BAD_ACTIONNo such action.
BAD_SERVICENo service was sent.
BAD_STATUSNot 1, 3, 6 or 8 — or the rental has already ended.
NO_NUMBERSNothing in stock for that pair. Try another country.
NO_BALANCETop up. Nothing was charged.
NO_ACTIVATIONThat id is not yours, or does not exist.
EARLY_CANCEL_DENIEDCancelled inside the first two minutes. Wait, then retry.
ERROR_SQLWe failed to record it. Nothing was charged.
Two behaviours worth knowing, because they involve your money. A rental that never receives a code is refunded automatically after twenty minutes — you do not have to call setStatus at all. And a cancel inside the first two minutes is refused: without that rule, renting and instantly cancelling in a loop would be a free way to scan our stock, so the protocol denies it and so do we.
Poll every 5 seconds, not every 500 milliseconds. Codes take seconds to minutes depending on the platform. Polling harder does not make them arrive sooner.

v2 — SMM services

Followers, views, likes and comments across the major platforms. Orders are placed by link and quantity, and progress is readable while they run.

Base URL  https://kamiverify.com/api/v2  — always POST.

This is the standard panel protocol on purpose. The action names and the response keys match what SMM panel software already expects. If you run a panel, you can very likely add KamiVerify as a provider by pasting this URL and your key into your existing provider screen — no adapter, no custom code.
POST/api/v2 · action=servicesThe full catalogue with prices
ParameterTypeWhat it is
keyrequiredstringYour API key.
actionrequiredstringThe literal services.
POST/api/v2 · action=addPlace an order
ParameterTypeWhat it is
keyrequiredstringYour API key.
actionrequiredstringThe literal add.
servicerequiredintegerService id from services.
linkrequiredstringThe post or profile URL the order runs against.
quantityrequiredintegerHow many. Must sit between the service's min and max.
POST/api/v2 · action=statusOne order's progress
ParameterTypeWhat it is
keyrequiredstringYour API key.
actionrequiredstringThe literal status.
orderrequiredintegerThe order id returned by add.
POST/api/v2 · action=ordersYour recent orders
ParameterTypeWhat it is
keyrequiredstringYour API key.
actionrequiredstringThe literal orders.
limitintegerHow many to return, newest first. Default 100, maximum 300.
POST/api/v2 · action=multistatusUp to 100 orders in one call
ParameterTypeWhat it is
keyrequiredstringYour API key.
actionrequiredstringThe literal multistatus.
ordersrequiredstringComma-separated order ids, 100 maximum. status accepts this too. The reply is keyed by order id, and an unknown id carries its own error rather than failing the batch.
Place an order and read it back
# place it
curl "https://kamiverify.com/api/v2" \
  -d "key=YOUR_API_KEY" -d "action=add" \
  -d "service=1043" \
  -d "link=https://instagram.com/p/Cx1y2z3" \
  -d "quantity=1000"
# {"order":238104}

# read it back
curl "https://kamiverify.com/api/v2" \
  -d "key=YOUR_API_KEY" -d "action=status" -d "order=238104"

# {
#   "charge": "0.2700",
#   "start_count": "1240",
#   "status": "In progress",
#   "remains": "320",
#   "currency": "USD"
# }

Order statuses

PendingAccepted, not started.
In progressRunning. remains counts down.
CompletedDelivered in full.
PartialSome delivered. The undelivered portion is refunded to your balance automatically.
CanceledNot delivered. Refunded in full.
ProcessingBeing handed to the provider.

Errors

The two protocols report failure differently, and that is deliberate rather than untidy — each matches its own standard. v1 returns a bare string such as BAD_KEY; every one is listed in the v1 section above. v2 returns JSON, described here.

v2 errors come back as 200 OK with an error key, which is what panel software expects. Check for the key, not for the HTTP status — a 4xx makes many child panels report "provider down" instead of showing your message.

An error response
{ "error": "Not enough balance" }
Incorrect API keyMissing, mistyped, or regenerated since you last saved it.
Not enough balanceTop up. Nothing was charged and no order was made.
Incorrect service IDThe service id does not exist, or is no longer sold.
Incorrect quantityBelow the service minimum or above its maximum.
Incorrect order IDNo such order, or it belongs to someone else.
The account is inactiveThe account is suspended. Contact support.
Treat a timeout as unknown, never as failed. If a request to add or getNumber times out, the order may still have been created and charged. Re-read with status before retrying, or you will pay twice for one order.

Rate limits

Nothing is throttled yet. There is no rate limiter in front of these endpoints today, so the figures below are fair-use guidance rather than enforced ceilings. Build to them anyway - they are what the limits will be when throttling is switched on, and code written against them will not need changing.
ActionGuidanceWhy
getStatus, status1 per second per orderPoll every 5 seconds. Faster does not make codes arrive sooner.
status with orders100 ids per callUse it instead of looping single lookups.
add, getNumber10 per secondPer account.
services1 per minuteThe catalogue barely moves. Cache it for an hour.

Reseller rules

Short, and we mean them.

  • Set your own prices. We bill you the API price. What you charge your customers is your business.
  • You own your customers. We never contact them and never see who they are — only the orders you place.
  • Support your own users first. If the problem turns out to be ours, bring it to us with the order id.
  • Lawful use only. Numbers are for receiving verification codes on accounts the user is entitled to open. Using them to impersonate people, take over accounts, or run fraud ends the account — yours, not just theirs. This is the rule that keeps our own suppliers connected, so there is no discretion in it.
  • No reselling the key. One key, one business. Give your customers your own interface, not our credentials.

No contract to sign, no minimum volume, no monthly fee. Stop whenever you like; whatever is left on your balance stays spendable.

Get your key and start

Create an account, top up from 2,500 XAF, and place your first API order in a few minutes.