OneCloud API Best Practices
Token Lifecycle Management
Access Tokens
Access tokens are valid for 1 hour while refresh tokens are valid for 24 hours. Please use an access token until it has fully expired then use the refresh token to obtain a new one.
JWT Tokens
JWT tokens are recommended over access tokens and can be decrypted using the jwks file to establish when the token expires. When the token expires, you will need to obtain a new token.
API Keys
API keys can be requested that are valid for an extended time and do not require refresh tokens. This is good for machine-to-machine applications.
Rate Limiting
Thresholds
The OneCloud platform enforces rate limiting at the network level. Exceeding these limits will result in your IP being temporarily blocked with an HTTP 403 response for all http requests — not just the offending endpoint.
These thresholds vary by server configuration. There is no warning before a block is applied — the block takes effect immediately.
Backoff Strategy
If you receive a 403 or 429 response, stop making requests and wait before retrying. Use exponential backoff (e.g., 1s, 2s, 4s, 8s) rather than retrying immediately, as immediate retries will extend the block duration.
Request Requirements
Allowed HTTP Methods
Only the following HTTP methods are accepted:
GET HEAD POST OPTIONS PUT PATCH DELETE
Requests using other methods (e.g., TRACE, CONNECT) will be blocked.
Allowed Content Types
Requests must use one of the following content types:
application/json(recommended)application/x-www-form-urlencodedmultipart/form-datatext/xmlapplication/xml
Requests with unsupported content types will be rejected.
Request Body Size
The maximum request body size is 25 MB (26,214,400 bytes). Requests exceeding this limit will receive an HTTP 400 response.
Request Body Formatting
Request bodies must be well-formed. Malformed JSON or XML payloads will be rejected with an HTTP 400 response. Multipart form boundaries must also be strictly valid.
Data Retrieval
Pagination
Always paginate list endpoints. Never attempt to retrieve an entire dataset in a single request. Use limit and offset parameters to fetch data in bounded pages (e.g., 50-200 records per request).
GET /ns-api/v2/resource?limit=100&offset=0
GET /ns-api/v2/resource?limit=100&offset=100
Avoid Unbounded Loops
Do not use forEach or similar loop patterns that fire many parallel API requests. This will quickly exceed rate limits and result in your IP being blocked.
// BAD - fires all requests at once, will trigger rate limiting (HTTP 403)
items.forEach(item => fetch(`/ns-api/v2/resource/${item.id}`));Instead:
- Use list endpoints with filters to retrieve multiple records in a single request rather than fetching them individually.
- Serialize requests if you must loop — process one at a time with a delay between each.
- Use server-side filtering to reduce the dataset at the source.
// GOOD - single request with server-side filtering
const response = await fetch('/ns-api/v2/resource?filter=domain+eq+example.com&limit=100&offset=0');// ACCEPTABLE - sequential requests with delay
for (const item of items) {
await fetch(`/ns-api/v2/resource/${item.id}`);
await new Promise(resolve => setTimeout(resolve, 100)); // 100ms delay
}CDR and Stats Retrieval
Call Detail Records and statistics endpoints can return very large datasets. Pulling unbounded CDR or stats queries is one of the most common causes of rate limiting, timeouts, and degraded platform performance.
Always Constrain Your Date Range
Never query CDRs or stats without a date range. Use the narrowest window that meets your needs.
// BAD - no date range, attempts to pull all historical CDRs
GET /ns-api/v2/cdrs?domain=example.com
// GOOD - constrained to a single day
GET /ns-api/v2/cdrs?domain=example.com&time_start=ge(2026-04-01T00:00:00)&time_start=le(2026-04-01T23:59:59)
Recommended maximums:
- CDR queries: 24 hours per request
- Stats/analytics queries: 7 days per request
If you need a larger window, break it into multiple smaller requests processed sequentially.
Paginate CDR Results
CDR endpoints can return thousands of records even for a single day. Always use start and limit to paginate results.
GET /ns-api/v2/cdrs?domain=example.com&time_start=ge(2026-04-01T00:00:00)&time_start=le(2026-04-01T23:59:59)&start=1&limit=200
Do Not Loop CDRs Per User
A common anti-pattern is looping through every user or extension to pull individual CDRs. This generates hundreds or thousands of API calls when a single domain-level query with filters would return the same data.
// BAD - one API call per user, will trigger rate limiting
users.forEach(user => fetch(`/ns-api/v2/cdrs?user=${user.id}&limit=1000`));
// GOOD - single query filtered by domain, paginated
GET /ns-api/v2/cdrs?domain=example.com&time_start=ge(2026-04-01T00:00:00)&time_start=le(2026-04-01T23:59:59)&start=1&limit=200Do Not Poll CDRs for Real-Time Data
CDRs are post-call records. If you need real-time call activity, use WebSockets or Event Subscriptions instead of repeatedly polling the CDR endpoint. Polling CDRs every few seconds will result in connection termination.
Stats Aggregation
When pulling statistics, use the highest level of aggregation that meets your needs. Requesting per-extension stats across an entire reseller territory when you only need domain-level totals wastes resources and may time out.
- Query at the domain level, not the user level, when possible.
- Use date-bounded requests — avoid open-ended stat pulls.
- Cache results client-side rather than re-fetching the same data repeatedly.
Polling
We do not allow excessive polling of the OneCloud APIs. If we detect excessive amounts of polling, we will terminate any connections without notice. You may receive a 429 or 403 from your IP when this happens.
WebSockets
We recommend the use of WebSocket connections for real-time data retrieval inside a client application. Socket event listeners will need to be configured on the client application side to respond to updates. This is recommended for always-on client applications.
Subscriptions
We recommend the use of subscriptions when using the APIs for server-to-server communication. Subscriptions will require a callback URL where subscription events will be posted to.
Error Reference
| HTTP Status | Cause | Action |
|---|---|---|
| 400 | Malformed JSON/XML, oversized request body, invalid multipart boundary | Fix the request format or reduce payload size |
| 403 | Rate limit exceeded or WAF block — your IP is temporarily blocked for all requests | Stop all requests, wait for the block to expire, then retry with backoff |
| 429 | Excessive polling detected at the application level | Reduce request frequency, switch to WebSockets or subscriptions |
Updated about 7 hours ago
