Developer docs
On this page
- Base URL
https://coresyncapi.avitechcloud.com/api/v1- Authentication
X-API-Key: cs_live_xxx. Keys and scopes- Format
- JSON, snake_case, times in UTC. Errors are problem+json.
Paths below are relative to the base URL. Every operation also answers 401, 429 and 500 as listed, and carries rate-limit headers. Writes that create a record or move money need an Idempotency-Key. Examples use made-up data for the ISP Amani Link.
Account
Who the API key is and which ISP it acts on.
Get the API key and the ISP it acts on#
/accountReturns the calling key (name, scopes, rate limit, expiry) and the ISP it acts on. Use it first to check a key works and to learn the ISP's currency and time zone. Changes nothing.
readRead-onlyResponses
- 200Success. Returns Account.
Response fields · Account · 2
| Name | Type | Description |
|---|---|---|
key | ApiKeyInfo | |
tenant | Tenant |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopetenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/account" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"key": {
"name": "amani-crm",
"prefix": "cs_live_xxxx",
"kind": "TENANT",
"scopes": [
"read",
"write"
],
"rate_limit_per_minute": 120,
"expires_at": null
},
"tenant": {
"code": "AMANI",
"name": "Amani Link",
"status": "ACTIVE",
"currency": "KES",
"country_code": "KE",
"timezone": "Africa/Nairobi"
}
}Subscribers
An ISP's customers: who they are, plan, balance, invoices, payments, connection; suspend, reactivate, change plan.
List subscribers#
/subscribersLists the ISP's subscribers, newest first, optionally filtered by status or a free-text search over name, username, account number, paybill code, email and phone. To find one person by an exact phone, email or account number, use lookupSubscribers instead. Changes nothing.
readCreator needsBILLING:SUBSCRIBERS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
statusquery | string | Only subscribers in this state. ONLINE / OFFLINE filter on the live connection. One of: |
qquery | string | Free-text search (partial matches). Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
- 200Success. A page of SubscriberSummary.
Fields of each item · SubscriberSummary · 13
| Name | Type | Description |
|---|---|---|
id | string | Subscriber id. Use it in every /subscribers/{id} operation. Example: |
account_number | string | The ISP's account number. Example: |
subscriber_code | string | The billing code the customer types as the M-Pesa paybill account reference. Example: |
username | string | PPPoE / RADIUS login name. Example: |
name | string | Full name, or the business name for a business account. Example: |
phone | string | Primary phone number in E.164. Example: |
email | string | Email address, if the ISP has one. Example: |
status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
service_type | string | How the subscriber connects. One of: |
online | boolean | True while the subscriber has a live session. Example: |
plan_name | string | Name of the plan on the current subscription, if any. Example: |
expires_at | string · date-time | When the current subscription runs out (UTC). Example: |
credit_balance | Money |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers?status=SUSPENDED&size=50" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"subscriber_code": "AL1042",
"username": "wanjiku.k",
"name": "Wanjiku Kamau",
"phone": "+254712345678",
"email": "wanjiku@example.com",
"status": "ACTIVE",
"service_type": "PPPOE",
"online": true,
"plan_name": "Home 10 Mbps",
"expires_at": "2026-11-25T09:00:00Z",
"credit_balance": {
"amount": "300.00",
"currency": "KES"
}
}
],
"total": 137,
"page": 1,
"size": 50
}Get a subscriber#
/subscribers/{id}Returns one subscriber with their status, current plan and subscription (expiry), balance and whether they are online. Changes nothing.
readCreator needsBILLING:SUBSCRIBERS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
Responses
- 200Success. Returns Subscriber.
Response fields · Subscriber · 22
| Name | Type | Description |
|---|---|---|
id | string | Subscriber id. Example: |
account_number | string | The ISP's account number. Example: |
subscriber_code | string | The billing code the customer types as the M-Pesa paybill account reference. Example: |
username | string | PPPoE / RADIUS login name. Example: |
name | string | Full name, or the business name for a business account. Example: |
first_name | string | First name. Example: |
last_name | string | Last name. Example: |
phone | string | Primary phone number in E.164. Example: |
phones | array of string | Every phone number on the account, in E.164 (some accounts carry two). |
email | string | Email address, if the ISP has one. Example: |
type | string | Account type. One of: |
status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
service_type | string | How the subscriber connects. One of: |
address | string | Installation or physical address. Example: |
zone | string | Service zone or area name. Example: |
online | boolean | True while the subscriber has a live session. Example: |
last_online_at | string · date-time | When the subscriber was last seen online (UTC). Example: |
subscription | Subscription | |
balance | Balance | |
created_at | string · date-time | When the account was created (UTC). Example: |
activated_at | string · date-time | When service was last activated (UTC). Example: |
suspended_at | string · date-time | When service was last suspended (UTC), if it is suspended. |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"subscriber_code": "AL1042",
"username": "wanjiku.k",
"name": "Wanjiku Kamau",
"first_name": "Wanjiku",
"last_name": "Kamau",
"phone": "+254712345678",
"phones": [
"+254712345678"
],
"email": "wanjiku@example.com",
"type": "RESIDENTIAL",
"status": "ACTIVE",
"service_type": "PPPOE",
"address": "Kilimani, Nairobi",
"zone": "Kilimani",
"online": true,
"last_online_at": "2026-10-25T08:55:00Z",
"subscription": {
"id": "5b6c7d8e-9f0a-1b2c-3d4e-5f6a7b8c9d0e",
"status": "ACTIVE",
"plan": {
"id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"code": "HOME10",
"name": "Home 10 Mbps",
"price": {
"amount": "1500.00",
"currency": "KES"
}
},
"starts_at": "2026-10-25T09:00:00Z",
"expires_at": "2026-11-25T09:00:00Z",
"auto_renew": true,
"price": {
"amount": "1500.00",
"currency": "KES"
},
"pending_plan_id": null
},
"balance": {
"credit": {
"amount": "300.00",
"currency": "KES"
},
"outstanding": {
"amount": "0.00",
"currency": "KES"
},
"open_invoices": 1,
"next_renewal_amount": {
"amount": "1500.00",
"currency": "KES"
},
"expires_at": "2026-11-25T09:00:00Z"
},
"created_at": "2025-03-02T10:15:00Z",
"activated_at": "2025-03-02T12:00:00Z",
"suspended_at": null
}Find subscribers by phone, email or account number#
/subscribers/lookupFinds subscribers by exactly one identifier. phone accepts any format (0712345678, 254712345678, +254 712 345 678) and matches however the number is stored; email ignores case; account matches the account number, the paybill code or the PPPoE username exactly. Usually returns one subscriber, but one phone can belong to several accounts. Use it to match a caller or a customer from another system. Changes nothing.
readCreator needsBILLING:SUBSCRIBERS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
phonequery | string | Phone number in any common format; compared as E.164. Example: |
emailquery | string | Email address (case-insensitive, exact). Example: |
accountquery | string | Account number, paybill code or PPPoE username (exact). Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
- 200Success. A page of SubscriberSummary.
Fields of each item · SubscriberSummary · 13
| Name | Type | Description |
|---|---|---|
id | string | Subscriber id. Use it in every /subscribers/{id} operation. Example: |
account_number | string | The ISP's account number. Example: |
subscriber_code | string | The billing code the customer types as the M-Pesa paybill account reference. Example: |
username | string | PPPoE / RADIUS login name. Example: |
name | string | Full name, or the business name for a business account. Example: |
phone | string | Primary phone number in E.164. Example: |
email | string | Email address, if the ISP has one. Example: |
status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
service_type | string | How the subscriber connects. One of: |
online | boolean | True while the subscriber has a live session. Example: |
plan_name | string | Name of the plan on the current subscription, if any. Example: |
expires_at | string · date-time | When the current subscription runs out (UTC). Example: |
credit_balance | Money |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/lookup?phone=%2B254712345678" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"subscriber_code": "AL1042",
"username": "wanjiku.k",
"name": "Wanjiku Kamau",
"phone": "+254712345678",
"email": "wanjiku@example.com",
"status": "ACTIVE",
"service_type": "PPPOE",
"online": true,
"plan_name": "Home 10 Mbps",
"expires_at": "2026-11-25T09:00:00Z",
"credit_balance": {
"amount": "300.00",
"currency": "KES"
}
}
],
"total": 137,
"page": 1,
"size": 50
}Get what a subscriber has paid ahead and owes#
/subscribers/{id}/balanceReturns the subscriber's wallet credit, the total of their unpaid invoices, what the next cycle costs and when the current one ends. Use it to answer "how much do I owe" or "when does my internet expire". Changes nothing.
readCreator needsBILLING:SUBSCRIBERS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
Responses
- 200Success. Returns Balance.
Response fields · Balance · 5
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/balance" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"credit": {
"amount": "300.00",
"currency": "KES"
},
"outstanding": {
"amount": "0.00",
"currency": "KES"
},
"open_invoices": 1,
"next_renewal_amount": {
"amount": "1500.00",
"currency": "KES"
},
"expires_at": "2026-11-25T09:00:00Z"
}Get a subscriber's connection#
/subscribers/{id}/sessionSays whether the subscriber is online now, with the live RADIUS session (IP, router, since when, data used) and their last ended session (when and why it dropped). Use it for "is my internet on" or "when did it drop". Changes nothing.
readCreator needsSYSTEM:DASHBOARD:VIEW or BILLING:SUBSCRIBERS:READRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
Responses
- 200Success. Returns SubscriberSession.
Response fields · SubscriberSession · 3
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/session" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"online": true,
"current": {
"id": "4815162342",
"type": "PPPOE",
"username": "wanjiku.k",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"ip_address": "10.6.0.25",
"mac_address": "AA:BB:CC:DD:EE:FF",
"nas_ip": "10.10.0.1",
"nas_name": "Kilimani-CCR",
"started_at": "2026-10-25T06:12:00Z",
"ended_at": null,
"end_cause": null,
"duration_seconds": 9840,
"bytes_up": 104857600,
"bytes_down": 2147483648
},
"last_session": {
"id": "4815162342",
"type": "PPPOE",
"username": "wanjiku.k",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"ip_address": "10.6.0.25",
"mac_address": "AA:BB:CC:DD:EE:FF",
"nas_ip": "10.10.0.1",
"nas_name": "Kilimani-CCR",
"started_at": "2026-10-25T06:12:00Z",
"ended_at": null,
"end_cause": null,
"duration_seconds": 9840,
"bytes_up": 104857600,
"bytes_down": 2147483648
}
}List a subscriber's invoices#
/subscribers/{id}/invoicesLists the invoices issued to one subscriber, newest first. Changes nothing.
readCreator needsBILLING:SUBSCRIBERS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
Fields of each item · Invoice · 12
| Name | Type | Description |
|---|---|---|
id | string | Invoice id. Example: |
number | string | Invoice number as printed. Example: |
subscriber | SubscriberRef | |
plan_name | string | The plan billed, as it was named when the invoice was issued. Example: |
amount | Money | |
status | string | ISSUED: unpaid. OVERDUE: unpaid past the due date. PAID. VOID: cancelled. One of: |
issued_on | string · date | Issue date (ISO 8601 date). Example: |
due_on | string · date | Due date (ISO 8601 date). Example: |
paid_on | string · date | Date it was paid, if it was. |
payment_id | string | The payment that settled it, if any. |
payment_reference | string | Receipt / reference of the settling payment. Example: |
created_at | string · date-time | When the invoice record was created (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/invoices" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"number": "INV-202610-0042",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"plan_name": "Home 10 Mbps",
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"status": "ISSUED",
"issued_on": "2026-10-01",
"due_on": "2026-10-08",
"paid_on": null,
"payment_id": null,
"payment_reference": "SAMPLE7Q2Z",
"created_at": "2026-10-01T05:00:00Z"
}
],
"total": 137,
"page": 1,
"size": 50
}List a subscriber's payments#
/subscribers/{id}/paymentsLists the payments applied to one subscriber, newest first. Changes nothing.
readCreator needsBILLING:PAYMENTS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
Fields of each item · Payment · 13
| Name | Type | Description |
|---|---|---|
id | string | Payment id. Example: |
subscriber | SubscriberRef | |
amount | Money | |
provider | string | Where the money came from, e.g. MPESA, KCB, EQUITY, CASH, BANK. Example: |
method | string | How it arrived: STK_PUSH, PAYBILL, TILL, MANUAL (recorded by staff or the API). Example: |
reference | string | The provider's receipt / transaction reference. Unique per provider. Example: |
payer_phone | string | The payer's phone in E.164, when the provider gives it. Example: |
account_reference | string | What the payer typed as the account / reference. Example: |
status | string | PENDING, COMPLETED, FAILED or REVERSED. One of: |
applied | boolean | True once the money has been credited to the subscriber's wallet / renewal. Example: |
applied_at | string · date-time | When it was applied (UTC). Example: |
not_applied_amount | Money | |
received_at | string · date-time | When the payment was received (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/payments" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"provider": "MPESA",
"method": "PAYBILL",
"reference": "SAMPLE7Q2Z",
"payer_phone": "+254712345678",
"account_reference": "AL1042",
"status": "COMPLETED",
"applied": true,
"applied_at": "2026-10-25T09:00:05Z",
"not_applied_amount": {
"amount": "0.00",
"currency": "KES"
},
"received_at": "2026-10-25T09:00:00Z"
}
],
"total": 137,
"page": 1,
"size": 50
}Change a subscriber's plan#
/subscribers/{id}/planMoves the subscriber to another plan now, without a payment: their speed and price change immediately and the subscription end date stays where it is. The reason is recorded for the ISP's reports. Use listPlans to find plan ids. For a paid upgrade, record the payment as well.
subscribers:writeCreator needsBILLING:SUBSCRIPTIONS:CREATEChanges dataParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
Request body
Move a subscriber to another plan now, without a payment and without moving their expiry date.
| Name | Type | Description |
|---|---|---|
plan_idrequired | string | The new plan (an ACTIVE plan from Example: |
reasonrequired | string | Why the plan is changing; reported in the ISP's plan-change reports. One of: |
notes | string | Notes. Required when reason is OTHER. Limits: up to 300 characters. Example: |
Responses
- 200Plan changed. Returns SubscriberChange.
Response fields · SubscriberChange · 3
| Name | Type | Description |
|---|---|---|
outcome | string | done: the change was made. approval_pending: the ISP requires a manager's approval for this action; a request was filed and the change happens when someone approves it in the admin. One of: |
subscriber | Subscriber | |
approval_request_id | string | The approval request filed, when outcome is approval_pending. |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 422
plan_inactiveno_subscriptionsame_planplan_change_failed - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/plan" \
-H "X-API-Key: $CORESYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"reason": "CUSTOMER_REQUEST",
"notes": "Moving to the business plan after opening a shop"
}'{
"outcome": "done",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"subscriber_code": "AL1042",
"username": "wanjiku.k",
"name": "Wanjiku Kamau",
"first_name": "Wanjiku",
"last_name": "Kamau",
"phone": "+254712345678",
"phones": [
"+254712345678"
],
"email": "wanjiku@example.com",
"type": "RESIDENTIAL",
"status": "ACTIVE",
"service_type": "PPPOE",
"address": "Kilimani, Nairobi",
"zone": "Kilimani",
"online": true,
"last_online_at": "2026-10-25T08:55:00Z",
"subscription": {
"id": "5b6c7d8e-9f0a-1b2c-3d4e-5f6a7b8c9d0e",
"status": "ACTIVE",
"plan": {
"id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"code": "HOME10",
"name": "Home 10 Mbps",
"price": {
"amount": "1500.00",
"currency": "KES"
}
},
"starts_at": "2026-10-25T09:00:00Z",
"expires_at": "2026-11-25T09:00:00Z",
"auto_renew": true,
"price": {
"amount": "1500.00",
"currency": "KES"
},
"pending_plan_id": null
},
"balance": {
"credit": {
"amount": "300.00",
"currency": "KES"
},
"outstanding": {
"amount": "0.00",
"currency": "KES"
},
"open_invoices": 1,
"next_renewal_amount": {
"amount": "1500.00",
"currency": "KES"
},
"expires_at": "2026-11-25T09:00:00Z"
},
"created_at": "2025-03-02T10:15:00Z",
"activated_at": "2025-03-02T12:00:00Z",
"suspended_at": null
},
"approval_request_id": null
}Suspend a subscriber's service#
/subscribers/{id}/suspendTurns the subscriber's internet off now: their status becomes SUSPENDED, RADIUS throttles them (or the router queue is closed for a static line) and any live session is disconnected. Billing records are kept and the subscription end date does not move. If the ISP requires a manager's approval for suspensions, nothing changes yet: an approval request is filed and the answer is 202 with outcome approval_pending. Suspending an already suspended subscriber changes nothing and answers done.
subscribers:writeCreator needsBILLING:SUBSCRIBERS:EDITChanges dataParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
Request body
Why the subscriber is being suspended. Recorded on their timeline.
| Name | Type | Description |
|---|---|---|
reasonrequired | string | Reason, shown on the subscriber's timeline and to approvers. Limits: 3–300 characters. Example: |
Responses
- 200Suspended (or already suspended). Returns SubscriberChange.
- 202The ISP requires approval; a request was filed. Returns SubscriberChange.
Response fields · SubscriberChange · 3
| Name | Type | Description |
|---|---|---|
outcome | string | done: the change was made. approval_pending: the ISP requires a manager's approval for this action; a request was filed and the change happens when someone approves it in the admin. One of: |
subscriber | Subscriber | |
approval_request_id | string | The approval request filed, when outcome is approval_pending. |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 422
invalid_statesuspend_failedapproval_unavailable - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/suspend" \
-H "X-API-Key: $CORESYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Customer asked to pause service while travelling"
}'{
"outcome": "done",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"subscriber_code": "AL1042",
"username": "wanjiku.k",
"name": "Wanjiku Kamau",
"first_name": "Wanjiku",
"last_name": "Kamau",
"phone": "+254712345678",
"phones": [
"+254712345678"
],
"email": "wanjiku@example.com",
"type": "RESIDENTIAL",
"status": "SUSPENDED",
"service_type": "PPPOE",
"address": "Kilimani, Nairobi",
"zone": "Kilimani",
"online": false,
"last_online_at": "2026-10-25T08:55:00Z",
"subscription": {
"id": "5b6c7d8e-9f0a-1b2c-3d4e-5f6a7b8c9d0e",
"status": "SUSPENDED",
"plan": {
"id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"code": "HOME10",
"name": "Home 10 Mbps",
"price": {
"amount": "1500.00",
"currency": "KES"
}
},
"starts_at": "2026-10-25T09:00:00Z",
"expires_at": "2026-11-25T09:00:00Z",
"auto_renew": true,
"price": {
"amount": "1500.00",
"currency": "KES"
},
"pending_plan_id": null
},
"balance": {
"credit": {
"amount": "300.00",
"currency": "KES"
},
"outstanding": {
"amount": "0.00",
"currency": "KES"
},
"open_invoices": 1,
"next_renewal_amount": {
"amount": "1500.00",
"currency": "KES"
},
"expires_at": "2026-11-25T09:00:00Z"
},
"created_at": "2025-03-02T10:15:00Z",
"activated_at": "2025-03-02T12:00:00Z",
"suspended_at": "2026-11-04T07:30:00Z"
},
"approval_request_id": null
}Reactivate a suspended subscriber without a payment#
/subscribers/{id}/reactivateTurns a SUSPENDED subscriber's internet back on without taking money, with a reason recorded on their timeline. If their subscription had already expired it is extended by one plan cycle from now, free of charge, exactly as the portal does. When the customer has paid, use recordPayment instead: it renews and reactivates them properly. Reactivating an ACTIVE subscriber changes nothing and answers done.
subscribers:writeCreator needsBILLING:SUBSCRIBERS:EDITChanges dataParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Subscriber id. Example: |
Request body
Why the subscriber is being reactivated without a payment. To reactivate by payment, use recordPayment instead.
| Name | Type | Description |
|---|---|---|
reasonrequired | string | Reason, shown on the subscriber's timeline. Limits: 3–300 characters. Example: |
Responses
- 200Reactivated (or already active). Returns SubscriberChange.
Response fields · SubscriberChange · 3
| Name | Type | Description |
|---|---|---|
outcome | string | done: the change was made. approval_pending: the ISP requires a manager's approval for this action; a request was filed and the change happens when someone approves it in the admin. One of: |
subscriber | Subscriber | |
approval_request_id | string | The approval request filed, when outcome is approval_pending. |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 422
invalid_stateno_active_subscriptionreactivate_failed - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/subscribers/3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f/reactivate" \
-H "X-API-Key: $CORESYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Paid in cash at the office; receipt to follow"
}'{
"outcome": "done",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"subscriber_code": "AL1042",
"username": "wanjiku.k",
"name": "Wanjiku Kamau",
"first_name": "Wanjiku",
"last_name": "Kamau",
"phone": "+254712345678",
"phones": [
"+254712345678"
],
"email": "wanjiku@example.com",
"type": "RESIDENTIAL",
"status": "ACTIVE",
"service_type": "PPPOE",
"address": "Kilimani, Nairobi",
"zone": "Kilimani",
"online": true,
"last_online_at": "2026-10-25T08:55:00Z",
"subscription": {
"id": "5b6c7d8e-9f0a-1b2c-3d4e-5f6a7b8c9d0e",
"status": "ACTIVE",
"plan": {
"id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"code": "HOME10",
"name": "Home 10 Mbps",
"price": {
"amount": "1500.00",
"currency": "KES"
}
},
"starts_at": "2026-10-25T09:00:00Z",
"expires_at": "2026-11-25T09:00:00Z",
"auto_renew": true,
"price": {
"amount": "1500.00",
"currency": "KES"
},
"pending_plan_id": null
},
"balance": {
"credit": {
"amount": "300.00",
"currency": "KES"
},
"outstanding": {
"amount": "0.00",
"currency": "KES"
},
"open_invoices": 1,
"next_renewal_amount": {
"amount": "1500.00",
"currency": "KES"
},
"expires_at": "2026-11-25T09:00:00Z"
},
"created_at": "2025-03-02T10:15:00Z",
"activated_at": "2025-03-02T12:00:00Z",
"suspended_at": null
},
"approval_request_id": null
}Sessions
Who is online right now.
List who is online now#
/sessionsLists live RADIUS sessions on the ISP's routers, newest first: PPPoE subscribers and hotspot devices, with IP, MAC, router, start time and data used. total is the number online. For one subscriber use getSubscriberSession. Changes nothing.
readCreator needsSYSTEM:DASHBOARD:VIEW or BILLING:SUBSCRIBERS:READRead-onlyParameters
| Name | Type | Description |
|---|---|---|
typequery | string | Only PPPoE subscribers or only hotspot devices. One of: |
qquery | string | Search over username, MAC and IP (partial). Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
Fields of each item · Session · 14
| Name | Type | Description |
|---|---|---|
id | string | Session id (RADIUS accounting row id). Example: |
type | string | PPPOE or HOTSPOT. One of: |
username | string | RADIUS username (PPPoE login, or the voucher / MAC for hotspot). Example: |
subscriber | SubscriberRef | |
ip_address | string | IP address assigned to the connection. Example: |
mac_address | string | The device's MAC address, as the router reports it. Example: |
nas_ip | string | The router (NAS) the session is on. Example: |
nas_name | string | The router's name. Example: |
started_at | string · date-time | When the session started (UTC). Example: |
ended_at | string · date-time | When it ended (UTC); null while it is live. |
end_cause | string | Why it ended, as RADIUS reports it (e.g. Lost-Carrier, User-Request, Admin-Reset); null while live. |
duration_seconds | integer · int64 | Length of the session so far, in seconds. Example: |
bytes_up | integer · int64 | Bytes the subscriber uploaded in this session. Example: |
bytes_down | integer · int64 | Bytes the subscriber downloaded in this session. Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/sessions" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "4815162342",
"type": "PPPOE",
"username": "wanjiku.k",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"ip_address": "10.6.0.25",
"mac_address": "AA:BB:CC:DD:EE:FF",
"nas_ip": "10.10.0.1",
"nas_name": "Kilimani-CCR",
"started_at": "2026-10-25T06:12:00Z",
"ended_at": null,
"end_cause": null,
"duration_seconds": 9840,
"bytes_up": 104857600,
"bytes_down": 2147483648
}
],
"total": 137,
"page": 1,
"size": 50
}Plans
The service plans an ISP sells.
List plans#
/plansLists the ISP's service plans with price, cycle length and speed, sorted by name. Use it to answer "what packages do you have" or to find the plan_id for changeSubscriberPlan. Changes nothing.
readCreator needsBILLING:PLANS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
statusquery | string | Only plans with this status. One of: |
typequery | string | FIXED (home/business lines) or HOTSPOT (WiFi vouchers). One of: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
Fields of each item · Plan · 15
| Name | Type | Description |
|---|---|---|
id | string | Plan id. Example: |
code | string | Plan code. Example: |
name | string | Plan name as customers see it. Example: |
description | string | Free-text description. Example: |
type | string | FIXED: a home/business line (PPPoE or static). HOTSPOT: a WiFi voucher package. One of: |
price | Money | |
validity_value | integer · int32 | Length of one cycle, in validity_unit. Example: |
validity_unit | string | Unit of the cycle length. One of: |
download_mbps | number · double | Download speed in Mbps, when the plan has a speed profile. Example: |
upload_mbps | number · double | Upload speed in Mbps, when the plan has a speed profile. Example: |
data_limit_bytes | integer · int64 | Data cap per cycle in bytes; null means unlimited. |
max_devices | integer · int32 | How many devices may be online at once; null uses the ISP default. Example: |
status | string | Plan status. Only ACTIVE plans can be assigned. One of: |
visible | boolean | Whether customers see the plan on self-service pages. Example: |
created_at | string · date-time | When the plan was created (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/plans" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"code": "HOME10",
"name": "Home 10 Mbps",
"description": "Unlimited home fibre, 10 Mbps",
"type": "FIXED",
"price": {
"amount": "1500.00",
"currency": "KES"
},
"validity_value": 30,
"validity_unit": "DAYS",
"download_mbps": 10,
"upload_mbps": 5,
"data_limit_bytes": null,
"max_devices": 1,
"status": "ACTIVE",
"visible": true,
"created_at": "2026-01-10T07:00:00Z"
}
],
"total": 137,
"page": 1,
"size": 50
}Get a plan#
/plans/{id}Returns one service plan. Changes nothing.
readCreator needsBILLING:PLANS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Plan id. Example: |
Responses
- 200Success. Returns Plan.
Response fields · Plan · 15
| Name | Type | Description |
|---|---|---|
id | string | Plan id. Example: |
code | string | Plan code. Example: |
name | string | Plan name as customers see it. Example: |
description | string | Free-text description. Example: |
type | string | FIXED: a home/business line (PPPoE or static). HOTSPOT: a WiFi voucher package. One of: |
price | Money | |
validity_value | integer · int32 | Length of one cycle, in validity_unit. Example: |
validity_unit | string | Unit of the cycle length. One of: |
download_mbps | number · double | Download speed in Mbps, when the plan has a speed profile. Example: |
upload_mbps | number · double | Upload speed in Mbps, when the plan has a speed profile. Example: |
data_limit_bytes | integer · int64 | Data cap per cycle in bytes; null means unlimited. |
max_devices | integer · int32 | How many devices may be online at once; null uses the ISP default. Example: |
status | string | Plan status. Only ACTIVE plans can be assigned. One of: |
visible | boolean | Whether customers see the plan on self-service pages. Example: |
created_at | string · date-time | When the plan was created (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/plans/9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"id": "9c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
"code": "HOME10",
"name": "Home 10 Mbps",
"description": "Unlimited home fibre, 10 Mbps",
"type": "FIXED",
"price": {
"amount": "1500.00",
"currency": "KES"
},
"validity_value": 30,
"validity_unit": "DAYS",
"download_mbps": 10,
"upload_mbps": 5,
"data_limit_bytes": null,
"max_devices": 1,
"status": "ACTIVE",
"visible": true,
"created_at": "2026-01-10T07:00:00Z"
}Invoices
Invoices issued to subscribers.
List invoices#
/invoicesLists the ISP's invoices, newest first, filtered by status, issue date or a search over the subscriber's name, phone, username and the invoice number. For one subscriber's invoices use listSubscriberInvoices. Changes nothing.
readCreator needsSYSTEM:DASHBOARD:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
statusquery | string | Only invoices in this state. One of: |
fromquery | string · date | Issued on or after this date (YYYY-MM-DD). Example: |
toquery | string · date | Issued on or before this date (YYYY-MM-DD). Example: |
qquery | string | Free-text search. Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
Fields of each item · Invoice · 12
| Name | Type | Description |
|---|---|---|
id | string | Invoice id. Example: |
number | string | Invoice number as printed. Example: |
subscriber | SubscriberRef | |
plan_name | string | The plan billed, as it was named when the invoice was issued. Example: |
amount | Money | |
status | string | ISSUED: unpaid. OVERDUE: unpaid past the due date. PAID. VOID: cancelled. One of: |
issued_on | string · date | Issue date (ISO 8601 date). Example: |
due_on | string · date | Due date (ISO 8601 date). Example: |
paid_on | string · date | Date it was paid, if it was. |
payment_id | string | The payment that settled it, if any. |
payment_reference | string | Receipt / reference of the settling payment. Example: |
created_at | string · date-time | When the invoice record was created (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/invoices" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"number": "INV-202610-0042",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"plan_name": "Home 10 Mbps",
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"status": "ISSUED",
"issued_on": "2026-10-01",
"due_on": "2026-10-08",
"paid_on": null,
"payment_id": null,
"payment_reference": "SAMPLE7Q2Z",
"created_at": "2026-10-01T05:00:00Z"
}
],
"total": 137,
"page": 1,
"size": 50
}Get an invoice#
/invoices/{id}Returns one invoice. Changes nothing.
readCreator needsSYSTEM:DASHBOARD:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Invoice id. Example: |
Responses
- 200Success. Returns Invoice.
Response fields · Invoice · 12
| Name | Type | Description |
|---|---|---|
id | string | Invoice id. Example: |
number | string | Invoice number as printed. Example: |
subscriber | SubscriberRef | |
plan_name | string | The plan billed, as it was named when the invoice was issued. Example: |
amount | Money | |
status | string | ISSUED: unpaid. OVERDUE: unpaid past the due date. PAID. VOID: cancelled. One of: |
issued_on | string · date | Issue date (ISO 8601 date). Example: |
due_on | string · date | Due date (ISO 8601 date). Example: |
paid_on | string · date | Date it was paid, if it was. |
payment_id | string | The payment that settled it, if any. |
payment_reference | string | Receipt / reference of the settling payment. Example: |
created_at | string · date-time | When the invoice record was created (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/invoices/7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"number": "INV-202610-0042",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"plan_name": "Home 10 Mbps",
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"status": "ISSUED",
"issued_on": "2026-10-01",
"due_on": "2026-10-08",
"paid_on": null,
"payment_id": null,
"payment_reference": "SAMPLE7Q2Z",
"created_at": "2026-10-01T05:00:00Z"
}Payments
Money received, and recording a payment.
List payments#
/paymentsLists payments received, newest first, by status, provider, whether they matched a subscriber, and time received. matched=false lists money that arrived but could not be tied to a subscriber. Changes nothing.
readCreator needsBILLING:PAYMENTS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
statusquery | string | Only payments in this state. One of: |
providerquery | string | Only this provider, e.g. MPESA, KCB, CASH. Example: |
matchedquery | boolean | true: only payments tied to a subscriber. false: only unmatched ones. Example: |
fromquery | string · date-time | Received at or after this time (ISO 8601, UTC). Example: |
toquery | string · date-time | Received at or before this time (ISO 8601, UTC). Example: |
qquery | string | Search over receipt, phone, account reference and subscriber name. Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
Fields of each item · Payment · 13
| Name | Type | Description |
|---|---|---|
id | string | Payment id. Example: |
subscriber | SubscriberRef | |
amount | Money | |
provider | string | Where the money came from, e.g. MPESA, KCB, EQUITY, CASH, BANK. Example: |
method | string | How it arrived: STK_PUSH, PAYBILL, TILL, MANUAL (recorded by staff or the API). Example: |
reference | string | The provider's receipt / transaction reference. Unique per provider. Example: |
payer_phone | string | The payer's phone in E.164, when the provider gives it. Example: |
account_reference | string | What the payer typed as the account / reference. Example: |
status | string | PENDING, COMPLETED, FAILED or REVERSED. One of: |
applied | boolean | True once the money has been credited to the subscriber's wallet / renewal. Example: |
applied_at | string · date-time | When it was applied (UTC). Example: |
not_applied_amount | Money | |
received_at | string · date-time | When the payment was received (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/payments?from=2026-10-01T00%3A00%3A00Z&matched=true" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"provider": "MPESA",
"method": "PAYBILL",
"reference": "SAMPLE7Q2Z",
"payer_phone": "+254712345678",
"account_reference": "AL1042",
"status": "COMPLETED",
"applied": true,
"applied_at": "2026-10-25T09:00:05Z",
"not_applied_amount": {
"amount": "0.00",
"currency": "KES"
},
"received_at": "2026-10-25T09:00:00Z"
}
],
"total": 137,
"page": 1,
"size": 50
}Get a payment#
/payments/{id}Returns one payment. Changes nothing.
readCreator needsBILLING:PAYMENTS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Payment id. Example: |
Responses
- 200Success. Returns Payment.
Response fields · Payment · 13
| Name | Type | Description |
|---|---|---|
id | string | Payment id. Example: |
subscriber | SubscriberRef | |
amount | Money | |
provider | string | Where the money came from, e.g. MPESA, KCB, EQUITY, CASH, BANK. Example: |
method | string | How it arrived: STK_PUSH, PAYBILL, TILL, MANUAL (recorded by staff or the API). Example: |
reference | string | The provider's receipt / transaction reference. Unique per provider. Example: |
payer_phone | string | The payer's phone in E.164, when the provider gives it. Example: |
account_reference | string | What the payer typed as the account / reference. Example: |
status | string | PENDING, COMPLETED, FAILED or REVERSED. One of: |
applied | boolean | True once the money has been credited to the subscriber's wallet / renewal. Example: |
applied_at | string · date-time | When it was applied (UTC). Example: |
not_applied_amount | Money | |
received_at | string · date-time | When the payment was received (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/payments/1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"id": "1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"provider": "MPESA",
"method": "PAYBILL",
"reference": "SAMPLE7Q2Z",
"payer_phone": "+254712345678",
"account_reference": "AL1042",
"status": "COMPLETED",
"applied": true,
"applied_at": "2026-10-25T09:00:05Z",
"not_applied_amount": {
"amount": "0.00",
"currency": "KES"
},
"received_at": "2026-10-25T09:00:00Z"
}Record a payment for a subscriber#
/paymentsRecords money the ISP received outside CoreSync's own channels (cash, a bank transfer, an M-Pesa receipt) and applies it the same way an M-Pesa payment is applied: it goes to the subscriber's wallet, renews their subscription when it covers the plan price (and reactivates a suspended subscriber), and it appears in the ISP's payments and reports. Moves money: needs an Idempotency-Key, and a provider + reference is only ever recorded once, so passing the real receipt makes a duplicate impossible. Answers 201 when recorded, 200 when this exact receipt was already recorded for this subscriber.
payments:writeCreator needsBILLING:PAYMENTS:EDITChanges dataIdempotency-Key requiredParameters
| Name | Type | Description |
|---|---|---|
Idempotency-Keyrequiredheader | string | A unique string per payment (e.g. a UUID). Retrying with the same key returns the first response instead of recording it again, for 24 hours. Example: |
Request body
A payment received outside CoreSync's own channels (cash, a bank transfer, an M-Pesa receipt the ISP holds).
| Name | Type | Description |
|---|---|---|
subscriber_idrequired | string | The subscriber who paid. Example: |
amountrequired | string | Amount received, as a decimal string. Example: |
currency | string | ISO 4217 currency. Must be the ISP's currency; defaults to it. Limits: 3–3 characters, 3 letters. Example: |
provider | string | Where the money came from. Defaults to CASH. One of: |
reference | string | The receipt or transaction reference. A provider + reference pair is only ever recorded once, so pass the real receipt (e.g. the M-Pesa code) to make a duplicate impossible. Generated from the Idempotency-Key when omitted. Limits: up to 100 characters. Example: |
Responses
- 201Recorded and applied. Returns Payment.
- 200This receipt was already recorded for this subscriber; nothing changed. Returns Payment.
Response fields · Payment · 13
| Name | Type | Description |
|---|---|---|
id | string | Payment id. Example: |
subscriber | SubscriberRef | |
amount | Money | |
provider | string | Where the money came from, e.g. MPESA, KCB, EQUITY, CASH, BANK. Example: |
method | string | How it arrived: STK_PUSH, PAYBILL, TILL, MANUAL (recorded by staff or the API). Example: |
reference | string | The provider's receipt / transaction reference. Unique per provider. Example: |
payer_phone | string | The payer's phone in E.164, when the provider gives it. Example: |
account_reference | string | What the payer typed as the account / reference. Example: |
status | string | PENDING, COMPLETED, FAILED or REVERSED. One of: |
applied | boolean | True once the money has been credited to the subscriber's wallet / renewal. Example: |
applied_at | string · date-time | When it was applied (UTC). Example: |
not_applied_amount | Money | |
received_at | string · date-time | When the payment was received (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameteridempotency_key_required - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 409
idempotency_in_progressduplicate_reference - 422
idempotency_key_reusedcurrency_mismatchpayment_not_applied - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/payments" \
-H "X-API-Key: $CORESYNC_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 4d1c9f0e-7a2b-4f43-9a51-2f0c7c1d8e11" \
-d '{
"subscriber_id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"amount": "1500.00",
"currency": "KES",
"provider": "MPESA",
"reference": "SAMPLE7Q2Z"
}'{
"id": "1c2d3e4f-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
"subscriber": {
"id": "3f2a6c1e-8b7d-4c1a-9e2f-1a2b3c4d5e6f",
"account_number": "AL-01042",
"name": "Wanjiku Kamau",
"phone": "+254712345678"
},
"amount": {
"amount": "1500.00",
"currency": "KES"
},
"provider": "MPESA",
"method": "PAYBILL",
"reference": "SAMPLE7Q2Z",
"payer_phone": "+254712345678",
"account_reference": "AL1042",
"status": "COMPLETED",
"applied": true,
"applied_at": "2026-10-25T09:00:05Z",
"not_applied_amount": {
"amount": "0.00",
"currency": "KES"
},
"received_at": "2026-10-25T09:00:00Z"
}Webhooks
Endpoints that receive signed events.
List webhook endpoints#
/webhooksLists the ISP's webhook endpoints and the events each receives. Signing secrets are not included. Changes nothing.
readCreator needsSYSTEM:SETTINGS:VIEWRead-onlyResponses
- 200Success. A list of WebhookEndpoint.
Response fields · WebhookEndpoint · 10
| Name | Type | Description |
|---|---|---|
id | string | Endpoint id. Example: |
url | string | HTTPS URL events are POSTed to. Example: |
description | string | A note to say what the endpoint is for. Example: |
events | array of string | Events this endpoint receives. |
active | boolean | False when switched off by hand, or automatically after 20 failed attempts in a row. Example: |
disabled_reason | string | Why it was switched off automatically, if it was. |
last_success_at | string · date-time | Last successful delivery (UTC). Example: |
last_failure_at | string · date-time | Last failed attempt (UTC). |
created_at | string · date-time | When the endpoint was added (UTC). Example: |
signing_secret | string | The secret to verify X-Webhook-Signature with. Present only in the response to Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/webhooks" \
-H "X-API-Key: $CORESYNC_API_KEY"[
{
"id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"url": "https://hooks.example.com/coresync",
"description": "Amani Link CRM",
"events": [
"payment.received",
"subscriber.suspended"
],
"active": true,
"disabled_reason": null,
"last_success_at": "2026-10-25T09:00:06Z",
"last_failure_at": null,
"created_at": "2026-10-25T08:00:00Z",
"signing_secret": null
}
]Get a webhook endpoint#
/webhooks/{id}Returns one endpoint and its delivery health (last success, last failure, whether it was switched off). Changes nothing.
readCreator needsSYSTEM:SETTINGS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Endpoint id. Example: |
Responses
- 200Success. Returns WebhookEndpoint.
Response fields · WebhookEndpoint · 10
| Name | Type | Description |
|---|---|---|
id | string | Endpoint id. Example: |
url | string | HTTPS URL events are POSTed to. Example: |
description | string | A note to say what the endpoint is for. Example: |
events | array of string | Events this endpoint receives. |
active | boolean | False when switched off by hand, or automatically after 20 failed attempts in a row. Example: |
disabled_reason | string | Why it was switched off automatically, if it was. |
last_success_at | string · date-time | Last successful delivery (UTC). Example: |
last_failure_at | string · date-time | Last failed attempt (UTC). |
created_at | string · date-time | When the endpoint was added (UTC). Example: |
signing_secret | string | The secret to verify X-Webhook-Signature with. Present only in the response to Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/webhooks/2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"url": "https://hooks.example.com/coresync",
"description": "Amani Link CRM",
"events": [
"payment.received",
"subscriber.suspended"
],
"active": true,
"disabled_reason": null,
"last_success_at": "2026-10-25T09:00:06Z",
"last_failure_at": null,
"created_at": "2026-10-25T08:00:00Z",
"signing_secret": null
}List an endpoint's deliveries#
/webhooks/{id}/deliveriesThe delivery log for one endpoint, newest first: each event, its status, attempts, the HTTP status the endpoint answered and the last error. Kept for 30 days. Changes nothing.
readCreator needsSYSTEM:SETTINGS:VIEWRead-onlyParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Endpoint id. Example: |
pagequery | integer · int32 | Page number, starting at 1. Limits: at least 1. Default Example: |
sizequery | integer · int32 | Results per page, 1–200. Limits: 1–200. Default Example: |
Responses
- 200Success. A page of WebhookDelivery.
Fields of each item · WebhookDelivery · 11
| Name | Type | Description |
|---|---|---|
id | string | Delivery id; also sent as X-Webhook-Delivery-Id. Example: |
endpoint_id | string | The endpoint. Example: |
event_id | string | The event's id (the envelope's id). The same event sent to two endpoints has one event_id. Example: |
event_type | string | Event type. Example: |
status | string | PENDING: waiting for its next attempt. DELIVERED: the endpoint answered 2xx. FAILED: gave up after 5 attempts. One of: |
attempts | integer · int32 | Attempts made so far (at most 5). Example: |
response_status | integer · int32 | HTTP status of the last attempt, if the endpoint answered. Example: |
last_error | string | What went wrong on the last attempt, if it failed. |
next_attempt_at | string · date-time | When the next retry happens (UTC), while PENDING. |
created_at | string · date-time | When the event was queued (UTC). Example: |
delivered_at | string · date-time | When the endpoint accepted it (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/webhooks/2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e/deliveries" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"items": [
{
"id": "8d9e0f1a-2b3c-4d5e-6f7a-8b9c0d1e2f3a",
"endpoint_id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"event_id": "evt_6f1d2c3b4a5948e7b6c5d4e3f2a1b0c9",
"event_type": "payment.received",
"status": "DELIVERED",
"attempts": 1,
"response_status": 200,
"last_error": null,
"next_attempt_at": null,
"created_at": "2026-10-25T09:00:05Z",
"delivered_at": "2026-10-25T09:00:06Z"
}
],
"total": 137,
"page": 1,
"size": 50
}Add a webhook endpoint#
/webhooksAdds an HTTPS URL that will receive the chosen events. The response carries the signing secret, the only time it is shown: store it to verify X-Webhook-Signature. Creates a record, so it needs an Idempotency-Key. An ISP can have up to 10 endpoints.
webhooks:writeCreator needsSYSTEM:SETTINGS:EDITChanges dataIdempotency-Key requiredParameters
| Name | Type | Description |
|---|---|---|
Idempotency-Keyrequiredheader | string | A unique string per new endpoint. Retrying with the same key returns the first response. Example: |
Request body
A new webhook endpoint.
| Name | Type | Description |
|---|---|---|
urlrequired | string | HTTPS URL to POST events to. Must be reachable from the internet. Limits: up to 500 characters. Example: |
eventsrequired | array of string | Events to receive. One of: |
description | string | A note to say what it is for. Limits: up to 200 characters. Example: |
Responses
- 201Added. signing_secret is set in this response only. Returns WebhookEndpoint.
Response fields · WebhookEndpoint · 10
| Name | Type | Description |
|---|---|---|
id | string | Endpoint id. Example: |
url | string | HTTPS URL events are POSTed to. Example: |
description | string | A note to say what the endpoint is for. Example: |
events | array of string | Events this endpoint receives. |
active | boolean | False when switched off by hand, or automatically after 20 failed attempts in a row. Example: |
disabled_reason | string | Why it was switched off automatically, if it was. |
last_success_at | string · date-time | Last successful delivery (UTC). Example: |
last_failure_at | string · date-time | Last failed attempt (UTC). |
created_at | string · date-time | When the endpoint was added (UTC). Example: |
signing_secret | string | The secret to verify X-Webhook-Signature with. Present only in the response to Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameteridempotency_key_required - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 409
idempotency_in_progress - 422
idempotency_key_reusedinvalid_webhook - 429
rate_limited - 500
internal_error
Example
curl "https://coresyncapi.avitechcloud.com/api/v1/webhooks" \
-H "X-API-Key: $CORESYNC_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 4d1c9f0e-7a2b-4f43-9a51-2f0c7c1d8e11" \
-d '{
"url": "https://hooks.example.com/coresync",
"events": [
"payment.received",
"subscriber.suspended"
],
"description": "Amani Link CRM"
}'{
"id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"url": "https://hooks.example.com/coresync",
"description": "Amani Link CRM",
"events": [
"payment.received",
"subscriber.suspended"
],
"active": true,
"disabled_reason": null,
"last_success_at": "2026-10-25T09:00:06Z",
"last_failure_at": null,
"created_at": "2026-10-25T08:00:00Z",
"signing_secret": "whsec_xxx"
}Send a test event to an endpoint#
/webhooks/{id}/testSends one signed webhook.test event to the endpoint now and returns the delivery, with the HTTP status the endpoint answered. Use it to check a receiver and its signature check. A test is attempted once and never retried; it works on a switched-off endpoint too. Adds one row to the delivery log.
webhooks:writeCreator needsSYSTEM:SETTINGS:EDITChanges dataParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Endpoint id. Example: |
Responses
- 200Success. Returns WebhookDelivery.
Response fields · WebhookDelivery · 11
| Name | Type | Description |
|---|---|---|
id | string | Delivery id; also sent as X-Webhook-Delivery-Id. Example: |
endpoint_id | string | The endpoint. Example: |
event_id | string | The event's id (the envelope's id). The same event sent to two endpoints has one event_id. Example: |
event_type | string | Event type. Example: |
status | string | PENDING: waiting for its next attempt. DELIVERED: the endpoint answered 2xx. FAILED: gave up after 5 attempts. One of: |
attempts | integer · int32 | Attempts made so far (at most 5). Example: |
response_status | integer · int32 | HTTP status of the last attempt, if the endpoint answered. Example: |
last_error | string | What went wrong on the last attempt, if it failed. |
next_attempt_at | string · date-time | When the next retry happens (UTC), while PENDING. |
created_at | string · date-time | When the event was queued (UTC). Example: |
delivered_at | string · date-time | When the endpoint accepted it (UTC). Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl -X POST "https://coresyncapi.avitechcloud.com/api/v1/webhooks/2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e/test" \
-H "X-API-Key: $CORESYNC_API_KEY"{
"id": "8d9e0f1a-2b3c-4d5e-6f7a-8b9c0d1e2f3a",
"endpoint_id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"event_id": "evt_test_9a8b7c6d5e4f3a2b",
"event_type": "webhook.test",
"status": "DELIVERED",
"attempts": 1,
"response_status": 200,
"last_error": null,
"next_attempt_at": null,
"created_at": "2026-10-25T09:00:05Z",
"delivered_at": "2026-10-25T09:00:06Z"
}Change a webhook endpoint#
/webhooks/{id}Changes the URL, the events, the note, or switches the endpoint off or back on (which also clears an automatic switch-off). Only the fields sent change. The signing secret stays the same.
webhooks:writeCreator needsSYSTEM:SETTINGS:EDITChanges dataParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Endpoint id. Example: |
Request body
Changes to a webhook endpoint. Only the fields you send change.
| Name | Type | Description |
|---|---|---|
url | string | New HTTPS URL. Limits: up to 500 characters. Example: |
events | array of string | The full new list of events (replaces the old list). One of: |
description | string | New note. Limits: up to 200 characters. Example: |
active | boolean | false switches the endpoint off; true switches it back on and clears an automatic disable. Example: |
Responses
- 200Success. Returns WebhookEndpoint.
Response fields · WebhookEndpoint · 10
| Name | Type | Description |
|---|---|---|
id | string | Endpoint id. Example: |
url | string | HTTPS URL events are POSTed to. Example: |
description | string | A note to say what the endpoint is for. Example: |
events | array of string | Events this endpoint receives. |
active | boolean | False when switched off by hand, or automatically after 20 failed attempts in a row. Example: |
disabled_reason | string | Why it was switched off automatically, if it was. |
last_success_at | string · date-time | Last successful delivery (UTC). Example: |
last_failure_at | string · date-time | Last failed attempt (UTC). |
created_at | string · date-time | When the endpoint was added (UTC). Example: |
signing_secret | string | The secret to verify X-Webhook-Signature with. Present only in the response to Example: |
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 422
invalid_webhook - 429
rate_limited - 500
internal_error
Example
curl -X PATCH "https://coresyncapi.avitechcloud.com/api/v1/webhooks/2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e" \
-H "X-API-Key: $CORESYNC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/coresync/v2",
"events": [
"payment.received",
"subscriber.suspended",
"subscriber.reactivated"
],
"description": "Amani Link CRM (production)",
"active": true
}'{
"id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"url": "https://hooks.example.com/coresync/v2",
"description": "Amani Link CRM (production)",
"events": [
"payment.received",
"subscriber.suspended",
"subscriber.reactivated"
],
"active": true,
"disabled_reason": null,
"last_success_at": "2026-10-25T09:00:06Z",
"last_failure_at": null,
"created_at": "2026-10-25T08:00:00Z",
"signing_secret": null
}Delete a webhook endpoint#
/webhooks/{id}Deletes the endpoint and its delivery log. Events stop going to it at once; anything still queued is dropped.
webhooks:writeCreator needsSYSTEM:SETTINGS:EDITChanges dataParameters
| Name | Type | Description |
|---|---|---|
idrequiredpath | string · uuid | Endpoint id. Example: |
Responses
- 204Deleted.
Errors
- 400
invalid_requestvalidation_failedmalformed_bodymissing_parameterinvalid_parameter - 401
missing_api_keyinvalid_api_keyapi_key_revokedapi_key_expired - 403
insufficient_scopekey_owner_lacks_permissiontenant_suspendedtenant_terminated - 404
not_found - 429
rate_limited - 500
internal_error
Example
curl -X DELETE "https://coresyncapi.avitechcloud.com/api/v1/webhooks/2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e" \
-H "X-API-Key: $CORESYNC_API_KEY"HTTP/1.1 204Objects
The objects the operations return and the events carry. Types link here from every field table.
WebhookEndpoint
A URL that receives events. The signing secret is only returned when the endpoint is created.
Returned by listWebhookEndpoints, getWebhookEndpoint, createWebhookEndpoint, updateWebhookEndpoint.
| Name | Type | Description |
|---|---|---|
id | string | Endpoint id. Example: |
url | string | HTTPS URL events are POSTed to. Example: |
description | string | A note to say what the endpoint is for. Example: |
events | array of string | Events this endpoint receives. |
active | boolean | False when switched off by hand, or automatically after 20 failed attempts in a row. Example: |
disabled_reason | string | Why it was switched off automatically, if it was. |
last_success_at | string · date-time | Last successful delivery (UTC). Example: |
last_failure_at | string · date-time | Last failed attempt (UTC). |
created_at | string · date-time | When the endpoint was added (UTC). Example: |
signing_secret | string | The secret to verify X-Webhook-Signature with. Present only in the response to Example: |
WebhookDelivery
One event sent (or being sent) to one endpoint.
Returned by listWebhookDeliveries, sendTestWebhookEvent.
| Name | Type | Description |
|---|---|---|
id | string | Delivery id; also sent as X-Webhook-Delivery-Id. Example: |
endpoint_id | string | The endpoint. Example: |
event_id | string | The event's id (the envelope's id). The same event sent to two endpoints has one event_id. Example: |
event_type | string | Event type. Example: |
status | string | PENDING: waiting for its next attempt. DELIVERED: the endpoint answered 2xx. FAILED: gave up after 5 attempts. One of: |
attempts | integer · int32 | Attempts made so far (at most 5). Example: |
response_status | integer · int32 | HTTP status of the last attempt, if the endpoint answered. Example: |
last_error | string | What went wrong on the last attempt, if it failed. |
next_attempt_at | string · date-time | When the next retry happens (UTC), while PENDING. |
created_at | string · date-time | When the event was queued (UTC). Example: |
delivered_at | string · date-time | When the endpoint accepted it (UTC). Example: |
Tenant
An ISP on CoreSync.
| Name | Type | Description |
|---|---|---|
code | string | The ISP's code. Example: |
name | string | Company name. Example: |
status | string | Account status. One of: |
currency | string | ISO 4217 currency the ISP bills in. Example: |
country_code | string | ISO 3166-1 alpha-2 country. Example: |
timezone | string | IANA time zone the ISP works in. Example: |
Balance
What a subscriber has paid ahead and what they owe.
Returned by getSubscriberBalance.
Money
An amount of money. The amount is a decimal string with two decimals, so it never loses precision.
| Name | Type | Description |
|---|---|---|
amount | string | Decimal amount as a string. Example: |
currency | string | ISO 4217 currency code. Limits: 3–3 characters, 3 letters. Example: |
PlanSummary
A short reference to a plan.
| Name | Type | Description |
|---|---|---|
id | string | Plan id. Pass it to Example: |
code | string | Plan code. Example: |
name | string | Plan name as customers see it. Example: |
price | Money |
Subscriber
A subscriber (an ISP's customer) with their current subscription and balance.
Returned by getSubscriber.
| Name | Type | Description |
|---|---|---|
id | string | Subscriber id. Example: |
account_number | string | The ISP's account number. Example: |
subscriber_code | string | The billing code the customer types as the M-Pesa paybill account reference. Example: |
username | string | PPPoE / RADIUS login name. Example: |
name | string | Full name, or the business name for a business account. Example: |
first_name | string | First name. Example: |
last_name | string | Last name. Example: |
phone | string | Primary phone number in E.164. Example: |
phones | array of string | Every phone number on the account, in E.164 (some accounts carry two). |
email | string | Email address, if the ISP has one. Example: |
type | string | Account type. One of: |
status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
service_type | string | How the subscriber connects. One of: |
address | string | Installation or physical address. Example: |
zone | string | Service zone or area name. Example: |
online | boolean | True while the subscriber has a live session. Example: |
last_online_at | string · date-time | When the subscriber was last seen online (UTC). Example: |
subscription | Subscription | |
balance | Balance | |
created_at | string · date-time | When the account was created (UTC). Example: |
activated_at | string · date-time | When service was last activated (UTC). Example: |
suspended_at | string · date-time | When service was last suspended (UTC), if it is suspended. |
SubscriberChange
The result of a change to a subscriber.
Returned by changeSubscriberPlan, suspendSubscriber, reactivateSubscriber.
| Name | Type | Description |
|---|---|---|
outcome | string | done: the change was made. approval_pending: the ISP requires a manager's approval for this action; a request was filed and the change happens when someone approves it in the admin. One of: |
subscriber | Subscriber | |
approval_request_id | string | The approval request filed, when outcome is approval_pending. |
Subscription
The subscriber's current (or latest) subscription: which plan, and until when.
| Name | Type | Description |
|---|---|---|
id | string | Subscription id. Example: |
status | string | Subscription status. EXPIRED means the end date passed without a renewal. One of: |
plan | PlanSummary | |
starts_at | string · date-time | Start of the current cycle (UTC). Example: |
expires_at | string · date-time | End of the current cycle (UTC). Service stops after this unless renewed. Example: |
auto_renew | boolean | Whether the next cycle is taken from wallet credit automatically. Example: |
price | Money | |
pending_plan_id | string | A plan change scheduled for the next renewal, if any. |
Payment
Money received from a customer: M-Pesa, bank, cash or recorded through the API.
Returned by listSubscriberPayments, listPayments, getPayment, recordPayment.
| Name | Type | Description |
|---|---|---|
id | string | Payment id. Example: |
subscriber | SubscriberRef | |
amount | Money | |
provider | string | Where the money came from, e.g. MPESA, KCB, EQUITY, CASH, BANK. Example: |
method | string | How it arrived: STK_PUSH, PAYBILL, TILL, MANUAL (recorded by staff or the API). Example: |
reference | string | The provider's receipt / transaction reference. Unique per provider. Example: |
payer_phone | string | The payer's phone in E.164, when the provider gives it. Example: |
account_reference | string | What the payer typed as the account / reference. Example: |
status | string | PENDING, COMPLETED, FAILED or REVERSED. One of: |
applied | boolean | True once the money has been credited to the subscriber's wallet / renewal. Example: |
applied_at | string · date-time | When it was applied (UTC). Example: |
not_applied_amount | Money | |
received_at | string · date-time | When the payment was received (UTC). Example: |
SubscriberRef
A short reference to a subscriber.
| Name | Type | Description |
|---|---|---|
id | string | Subscriber id. Example: |
account_number | string | The ISP's account number for this subscriber. Example: |
name | string | Full name, or the business name for a business account. Example: |
phone | string | Primary phone number in E.164. Example: |
SubscriberSummary
A subscriber as listed. Fetch getSubscriber for the plan, subscription and balance in full.
Returned by listSubscribers, lookupSubscribers.
| Name | Type | Description |
|---|---|---|
id | string | Subscriber id. Use it in every /subscribers/{id} operation. Example: |
account_number | string | The ISP's account number. Example: |
subscriber_code | string | The billing code the customer types as the M-Pesa paybill account reference. Example: |
username | string | PPPoE / RADIUS login name. Example: |
name | string | Full name, or the business name for a business account. Example: |
phone | string | Primary phone number in E.164. Example: |
email | string | Email address, if the ISP has one. Example: |
status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
service_type | string | How the subscriber connects. One of: |
online | boolean | True while the subscriber has a live session. Example: |
plan_name | string | Name of the plan on the current subscription, if any. Example: |
expires_at | string · date-time | When the current subscription runs out (UTC). Example: |
credit_balance | Money |
Session
A RADIUS session: one connection of a subscriber (PPPoE) or a hotspot device.
Returned by listOnlineSessions.
| Name | Type | Description |
|---|---|---|
id | string | Session id (RADIUS accounting row id). Example: |
type | string | PPPOE or HOTSPOT. One of: |
username | string | RADIUS username (PPPoE login, or the voucher / MAC for hotspot). Example: |
subscriber | SubscriberRef | |
ip_address | string | IP address assigned to the connection. Example: |
mac_address | string | The device's MAC address, as the router reports it. Example: |
nas_ip | string | The router (NAS) the session is on. Example: |
nas_name | string | The router's name. Example: |
started_at | string · date-time | When the session started (UTC). Example: |
ended_at | string · date-time | When it ended (UTC); null while it is live. |
end_cause | string | Why it ended, as RADIUS reports it (e.g. Lost-Carrier, User-Request, Admin-Reset); null while live. |
duration_seconds | integer · int64 | Length of the session so far, in seconds. Example: |
bytes_up | integer · int64 | Bytes the subscriber uploaded in this session. Example: |
bytes_down | integer · int64 | Bytes the subscriber downloaded in this session. Example: |
SubscriberSession
Whether a subscriber is online right now, with their live session or their last one.
Returned by getSubscriberSession.
Invoice
An invoice issued to a subscriber.
Returned by listSubscriberInvoices, listInvoices, getInvoice.
| Name | Type | Description |
|---|---|---|
id | string | Invoice id. Example: |
number | string | Invoice number as printed. Example: |
subscriber | SubscriberRef | |
plan_name | string | The plan billed, as it was named when the invoice was issued. Example: |
amount | Money | |
status | string | ISSUED: unpaid. OVERDUE: unpaid past the due date. PAID. VOID: cancelled. One of: |
issued_on | string · date | Issue date (ISO 8601 date). Example: |
due_on | string · date | Due date (ISO 8601 date). Example: |
paid_on | string · date | Date it was paid, if it was. |
payment_id | string | The payment that settled it, if any. |
payment_reference | string | Receipt / reference of the settling payment. Example: |
created_at | string · date-time | When the invoice record was created (UTC). Example: |
Plan
A service plan (package) the ISP sells.
Returned by listPlans, getPlan.
| Name | Type | Description |
|---|---|---|
id | string | Plan id. Example: |
code | string | Plan code. Example: |
name | string | Plan name as customers see it. Example: |
description | string | Free-text description. Example: |
type | string | FIXED: a home/business line (PPPoE or static). HOTSPOT: a WiFi voucher package. One of: |
price | Money | |
validity_value | integer · int32 | Length of one cycle, in validity_unit. Example: |
validity_unit | string | Unit of the cycle length. One of: |
download_mbps | number · double | Download speed in Mbps, when the plan has a speed profile. Example: |
upload_mbps | number · double | Upload speed in Mbps, when the plan has a speed profile. Example: |
data_limit_bytes | integer · int64 | Data cap per cycle in bytes; null means unlimited. |
max_devices | integer · int32 | How many devices may be online at once; null uses the ISP default. Example: |
status | string | Plan status. Only ACTIVE plans can be assigned. One of: |
visible | boolean | Whether customers see the plan on self-service pages. Example: |
created_at | string · date-time | When the plan was created (UTC). Example: |
Account
Who you are calling as: the API key, and the ISP it acts on.
Returned by getAccount.
| Name | Type | Description |
|---|---|---|
key | ApiKeyInfo | |
tenant | Tenant |
ApiKeyInfo
An API key, as the API sees it. The secret itself is never returned.
| Name | Type | Description |
|---|---|---|
name | string | The key's name; it is the actor on everything the key does. Example: |
prefix | string | The first 12 characters of the key, to tell keys apart. Example: |
kind | string | TENANT for an ISP's own key (cs_live_…). One of: |
scopes | array of string | What the key may do. |
rate_limit_per_minute | integer · int32 | Requests allowed per minute. Example: |
expires_at | string · date-time | When the key stops working (UTC); null if it does not expire. |
Problem
An error, as RFC 9457 problem details. Branch on code; detail is for people.
| Name | Type | Description |
|---|---|---|
typerequired | string | urn:problem:<code>. Example: |
titlerequired | string | Short summary of the kind of problem. Example: |
statusrequired | integer · int32 | HTTP status. Example: |
detail | string | What went wrong, for a person. Example: |
instance | string | The request path. Example: |
coderequired | string | Stable machine-readable code. Example: |
errors | array of object | Per-field problems, for validation_failed. |
PaymentReceivedData
A payment that was received and applied.
| Name | Type | Description |
|---|---|---|
payment | Payment |
PaymentReceivedEvent
Sent when a payment is received and applied to a subscriber.
| Name | Type | Description |
|---|---|---|
id | string | Event id, unique. The same event delivered twice keeps its id: use it to ignore duplicates. Example: |
type | string | Event type. One of: |
occurred_at | string · date-time | When it happened (UTC). Example: |
tenant | string | The ISP's code. Example: |
data | PaymentReceivedData |
SubscriberStatusData
A subscriber whose service was switched off or back on.
| Name | Type | Description |
|---|---|---|
subscriber | SubscriberRef | |
status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
previous_status | string | Account status. ACTIVE: connected and billed. SUSPENDED: service off (unpaid, expired or by hand). PENDING / DRAFT: being set up. TERMINATED: closed. One of: |
changed_by | string | Who made the change: a staff member's name, an API key's name, or SYSTEM for automation and expiry. Example: |
SubscriberStatusEvent
Sent when a subscriber is suspended (type subscriber.suspended) or reactivated (type subscriber.reactivated).
| Name | Type | Description |
|---|---|---|
id | string | Event id, unique. Example: |
type | string | Event type. One of: |
occurred_at | string · date-time | When it happened (UTC). Example: |
tenant | string | The ISP's code. Example: |
data | SubscriberStatusData |
SessionDownData
A PPPoE session that ended.
| Name | Type | Description |
|---|---|---|
session | Session |
SessionDownEvent
Sent when a subscriber's PPPoE session ends.
| Name | Type | Description |
|---|---|---|
id | string | Event id, unique per session. Example: |
type | string | Event type. One of: |
occurred_at | string · date-time | When the session ended (UTC). Example: |
tenant | string | The ISP's code. Example: |
data | SessionDownData |
WebhookTestData
A test event.
| Name | Type | Description |
|---|---|---|
message | string | Always the same text. Example: |
endpoint_id | string | The endpoint that was tested. Example: |
WebhookTestEvent
Sent by "Send a test event".
| Name | Type | Description |
|---|---|---|
id | string | Event id. Example: |
type | string | Event type. One of: |
occurred_at | string · date-time | When it was sent (UTC). Example: |
tenant | string | The ISP's code. Example: |
data | WebhookTestData |
Stuck, or missing something? Tell us what you're building.
hello@coresyncisp.com