We work with a growing network of 8000 partners globally including OTT platforms, long distance calling apps, financial institutions, retailers, POS providers and more.
TABLE OF CONTENTS
The Ding API is a Level 0 REST web service. We have used the swagger standard to describe this service. As a result, we are able to provide an interactive documentation page, which lists all the methods and even allows you to interact with API, showing the request bodies and responses that you will receive from the API.
To generate an API Key, you should go to the Developer tab which can be found in the Account Settings section of your DingConnect account.
Enter the API Key
into the token input box on top-right of the Methods page Methods and click the button.
Then browse the API definition and interact with the API from that page. Using this interface you can figure out the
headers,
request bodies and responses that your software will need to send to interact with the API.
The swagger definition can also be used to automatically generate client SDK libraries in many different languages. Many free and commercial code generators are available that can consume this swagger definition and generate client code for you, allowing you to rapidly develop your application. For example, you can import our swagger definition into the online service provided at http://editor.swagger.io and from that interface you can generate client code in over 20 different programming languages.
The URL for our swagger definition is in the URL text box on the Methods page and ends with
/swagger/docs/v1
.
The DingConnect API supports authorisation using API Keys and OAuth. For any new integration, our recommendation is to use OAuth.
All requests to the API must be authenticated. Any exceptions to this rule are documented in the individual API methods.
All requests can include an optional header X-Correlation-Id
that can be used to correlate HTTP requests between a client and server.
This header will be useful to diagnose potential issues that integrated clients might encounter.
The client must include an HTTP header api_key
using the API key that was issued to you.
If authentication fails, you will receive a HTTP 401 response.
The only supported OAuth flow is the client credentials flow, which is used only for server-to-server API requests. In order to use OAuth, a new OAuth client must be registered in your DingConnect account.
OAuth credentials are managed from within the DingConnect portal, by navigating to the Developer tab in Account Settings.
Once new OAuth credentials are generated, a bearer token can be requested from https://idp.ding.com/connect/token with the client_id and client_secret. The returned token must be included in the Authorization header with the “Bearer” authentication scheme. A new token must be requested once the current token expires.
Supported identity provider configuration can be obtained from: https://idp.ding.com/.well-known/openid-configuration, and used programmatically with client libraries.
Example response
{
"issuer": "https://idp.ding.com",
"jwks_uri": "https://idp.ding.com/.well-known/openid-configuration/jwks",
"token_endpoint": "https://idp.ding.com/connect/token",
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"id_token_signing_alg_values_supported": [
"RS256"
]
}
In order to request a token, a valid client_id and client_secret must be used, as documented above.
Parameter | Type | Description |
---|---|---|
client_id | string | Client Id |
client_secret | string | Client secret |
grant_type | string |
Must be client_credentials .
|
Token will stay valid for the duration that was specified when creating the client/credentials.
Example request
POST https://idp.ding.com/connect/token HTTP/1.1
Host: idp.ding.com
Content-Type: application/x-www-form-urlencoded
client_id=44c61ca4-b3c0-4604-9d25-ad1e486f33f2
&client_secret=4mVCwicZXgbB6wJFPeh1D+xLlkeW34JN+y449hZYdUc=
&grant_type=client_credentials
Example response
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFDQTY1OUI2ODk
0RTdDQzNDRDc5MjM1OTNBMEFCNTY1IiwidHlwIjoiYXQ
rand0In0.eyJuYmYiOjE1OTg1MjY3MDQsImV4cCI6MTU
5ODUyODUwNCwiaXNzIjoiaHR0cDovL2lkcHNlcnZpY2U
6OTkwMCIsImF1ZCI6ImRpbmdjb25uZWN0YXBpIiwiY2x
pZW50X2lkIjoiNDRjNjFjYTQtYjNjMC00NjA0LTlkMjU
tYWQxZTQ4NmYzM2YyIiwianRpIjoiQUYxQUFENTU1RUM
zQzk3NUIyNkVCQjFDRjhGM0Q4NTQiLCJpYXQiOjE1OTg
1MjY3MDQsInNjb3BlIjpbInRvcHVwYXBpIl19.nEFikzy
qNk_YjFOyJ95n_HLebhP7jW4FzPVPEKdLpBZaC8-7CELj
NDcbSnfxBKMBq1xb506azZ5dcs6AVVHHKBsDfKww8pQyL
-R1SBuGN1BHtYpr-DKYnR52Y2Ga7BR5CQ0owtTmLk24z_
Fze2Ocw0eZpFk_3tLldrYg92w4shq88tUHy_9xLXnfch
sTND6Zpx4nav8cSR1vFmdEIIkcaMJzpVdiuvZcSrSbkd
2HVIKqq4K8jfP572EdeAk0ZW7jWsv2BJlk0HvpFW6s6q
TTXHToF7ZJgF0GSRSBiWn_E1Sr1bZxxHB55rR3v8y8r_
7TVkfmWRvZTDzHfqxCih7j5g",
"expires_in": 1800,
"token_type": "Bearer",
"scope": "topupapi"
}
Please note that expire_in
value is in seconds.
The Authorization header must be populated with the access token using the “Bearer” authentication scheme.
Example request
GET https://api.dingconnect.com/api/V1/GetRegions HTTP/1.1
Host: api.dingconnect.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjFDQTY1OU
I2ODk0RTdDQzNDRDc5MjM1OTNBMEFCNTY1Iiwi
dHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTgzNz
MwOTEsImV4cCI6MTU5ODM3NDg5MSwiaXNzIjoi
aHR0cDovL2lkcHNlcnZpY2U6OTkwMCIsImF1ZC
I6ImRpbmdjb25uZWN0YXBpIiwiY2xpZW50X2lk
IjoiN2Q5ZmVlOTAtZjFjYi00NmNhLTlkMTUtYz
YyNmQxMjkxYjFmIiwianRpIjoiRjY3RjNDMDFF
MURGMDY4REFCNTIxMjVGMjM4NTREOEYiLCJpYX
QiOjE1OTgzNzMwOTEsInNjb3BlIjpbInRvcHVw
YXBpIl19.aglCy-aPOIqNR5W9lX9dBrd0mQSGb
mv_3kHAAtZpbq_67fCefLe2us-TjpZ_RQJ1cud
365rfB4TPXzoVpGGPY4E2dzu1jQ8Ubz2PsroO9
fgizcxgaic_Lwl5apHddvWdl9evgB90z1kXPXl
PZBEoxdFqkpOFt4HaKk2iOcfsoBDudvvdoT_xQ
SklJkAmInfLN9SKms5TgeIifwIEOwvmKcBMMaJ
UoaPyMv1af8FysyQanZFuem-Yt5deSPOenryZS
sCrubih59aF36nPU7J6lmQWdtmSBSMbrEfXlzG
JRanlpHQPTplNTynVSAegKZa9L-NpeI3GbQ5qa
gfKLE0SOg
When a token expires, a new token must be requested, as documented above in “Getting Tokens”
Token expired example response
{
"ResultCode": 4,
"ErrorCodes": [
{
"Code": "AuthenticationFailed",
"Context": "TokenExpired"
}
]
}
Test the API by clicking the Run In Postman button. This will create a fork of our API Collection in Postman.
Once loaded, edit the Collection variables to add your API key to the api_key
variable, and you’re all set.
Deferred SendTransfer is a special type of SendTransfer that gives you the ability to get notified with HTTP callback (aka webhook)
when the transfer is completed. You will get an immediate response with ProcessingState=Submitted
and the final transfer
result will be sent as webhook notification.
When there are failures the transfer will be retried until it is completed successfully or the maximum retry threshold is reached and only then will a notification be sent.
To send deferred transfer, you need to:
SendTransfer response notifications are sent using HTTP callbacks (aka webhook). Your endpoint needs to be public. DingConnect only
supports HTTPS endpoints.
Consider adding the Ding domain and IP addresses to your firewall whitelist. For more information please contact support.
To send deferred SendTransfer, you need to:
X-Options
and X-Correlation-Id
headers. Where X-Options
is set to
DeferTransfer
and X-Correlation-Id
is set to the id number that you will use to identify this
send transfer when you receive response notification.
When the SendTransfer request is sent using X-Option: DeferTransfer
header response will be returned immediately
with the ProcessingState set to “Submitted” and final transaction result will be sent to the notification server endpoint
previously setup. The notification response will contain X-Correlation-Id
header you provided.
POST https://api.dingconnect.com/api/V1/SendTransfer HTTP/1.1
Host: idp.ding.com
Content-Type: application/json
X-Options: DeferTransfer
X-Correlation-Id: 95E0578C-247C-4235-8AAC-BB901BBCCA9B
{
"SkuCode": "AF_AW_TopUp",
"SendValue" : 1,
"AccountNumber" : "93000000000",
"DistributorRef" : "12345",
"ValidateOnly" : false
}
{
"TransferRecord": {
"TransferId": {
"TransferRef": "134",
"DistributorRef": "12345"
},
"SkuCode": "AF_AW_TopUp",
"Price": {
"CustomerFee": 0.00,
"DistributorFee": 0.00,
"ReceiveValue": 76.0,
"ReceiveCurrencyIso": "AFN",
"ReceiveValueExcludingTax": 68.40,
"TaxRate": 10.0000,
"TaxName": "AIT",
"TaxCalculation": "Inclusive",
"SendValue": 1.0,
"SendCurrencyIso": "USD"
},
"CommissionApplied": 0.0,
"StartedUtc": "2021-12-06T14:32:50Z",
"CompletedUtc": "2021-12-06T14:32:51Z",
"ProcessingState": "Submitted",
"ReceiptText": null,
"ReceiptParams": null,
"AccountNumber": "93000000000"
},
"ResultCode": 1,
"ErrorCodes": []
}
When request is competed endpoint will be called with completed transfer response.
{
"TransferRecord": {
"TransferId": {
"TransferRef": "33",
"DistributorRef": "12345"
},
"SkuCode": "AF_AW_TopUp",
"Price": {
"CustomerFee": 0,
"DistributorFee": 0,
"ReceiveValue": 76.0,
"ReceiveCurrencyIso": "AFN",
"ReceiveValueExcludingTax": 68.40,
"TaxRate": 10.000,
"TaxName": null,
"TaxCalculation": null,
"SendValue": 5,
"SendCurrencyIso": "USD"
},
"CommissionApplied": 0,
"StartedUtc": "2021-12-09T21:40:15Z",
"CompletedUtc": "2021-12-09T21:40:15Z",
"ProcessingState": "Complete",
"ReceiptText": null,
"ReceiptParams": null,
"AccountNumber": "93000000000"
},
"ResultCode": 1,
"ErrorCodes": []
}
All requests and responses are formatted using the JSON interchange format https://www.json.org/. Parsers are available for all modern programming and scripting languages and are generally very easy to use. This format was chosen because it allows us to add new fields to our responses and to evolve our API over time without breaking conforming parsers.
You should not attempt to manually parse responses using regular expressions as extra fields can be added over time and there is every chance that the ordering of fields may change over time due to 3rd party framework and library upgrades. However a conforming parser will seamlessly handle these changes and your integration with our API will not break.
Every API response will contain a high level integer result code that broadly indicates the success, failure or otherwise of the actual call.
These are the top level ResultCode
values that you can receive:
ResultCode | HTTP Status | Meaning | Description |
---|---|---|---|
1 | 200 | Success. | The API call was processed successfully |
2 | 200 | Success With Warning. | The API call was processed successfully, but there was a warning. Use the ErrorCodes for further details on the warning. |
3 | 503/429 | Transient Error. |
The API call failed because of some transient error. The request can
be retried later. You can retry but should contact Ding if
the error persists. There will be a Retry-After HTTP header
indicating when to retry the request.
|
4 | 400/401 | Client Error. | The submitted request contained bad parameters. Do not retry with the same parameters. The caller must fix the input parameters before retrying. |
5 | 500 | Server Error. | The parameters for the request are correct, but the server was unable to process them. Do not retry with the same parameters. You must contact Ding to resolve the situation. |
In cases where the response does not succeed, the ErrorCodes
array will contain one or more string
error
codes
that indicate why the request failed.
You can use the GetErrorCodeDescriptions
API call to get human readable error messages for each string
in
the
ErrorCodes
array.
Note that the top level set of ResultCode
values will never change. However, we will continue to add
more
ErrorCodes
on an ongoing basis. It would be dangerous to assume that the list of possible error codes
will not
change.
A full list of codes is listed below in the Error and Context Codes section below
The API tries to minimize the amount of data returned in each call. To do this, we use codes as much as possible. For example, we use standard country & currency ISO codes. We also have our own codes for Products and Providers.
There are API calls for retrieving the list of items and their code.
GetProviders
will contain a list ofProvider
objects which, in turn, will contain itsProviderCode
.
This code is then used in the definition of a Product
.
ThenGetProducts
will contain a list of objects that each have aSkuCode
.
ThisSkuCode
is used inSendTransfer
.
The idea with the various Get methods is that you should be able to cache the results in your
application and
you
will rarely need to call them again. This kind of caching
will greatly speed up the performance of your application by avoiding repeated, unnecessary calls to the server. But
your application should not cache forever: instead it should honor the Cache-Control
headers that are returned in the HTTP response headers. Many programming languages already have libraries that can
interpret these headers correctly and we recommend their use.
In addition to reference data codes, we try to separate language-specific descriptions from the objects to which they apply. In some cases a description can be quite long and it may perhaps contain formatting information.
Products
can have long descriptions.
Promotions
can have detailed terms and conditions.
Each of these textual descriptions can be for multiple languages.
Each item that can be localized will have a LocalizationKey
property. This localization key is used to
find the
full
text appropriate to that object in the corresponding item Descriptions
API call.
GetProductDescriptions
is used to lookup localizations for products.
GetPromotionDescriptions
is used with promotions.
Localizations will be returned in multiple languages. There will always be English (en) translations. Not all items will have translations in all languages, so when filtering by languageCode you should always request the en language as well as the intended target language.
Note that large blocks of text should be parsed as CommonMark. This will allow you to apply your own styling.
Again, the localization data is highly cacheable and you should load the localizations for your languages at intervals. Again, please pay attention to the cache control headers and refresh your cache when appropriate.
Many of the APIs return lists of items that can be filtered using parameters. For optimal usage, you should understand how parameters in the same request interact.
For all APIs, submitting no filter parameters will mean that all items will be returned.
Almost all filter parameters are arrays. This means that you can submit multiple values for the given parameter and the API will find items that have any of those values. In database terms, for a particular named parameter, all values provided are OR'd.
For theGetProducts
API, you could submitcountryIsos
of [JM,HT]
The API method will return all products that have a countryIso of HT or JM.
It is possible to submit values for different named parameters in combination. The API will try to find items that satisfy all of those combinations. In database terms, with different named parameters the values are ANDed.
For theGetProducts
API, you could submitcountryIsos
of [JM] and abenefits
value of [Data].
The API method will return products that have both a country of JM and the Data benefit.
You can combine this effect in a powerful way by combining multiple values for different named parameters.
For theGetProducts
API, you could submitcountryIsos
of [JM,HT] andbenefits
of [Data,Utility].
This would return all products that have Data or Utility benefits in Jamaica or Haiti.
In some of our API methods the number of items returned are bounded.
There are a limited number of countries and currencies in the world and we don't mind giving you that entire list.
However in some of our APIs the number of items returned could be unbounded and may return many items.
The number of transfers that you have done last month could number in the thousands.
For unbounded lists, we will not return the entire list. Instead we will return pages of data and you must request each page.
With unbounded lists, you can use Skip
and Take
parameters to indicate how many records to
skip from the
beginning
of
the list and how many items to take.
Skip=0
will skip no items in the list, and so represents the start of the list.
Skip=10
will skip ten items and so the eleventh item will be the first one returned.
Skip=0, Take=10
will start at the beginning of the list and return 10 items.
Skip=10, Take=10
will skip the first 10 items and return the next 10 items. This would be items 11-20
In this manner you can page through data. The API indicates when there are more items available by setting
ThereAreMoreItems=true
. When this property is false
, then there is no more data. If you
fetch
another page, it will be empty.
Note that Take
has a maximum of 100 and we will only allow you to Skip
a maximum of 500
records. This
allows a maximum of 600 records to be retrieved.
Some of our API methods support batching. This is the ability to submit multiple input items where each input item is processed individually. Each input item can succeed or fail independently and so the response needs to be able to report on the success or failure of each one.
Each batch request will contain an array of input items that are POSTed in the body of the request. Each of these
items must contain a string BatchItemRef
property that will uniquely identify the item within the
overall request.
The response will contain a list of items, each of which will contain individual BatchItemRef
,
ResultCode
and ErrorCodes
properties as well as any other properties that are relevant to the particular method
you
called.
The BatchItemRef
is the unique code you submitted in the input item. The ResultCode
and
ErrorCodes
are the
result and errors for that particular input item. If the ResultCode
is success (see Responses above),
then
other properties in the result item will be populated. If the ResultCode
is not success, then you
should
process the ErrorCodes
array for this input item.
In this way, we can report on the success or failure of individual input items.
It is important to realize that, just like other API methods, there is still an overall success or failure for the overall request. If the overall request has failed, then none of the individual input items will have been processed. Only if the overall request has succeeded should the individual items be considered. Note that it is entirely possible for the overall request to succeed, even if all the input items failed.
Please note that the ordering of the items in the response list is not guaranteed to be in the same order as you submitted.
Please note that for every successful SendTransfer the limits for each method will be reset to their original value.
Method | Requests/10 minutes |
---|---|
get /api/V1/GetErrorCodeDescriptions | 20 |
get /api/V1/GetCurrencies | 20 |
get /api/V1/GetRegions | 20 |
get /api/V1/GetCountries | 20 |
get /api/V1/GetProviders | 50 |
get /api/V1/GetProviderStatus | 50 |
get /api/V1/GetProducts | 50 |
get /api/V1/GetProductDescriptions | 50 |
post /api/V1/SendTransfer | Unlimited |
post /api/V1/SendTransfer (Validate Only) | 100 |
post /api/V1/EstimatePrices | 50 |
get /api/V1/GetBalance | 50 |
get /api/V1/GetPromotions | 50 |
get /api/V1/GetPromotionDescriptions | 50 |
post /api/V1/ListTransferRecords | 50 |
post /api/V1/CancelTransfers | 50 |
get /api/V1/GetAccountLookup | 50 |
SkuCode
.
ProviderCode
. Providers can
have an identical ShortName
in different countries, but they are legally different entities. Many of
our providers are mobile phone operators.
This is a feature to to reject SendTransfer requests with a DistributorRef already used for a SendTransfer request either in progress or a has been Successful in the past 60 minutes.
In the case the DistributorRef was already used, you will receive HTTP 400 with ResultCode of 4 and the error Code "DuplicateTransactionPrevented"