Authentication
Every request to /v1/* (except /v1/auth/*) is authenticated with HTTP Basic auth using your API key id as the username and the secret as the password.
curl https://api.teronapay.com/v1/balance \
-u "np_xxxxxxxxxxxxxxxxxxxxxxxx:<secret>"Equivalently:
GET /v1/balance HTTP/1.1
Host: api.teronapay.com
Authorization: Basic <base64(key_id:secret)>Getting an API key
Two ways:
- Sign up at
/signup. The signup response includes your first key (labeldashboard). The plaintext secret is shown once — copy it now. - Login at
/v1/auth/loginreturns a fresh session key (labeldashboard-session) on every call. Useful for short-lived web sessions.
POST /v1/auth/register
Create a new merchant + first user + first API key in one transaction. Unauthenticated.
Request
{
"email": "owner@acme.com",
"password": "hunter2hunter2",
"merchant_name": "Acme Corp",
"country": "KE"
}| Field | Type | Notes |
|---|---|---|
email | string | Required. Must contain @. Unique across all merchants |
password | string | Required. 8..128 chars |
merchant_name | string | Required |
country | string | ISO-3166-1 alpha-2. Defaults to KE when empty |
Response 201:
{
"merchant_id": "ed4aa4ab-e0f9-467f-9165-d17f67ec1bdc",
"merchant_name": "Acme Corp",
"user_id": "2462570a-d20f-4a95-98e1-72a8060f6ffb",
"email": "owner@acme.com",
"role": "owner",
"api_key_id": "np_1b6460d28e97c90c718b359e",
"api_key_secret": "9a2e66835a692364acd8f040957b015e6ab5fc215c9ec3d5d7e008b8ebbdb6e4"
}Errors
400 invalid_request— bad email/password/country shape409 conflict— email already registered
POST /v1/auth/login
Verify email + password; return a fresh session API key. Unauthenticated.
Request
{ "email": "owner@acme.com", "password": "hunter2hunter2" }Response 200: same shape as register.
Errors
401 unauthorized— invalid credentials (also returned when the user is disabled — we don't leak existence)403 forbidden— merchant is suspended
Security notes
- Never embed the secret in client-side code. Use a server-side BFF (like the
web/dashboard does). - Rotate keys periodically. Each login issues a fresh
dashboard-sessionkey; you can also issue/revoke keys from the dashboard. - All API traffic must be HTTPS. We reject
http://in production. - Rate limit: 600 RPM/merchant by default. Write endpoints (
POST /v1/payments,POST /v1/payouts) share a tighter bucket (60 RPM by default).
