Skip to main content

Version 3.20


What is it?

The Simwood Customer API ("Application Programming Interface") is a way for your own back-office systems and web sites to seamlessly integrate with Simwood and manage your wholesale telephony account and services.

What can I do with it?

The API is the preferred way to configure your Simwood services. Everything in the portal can also be configured via the API (and in some cases the API offers some additional functionality) Our portal is based on the API, and everything you can do in the portal you can do through the API in your own code. We’ve deliberately made it this way. The only exception to this is the authentication elements of the portal, as using your API key to log in on the web would be cumbersome.


Some of our customers follow how we do things with interest - this page is for them. If you don’t care, you can safely skip it. The best way to keep up to date with the latest developments behind the scenes is via our blog;


The v3 API, like its predecessors, is predominantly written in PHP served by nginx. nginx takes care of basic HTTPS functions but all header generation is done in code. This way the API can be RESTful in its responses. There is no state maintained in the web-app.


As before, many queries are made against MySQL although we have dedicated servers for the API’s use. These are built for queries and are slaves of masters. We can build additional query servers sideways as required. Writes are, of course, made against the masters. Increasingly, API requests are served directly from our underlying REDIS ram-based data stores where possible.


This API introduces multiple layers in between the above for performance and scale:

Beanstalkd Queues

We use Beanstalkd a lot for internal messaging. In this API where a request is non-trivial and involves other processes, we’ll simply queue a job.


REDIS replaced memcached as our caching data store, and is used for much more as it supports a number of advanced data structures facilitating vastly improved monitoring and real-time information. See for more information.

App Servers

We have numerous daemons running monitoring specific queues (pipes in beanstalkd language). One of the beautiful features of beanstalkd is that it is blocking, i.e. 10 daemons can watch the same pipe and code will block waiting for a response. One, and one only, will be given the job when there is one. This avoids polling – meaning this is extremely efficient and very scalable as we can just spin up as many daemons as required. Further, release of a job to a daemon is sub-millisecond giving the queueing the performance of direct requests. Most complicated jobs involve multiple daemons working through a sequence of queues.

Basic Operations

The Simwood API can be found at the following URI; PLEASE NOTE THAT TLS v1.1 OR HIGHER IS MANDATORY FOR ALL REQUESTS

Basic GET Requests

A number of end-points in the API can be accessed with a simple GET request and will therefore work in a browser. Some do not require authentication and are a good place to start and to test connectivity to the API.

Two simple examples are: - will return your IP address as seen by the API - will return a timestamp from the API

JSON Output Format

You’ll see that in both above cases the output is JSON, e.g:

{"timestamp":1388748052,"rfc":"Fri, 03 Jan 2014 11:20:52 +0000"}

JSON (“JavaScript Object Notation”) is used as it’s a lightweight format designed for exchange of data structures which has an additional advantage of being relatively human readable. All modern languages such as PHP, ASP, .net, Node, Perl etc can handle JSON structures and convert to/from their native objects or arrays easily making it the ideal choice for REST APIs.

“Pretty” JSON

JSON is designed to be machine-readable and as such is sent with minimal whitespace by default however when developing it is often useful to see the output in a more human-friendly format, you can achieve this simply by appending “?pretty=true” to any endpoint e.g would look like this;

"timestamp": 1388748052,
"rfc": "Fri 03 Jan 2014 11:20:52 +0000"

Authenticating Requests

Most commands are linked to an account and therefore require authentication. We use standard Basic Authentication, i.e. your client makes a request, we respond with a 401 response code, your client replies with the API username and password included. Your API username and password were provided at the time of creating your Simwood account, if you do not have these please contact our support team and we’ll be happy to provide you with them.

Note that, at present;

  • Your API username and password is not the same as your portal login details
  • Your API password is designed to be used programatically, and is typically not memorable
  • Your API details allow full access to your account, and must be protected accordingly.
  • You cannot, currently, change your API username or password - although our support team are happy to do so if required (e.g. if your details are lost or you have reason to believe they are compromised)

If you pull up an example URL in your browser it’ll do this for you. For your code, different development languages will tackle this in different ways but most will ‘just deal with it’ automatically for you. cURL for example, will just take the username and password as parameters, e.g.:

curl --user name:password…

PHP’s cURL implementation is very similar in that you’d set CURLOPT_USERPWD with curl_setopt.

An example authenticated GET request is:{ACCOUNT}/prepay/balance

This example URL will not work directly in a web browser as the {ACCOUNT} placeholder in the above will need to be replaced with account ID (typically a six digit number)

Which would return the following


Adding ?pretty=true to the end of the URL would give you the same information in the following format;

