Skip to main content

Overview

API Basics

The API is a RESTful Web Services with JSON formatted messages.

Basically, it means that :

  • Submitting new data is performed with HTTP POST request
  • Retrieving existing data is performed with HTTP GET request
  • Modifying existing data is performed with HTTP PUT request
  • Removing or canceling existing data is performed with HTTP DELETE request

All requests must be sent with the HTTP header Content-Type equals to application/json and be UTF-8 encoded.

Environments

Authentication

All requests require to be fully authenticated through the HTTP header Authorization. The content of the header should respect the format described below.

warning
  • All the requests must be sent from your server directly to our server and not from a user's browser or application.
  • For security reasons, the API Access Key and Secret Key provided by W-HA must be stored securely in your server. It should never be accessible or visible to the end-users.
  • It should not be stored or packaged in any source codes accessible from end-user point of view (html/javascript from a browser or in a source code of an application for Smartphone).
  • The API Keys are accessible in your Dashboard in the Partner section.

Authorization Header

Authorization:AUTH api_access_key:timestamp:version:sign
PropertyTypeValueDescription
api_access_keystringsize = 32 maxAPI Key (provided by W-HA)
timestamplongShould not be aged of more than 5 minutes.Timestamp of the request in milliseconds
versionintegerVersion number of the authentication process
signstringHMAC-SHA256 signature
See below to see how to generate the signature

Signature computation

The sign parameter is a HMAC-SHA256 of the following parameters separated by :

  • api_access_key
  • timestamp
  • version
  • request body (JSON) (could be empty in some cases).

A secret shared key (provided by W-HA) called api_secret_key is used to compute the hash.

  • stringToSign = api_access_key:timestamp:version:request_body
  • sign = HMAC-SHA256(StringToSign, api_secret_key)

Example with a request body

  • api_access_key = OLqMu27t1mylpc2D
  • api_secret_key = YMy7t54-WaF9F!LOSp994p1?0x8pUp
  • timestamp = 1494862655078
  • version = 1
  • request_body = {"tag":"my_new_tag"}
  • stringToSign = OLqMu27t1mylpc2D:1494862655078:1:\{"tag":"my_new_tag"\}
  • sign = 2b6cf86e9f3d5c50a5b7f79aa10c9ce6da1fcd31211bf87374347274c168cf01

HTTP Header

Authorization: AUTH OLqMu27t1mylpc2D:1494862655078:1:2b6cf86e9f3d5c50a5b7f79aa10c9ce6da1fcd31211bf87374347274c168cf01

Example with no request body

  • api_access_key = OLqMu27t1mylpc2D
  • api_secret_key = YMy7t54-WaF9F!LOSp994p1?0x8pUp
  • timestamp = 1494862788453
  • version = 1
  • request_body =
  • stringToSign = OLqMu27t1mylpc2D:1494862788453:1:
  • sign = 1e8b319599fa2185b55e502ed962490e9e23aceb920676e17c0ac76112d5450a

HTTP Header

Authorization: AUTH OLqMu27t1mylpc2D:1494862788453:1:1e8b319599fa2185b55e502ed962490e9e23aceb920676e17c0ac76112d5450a

Simplified sample in JAVA (with RestTemplate)

private static final String HEADER_FIELD_SEPARATOR = ":";

private String getAuthHeader(String apiKey, String apiSecret, String requestBody) {

String timestamp = "" + new Date().getTime();
String version = "1";

//stringTosign
String stringToSign = apiKey + ":" + timestamp + ":" + version + ":";
if (requestBody != null) {
stringToSign += requestBody;
}

//sign
String sign = EncodingUtils.encodeHmacSha256(stringToSign, apiSecret);

//header
String authHeader = "AUTH " + apiKey + ":" + timestamp + ":" + version + ":" + sign;
return authHeader;
}