"balance": "12.32",

Both are treated equally by a JSON parser, and are syntactically valid, however the ‘pretty-printed’ version may be useful for debugging. Simwood

PUT and DELETE requests

In the spirit of being REST-ful, many URLs can be acted upon with different methods. The URL does not change, only the HTTP method used against it. One example of this is number configuration, for example;{ACCOUNT}/allocated/{NUMBER}

Again, this will not work as {ACCOUNT} and {NUMBER} need replacing with real data. {NUMBER} is the e164 representation of the number, e.g. 442031234567.

GET is the default method, accessing the above end-point with a GET will return the current configuration of that number. PUT will create the end-point, i.e. allocate the number to your account if it does not exist already. DELETE will remove the end-point, i.e. de-configure and remove the number from your account. PUT is context sensitive and specific uses will be described in greater detail within different commands. Briefly though, whereas:{ACCOUNT}/allocated/{NUMBER}

will create a number end-point, i.e. allocate the number but{ACCOUNT}/allocated/{NUMBER}/config

will configure a number, i.e. write the sent config to it. DELETE works more uniformly but only at the level it operates, e.g.{ACCOUNT}/allocated/{NUMBER}

will de-configure and remove a number but{ACCOUNT}/allocated/{NUMBER}/config

will just remove the configuration, leaving the number on your account

Setting the method is language specific and PUT and DELETE cannot be easily replicated in a browser. Almost all environments/browsers will default to GET so the chances are if it doesn’t work as you expect you are using the GET method. For development languages which do not permit all HTTP methods to be used you can pass a hidden parameter named _method in an HTTP POST or GET and set the method to use in there. This will override the actual HTTP method used. For example, in an HTTP form you may use: <input type="hidden" name="_method" id="_method" value="put" />

  • All modern languages allow HTTP methods to be used correctly, and we would strongly encourage this in preference to setting a _method parameter.

POST requests / Reports

POST is very similar to PUT but is used where one is not updating a specific resource, i.e. requesting reports, or when creating a new resource For example, to request a summary of calls and charges for the current day the end-point would be:{ACCOUNT}/reports/voice/summary/day/in

You would use POST for this request as whilst you are sending a request to the server and the end-point is fixed, what that end-point represents and what you get back are variable. POST is used for all report type requests. The output from such a POST request (which requests a report) will typically be small, i.e.:


You will note that this is not in fact a summary of today’s charges. It is a hash that uniquely identifies that report and a link to it. As the return suggests, you can retrieve the actual results with a GET request to{ACCOUNT}/4e591630fedf4aa149db9874fb33fe23.

But don’t worry...

Whilst is is important to understand the effect a given request method will have, we are somewhat relaxed in our interpretation of them where possible. DELETE is always DELETE with no alternative but we will accept a POST instead of a PUT and a GET instead of a POST where possible. You should not assume we will, and should adhere to the RESTful way, but this flexibility is there if you wish to test behaviour in a browser for example.

Report De-duplication

As described above, when you request a report the return will just contain a link to the results. That link will be unique to that specific report, i.e. in the above example the hash for today’s summary will be the same with every request, but only every request today. Tomorrow will generate a different hash. If you make multiple requests for the same report before you retrieve it, duplicates will simply be ignored and the report will only be run once.

However, once a report has been run, the results await your collection within the next 5 minutes. Further requests with the same hash will continue to be ignored as long as that report exists. Once the report is retrieved it will be deleted. Only after a report has been deleted (either by retrieval or expiry), will an identical report request result in a new report.

NB reports expire after 5 minutes, any attempt to access the report after 5 minutes will result in a 404 error, you should therefore build your application to poll the report URL multiple times as soon as possible after submitting your request or use the callback URL detailed below.

Hashes are intended to be generated sensibly. For example, a given report for today will always give the same hash. A different report for today or the same report for tomorrow will give different hashes. Reports on different numbers will generate different hashes. Further, de-duplication will only apply where previous results have not been retrieved.

The intention here is to protect the system from the coder who wishes to request a year’s CDRs every second. He can, but all requests other than the first will be ignored until he retrieves the results. This rather extreme example is actually real and was a consequence of the way the v2 API paginated results and required clients to step through them. More than a few customer implementations reached the end of the results and went into a race condition.

Report Retrieval

As shown above, the return from a report request will give a hash and an encoded URL. The hash can be used to access the results directly, even from another system, using a GET request to, for example:{ACCOUNT}/4e591630fedf4aa149db9874fb33fe23