public AccountDto getAccount(String accountId) {
//headers
HttpHeaders headers = new HttpHeaders();
headers.add(HEADER_AUTHORIZATION, this.getAuthHeader(apiKey, apiSecret, null));

try {
ResponseEntity responseEntity = restTemplate.exchange(baseUrl + "/accounts/" + accountId, HttpMethod.GET, new HttpEntity<>(headers), WalletDto.class);
return responseEntity.getBody();
} catch (HttpStatusCodeException e) {
//error management
} catch (RestClientException e) {
//error management
}
}

public SimpleExternalId createStandardAccount(AccountStandardRequest request) {
//convert body to JSON for signature computation
ObjectMapper objectMapper = new MappingJackson2HttpMessageConverter().getObjectMapper();
String requestBody = objectMapper.writeValueAsString(request));

//headers
HttpHeaders headers = new HttpHeaders();
headers.add(HEADER_AUTHORIZATION, this.getAuthHeader(apiKey, apiSecret, requestBody));

try {
ResponseEntity responseEntity = restTemplate.exchange(baseUrl + "/accounts/standard", HttpMethod.POST, new HttpEntity<>(requestBody, headers), SimpleExternalId.class);
return responseEntity.getBody();
} catch (HttpStatusCodeException e) {
//error management
} catch (RestClientException e) {
//error management
}
}

Versioning

Minor API modifications that are not breaking the compatibility with the existing API should be supported transparently by the partner.

Example of non-breaking changes:

  • adding new API endpoint/service
  • adding some optional parameters in request header, query or body of existing API
  • adding some optional new properties in the response header or body of existing API
  • adding new possible values in ENUM parameters of a request
  • changing the order of properties in a response
  • changing human-readable strings such as error message
  • changing size or format of generated ids (object identifier) but respecting the documented maximal size

Major API modifications breaking the compatibility will be managed through a new version number in the API URL.

Example of breaking changes:

  • renaming or removing existing endpoint/service
  • renaming or adding mandatory parameters in the request header, query or body
  • renaming or removing parameters in response header or body
  • restricting allowed values of an ENUM in a request

Lists Pagination Management

Some Web Services return a list of elements (i.e GET /wallets return a list of Wallets). Responses of these services are based on a pagination mechanism to control the number of returned elements. By default, the response is the first page and the maximum number of returned elements is 20. This behavior can be changed for a requests by setting the following parameters :

URL - ParametersTypeValueDescription
pageintegermin = 1
optional
default = 1
Requested page index
per_pageintegermin = 1
max = 100
optional
default = 20
Maximum of element number per page

The response HTTP body contains the list of elements and the response HTTP header includes the following properties:

Header - PropertyTypeDescription
x-pageintegerRequested page index (equals to the request parameter page if it is set)
x-page-sizeintegerCapacity for a page (equals to the request parameter per_page if it is set)
x-total-elementslongThe overall amount of elements corresponding to the search criteria (without pagination)
x-total-pagesintegerThe number of pages corresponding to the search criteria

Error management

If a request failed, HTTP status code of the response is different of 200 (or associated 201, 204 ...) and the body contains an error object structuring the detailed cause of the problem.

HTTP error code

CodeDescription
400 Bad requestSee error code / message in response body.
401 Authentication failureAuthentication failed.
403 ForbiddenAuthentication is OK but you are not authorized to access this method.
404 Not foundError on hostname or URI.
405 Method not allowedWrong utilization of the method (e.g. GET instead of POST).
500 The server encountered an unexpected conditionIn case of internal error.
501 Not ImplementedNot supported.
503 Server busy and service unavailableService temporary unavailable. Try later.

Error Object

PropertyTypeValueDescription
codestringsize = 4Error code
messagestringmax size = 300Error message

Response Sample

HTTP/1.1 400 Bad Request
{
"code": "1004",
"message": "Invalid parameter(s)"
}

List of Error codes