This URL can be polled at a sensible interval as it will simply return a 204 No Content until the report exists. Once the report does exist, it can be downloaded only once and then will be automatically deleted. To negate the need for polling, clients may instead wish to specify a ‘callback’ URL with their request. This should be POSTed as a variable called ‘callback’. The response to the request will be identical as without it but on successful generation of the report we will make a POST to the URL provided. This will contain a single HTTP POST variable call ‘payload’ which will contain the report hash in JSON format, e.g.:


The client should then GET the report as usual within a maximum of 5 minutes, after which it may expire.

Dates in Reports

Most reports can be run for a range or at a specific date. Where omitted they will generally default to today. Dates are always expressed in MySQL format (YYYY-MM-DD hh:mm:ss), e.g. 2012-01-01 14:30:00

File (Report Output) Handling

Unlike many APIs the Simwood API is asynchronous when requesting some complex reports to improve performance (this is discussed in more detail above) and some POST requests will result in a small response containing a hash and ‘link’ to a file e.g.


The functions below are used to retrieve these;


GETLists uncollected files on the account
"ff98d8d8fdf9dfd178e72b6e6ba207ff" {


GETRetrieve specific file on account, where HASH is the hash returned when the report was requested. File will be deleted after retrieval.

API Endpoints

If the above has all made sense, you should need little more than a list of the available end-points and the HTTP methods they support to get going. This follows and you’ll quickly observe they are hierarchical and hopefully consistent. The method shown indicates behaviour as described earlier.

Each endpoint is documented below in the following format;


GETExplains what happens when the GET method is used
POSTExplains what happens when the POST method is used. Will also explain what parameter is used for
parameter - An example GET / POST or PUT parameter
anotherparam - Another parameter to be sent by POST

Please Note - Where example responses are shown in this documentation they may be reformatted to be more easily human-readable, the actual response will have escaped slashes (e.g. / replaced with \/) and not include any excess white space.

The following conventions are used in describing the URL or other parameters
{ACCOUNT}Where a word is capitalised and enclosed by curly braces { } it must be replaced with the appropriate information e.g. {ACCOUNT} or {IP}
[ on | off ]Where two or more words are separated by the pipe character | and enclosed within square brackets [ ] these are ‘either or’ options. e.g. a url with the form /latest/[1|5|10] allows you to specify any of the following 3 URLs;
Arbitrary values (e.g. /latest/15) are not supported
URLsThe URLs are shown without the leading which must be inserted before the /v3/ when making any API call.
paramnameParameters are shown in italics, these are passed by GET, POST or PUT in the request and do not form part of the URI (except in the case of the GET request, when they are part of the query string after the ? mark)
paramname[]Parameters with square brackets at the end are different and can be thought of as Array Parameters. These can be passed multiple times but even if only one item is being included you must include the [] on the end. For compatibility with some languages (e.g. PHP with Curl) an integer value can be between the square brackets e.g the following two examples are equivalent;


The following tools are made available without authentication to help integrate with the Simwood API.

IP Address

Your IP address, as seen by the Simwood API service

Request Typeresult
GETReturn your external IP address, as seen by the Simwood API


The current server timestamp

Request Typeresult
GETReturns the current timestamp


This tool is provided to help debug requests to the Simwood API. It accepts any request method (GET, PUT, POST, DELETE etc) and returns a human-readable report of the information submitted.

curl ""


curl -X POST ""
Request Typeresult
ANYReturns human-readable report of the request received
Simwood API - Explain Tool
Query ID: swAPI6410ece80eaff
Timestamp: 2023-03-14 21:53:44
HTTP Request Method: GET
API Request Method: GET
== Query String ========================================
Your query string contained 2 elements;
test => 1
pretty => true
== HTTP Post Vars =====================================
No HTTP request body request elements
== JSON Request ========================================
No JSON Request body
== Raw Request ========================================

Simwood API v3

NB As this is intended to be a human-readable report for debugging purposes the format may change at any time, and without notice, and should not be relied upon.

Account Management

Account Type

Your account will be one of the following four types; developer, startup, virtual_interconnect, or managed_interconnect, each have different commercials but are functionally identical. All new accounts start off as ‘Developer’, we encourage you to move to ‘Start-Up’ for production use, and to consider ‘Virtual Interconnect’ or ‘Managed Interconnect’ as your requirements evolve.

The differences between these account types can be found in the Simwood Account Pricing document.

please replace all variables above for the curl command to work. check introduction page to see how you can set envronmental variabls in your lab.
Request Typeresult
GETGet your current account type, and limitations Account type will be one of the following; developer, startup, virtual_interconnect, managed_interconnect
PUTUpgrade or downgrade your account
This option is only available to customers of account_type developer or startup
account_type updgrade to developer(if startup), or upgrade to startup(if developer)

Charges Apply

$.. There is a minimum commitment associated with the Start-Up package, along with other commercial differences. Please see the Simwood Product Brochure for more information


You can migrate between developer and startup at any time. By changing your package type to Start-Up please ensure you are aware of the commercial obligations of this package, including the minimum pre- payment amount (which differs from the developer package) and the minimum total spend per month, which replaces the service charge of the Developer pack.

It is not possible to switch to our Virtual Interconnect or Managed Interconnect options online either via the API or Portal. Please contact us if you are interested in these packages.

If you are unsure, please contact our Operations Desk via eMail to, or call us on 0330 122 3000 to discuss your requirements further.

Credit Account Management

The current status of all invoices on your account is available through the API.

#List of unpaid invoices on account (since June 2010)
curl --user $CARRIER_API_USERNAME:$CARRIER_API_PASSWORD$ACCOUNT/credit/invoices/unpaid

#List of paid invoices on account (since June 2010)

#List of invoices on account (since June 2010)

PDF Copy Invoices


Prepay Account Management


POSTRequests a report of Summary of account movements. If the optional from_date and to_date parameters are not specified will default to today.
from_date Start date of report (in form YYYY-MM-DD)
to_date End date of report (in form YYYY-MM-DD)

Other examples

#GET List all account pre-payments

#GET List last (1) or last ten (10) pre-payments to account

#GET Transfers between this prepay account and others.

#List last (1) or last ten (10) transfers on the prepay account

Prepay Account Balance

The API provides tools for checking and protecting your pre-paid balance(s)

#Return balance of account

Example result

"balance": "168.06100",
"currency": "GBP"

Low Balance Alerts

You can set an amount at which you will receive a notification (configured via the notifications, detailed below) when your balance drops below the specified amount. A maximum of one notification will be sent per day.

#GET  /v3/accounts/{ACCOUNT}/prepay/balance/alert
#Returns the current level of alert.
"account": ACCOUNT,
"alert_balance": 90
#PUT Sets the alert balance to the specified alert_balance
alert_balance #the balance at which an alert should be generated

Balance Locking

We provide the ability to ‘lock’ a portion of your balance to make it unavailable to spend. i.e. you can specify the balance at which we’ll treat your account as ‘out of credit’ and therefore kill calls in progress.

This is normally zero but the balance locking facility enables customers to keep large credit balances without risking the entire amount in the event that they, or a customer, suffer a compromise.

You can set alerts based on the available balance (i.e. balance-locked balance) using the balance alert above.


GETReturns the ‘locked’ balance, this represents a portion of your pre-paid balance that cannot be consumed - e.g. to protect against unexpected spend
PUTSets the protected amount to the specified balance. This amount remains in your account but cannot be spent.
balance The amount to be protected.
DELETERemove the locked balance, allowing the full amount of your pre-paid balance to be used for calls.

NB The above ‘locked balance’ function is provided on a ‘best-efforts’ basis and is not intended as a substitute for securing your own VoIP platform. You remain responsible for all calls made on your account.

Termination Rate Functions

Available Tariffs

Some account types have more than one available tariff or rate deck, these can be viewed as follows where this is applicable to your account;


GETRequest tariffs available on your account, these are shown together with the prefix required for dynamic rate deck selection (no prefix is required for calls using the default rate deck)

Example result

"success": true,
"data": [
"description": “Legacy GBP Platinum",
"servicelevel": 1,
"quality": “Platinum”,
“prefix”: 999001,
"url": “\/v3\/accounts\/929999\/rates\/csv\/Simwood_Platinum.csv"
}, {
"description": “Legacy GBP Gold",
"servicelevel": 2,
"quality": “Gold”,
“prefix”: 999002,
“default”: true,
"url": “\/v3\/accounts\/929999\/rates\/csv\/Simwood_Gold.csv"
] }

Ratecard Downloads (CSV Format)

Our latest termination rates are also always available in CSV and Excel (XLSX) format from the portal or in CSV format via the API;


#Get Request the latest ratecard in CSV Format

NB: The options silver, platinum and gold are only for ‘legacy’ or ‘startup’ account types with multiple rate decks. Virtual Interconnect and Managed Interconnect customers should use default or the file name provided from the above query

Destination Lookup


GETReturns the cost of calling the specified number in your account currency. Each rate array is keyed by the relevant deck (1 - platinum, 2 - gold, 3 - silver) and shows (p)eak, (o)ffpeak, (w)eekend rates and the (c)onnection charge.
#Get Note number is in 164 format. ie UK is 44XXXXXXXXXX