CodeMessageHTTP Status Code
9001Internal error500
1001Unknown service version400
1002Authorization error401
1003Service forbidden403
1005Invalid request JSON format400
1006Invalid request parameter(s)400
2001Unknown Wallet id400
2002Wallet invalid status400
2003Wallet invalid type400
2004Operation not permitted because balance=******400
2101Operation not permitted.400
2102Partner not available.400
2150API Key doesn't exist400
2151API Key cannot be deleted because this key is Active400
2201Unknown Account id400
2202Account invalid status400
2203Account invalid type400
2204Account invalid kyc level400
2205Invalid Birthdate - Minimum age required is ****400
2206Account already exist400
2207Account: KYC data remove not allowed '*****'400
2208Account: KYC data update not allowed '*****'400
2211Operation not permitted because Account Validation is in progress400
2212Account information and kyc level '*****' are not consistent, infos: *****400
2213Requested Level must be greater than current400
2214No valid Document of type '*****'400
2220Kyc Status required400
2231Unknown Document id400
2232Document invalid status400
2233Unknown Document File id400
2235Document type 'PROOF_OF_IBAN' cannot be manage independently of Bank Account400
2251Document invalid format400
2252Document unreadable400
2253Document expired400
2254Document invalid400
2255Document not compliant400
2256Document with missing page400
2301Unknown BankAccount id400
2302BankAccount invalid status400
2303IBAN not SEPA zone400
2304IBAN not authorized400
2305BIC not SEPA zone400
2306BIC not authorized400
2307IBAN already exists400
2308Maximum number of Bank Accounts reached for the Account400
2309IBAN Proof file is missing400
2310BankAccount can't be deleted as part of KYC400
2320IBAN overused400
2330BankAccount VOP check not available400
2331BankAccount VOP check IBAN invalid400
2332BankAccount VOP check not match400
2351Unknown CreditCard id400
2352CreditCard invalid status400
2353Unknown CreditCard id400
2354CreditCard invalid status400
2355CreditCard not supported400
2401Unknown Transaction id400
2402Transaction invalid status400
2403Transaction invalid type400
2404Transaction invalid payment method400
2405Invalid parameters: fees are greater than amount400
2406Invalid parameters: fees wallet id is missing400
2407Invalid parameters: sender wallet and bank account are not associated to the same account400
2408Invalid parameters: transaction partner ref invalid (must be unique)400
2409Invalid parameters: sender and receiver are equals400
2410Invalid parameters: wallets have incompatible currencies400
2411Transaction not allowed type400
2420Transaction authorization is timed-out400
2421Transaction authorization failure400
2422Transaction confirmation failure400
2423Transaction cancellation failure400
2424Transaction refund failure400
2425Transaction refund impossible as it is a REFUND transaction400
2426Transaction refund impossible : invalid requested amount or fees400
2427Transaction is fully refunded400
2428Transaction confirmation failure : the confirmation amount exceed the authorized one400
2429Transaction is timed out because payment process not initiated by user400
2430Transaction is timed out because 3ds process not completed by user or is failed on PSP side400
2431Transaction failed because the 3ds process failed by user400
2432Transaction failed (3ds process has succeeded but an error occurred during the final redirection)400
2433Transaction rejected400
2434Transaction too old to be refunded400
2435Transfer not allowed : Account has too low KYC level to transfer to an Account Standard400
2436Transfer not allowed : Account has too low KYC level to transfer to Account Business400
2437Transaction not validated by end-user400
2451Transaction amount cannot be less than '******'400
2452Wallet '******' insufficient balance.400
2453Transaction amount cannot be greater than '*****'400
2461Account has reached is BALANCE MAX limit400
2462Account has reached is CASH_IN MONTHLY MAX limit400
2501Unknown Wallet Activity id400
2601Transaction Bank Account invalid status400
2651Transaction Bankwire invalid status400
2652The transaction Bankwire payment amount is too high400
2653The transaction Bankwire payment amount is too low400
8001Invalid Currency Code400