API Reference
Wave Business APIs provide a programmatic means to work with your Wave business account. Using these REST APIs, you can collect money and check the balance on your wallet. To use these APIs, you need a Wave business account.
For an overview and quick start instructions, see our Getting Started with the Wave Checkout API guide.
Base URL
All the endpoint paths referenced in the API document are relative to a base URL, https://api.wave.com.
Authentication
Authenticating to the API is done via API keys. These keys are bound to a single business wallet and can only interact with it.
If you need to interact with more than one wallet in your network, then you will have to obtain one key per wallet.
Each request must be sent over HTTPS and contain an authorization header specifying the bearer scheme with the api key:
Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6
Note that the actual key is much longer but for documentation purposes most of the characters have been replaced by an ellipses.
Obtaining your API key
You can manage API keys in the developer's section in the Wave Business Portal. You can create, view, and revoke keys, and define which specific APIs each key has access to.
When you create a new API key, you will only see the full key once. Make sure you copy it without missing any characters, since it will be masked afterwards for security reasons.
Wave doesn't know your full key, but if you contact API support we can identify them by the last 4 letters that you see displayed in the business portal.
Error codes
In the authentication phase, one of the following errors can cause your request to return early:
Status | Code | Descriptions |
---|---|---|
401 | missing-auth-header |
Your request should include an HTTP auth header. |
401 | invalid-auth |
Your HTTP auth header can't be processed. |
401 | api-key-not-provided |
Your request should include an API key. |
401 | no-matching-api-key |
The key you provided doesn't exist in our system. |
401 | api-key-revoked |
Your API key has been revoked. |
403 | invalid-wallet |
Your wallet can't be used in this particular API. |
403 | disabled-wallet |
Your wallet has been temporarily disabled. You should still be able to use the endpoint to check your balance. |
Rate limiting
Wave APIs are rate limited to prevent abuse that would degrade performance for all users. If you send many requests in a short period of time, you may receive 429 error responses.
Requests
Here's an example of how you can construct a POST request with
Authorization
andContent-Type
headers and JSON data:
curl \
-X POST \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6' \
-H 'Content-Type: application/json' \
-d '{
"amount": "1000",
"currency": "XOF",
"error_url": "https://example.com/error",
"success_url": "https://example.com/success"
}' \
https://api.wave.com/v1/checkout/sessions
const axios = require('axios');
axios.post('https://api.wave.com/v1/checkout/sessions', {
amount: "1000",
currency: "XOF",
error_url: "https://example.com/error",
success_url: "https://example.com/success"
}, {
headers: {
'Authorization': 'Bearer wave_sn_prod_YhUNb9d...i4bA6',
'Content-Type': 'application/json'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
"amount" => "1000",
"currency" => "XOF",
"error_url" => "https://example.com/error",
"success_url" => "https://example.com/success"
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
import okhttp3.*;
import org.json.JSONObject;
public class Main {
public static void main(String[] args) {
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, new JSONObject()
.put("amount", "1000")
.put("currency", "XOF")
.put("error_url", "https://example.com/error")
.put("success_url", "https://example.com/success")
.toString());
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions")
.method("POST", body)
.addHeader("Authorization", "Bearer wave_sn_prod_YhUNb9d...i4bA6")
.addHeader("Content-Type", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Wave API requests use HTTP bearer authorization and, for those with a body, JSON format and UTF-8 encoding. All requests should be sent with HTTPS.
Methods
Wave API requests use the HTTP GET
or POST
methods.
The GET
method is used to retrieve resources. GET
requests are idempotent and will not change any data on the server.
The POST
method is used to create new resources.
Headers
For authentication, the Authorization
header must be included in the request. The value consists of the auth scheme, Bearer
followed by the api key:
Authorization: Bearer <API key>
For requests which include a body, the Content-Type
header must specify that the body is JSON:
Content-Type: application/json
Body
Some Wave API requests include data. That data must be in JSON format and use UTF-8 encoding.
Responses
Wave API responses use HTTP status codes to indicate whether a request has been completed successfully. 2xx codes indicate that the request was successful received, understood and accepted. 4xx codes signal a problem with the request from the client and 5xx codes indicate a problem on the server end. See Errors for more information about error responses.
For a response to a successful API request, the message body contains information provided by the server in JSON format (using UTF-8 encoding).
For a response to an unsuccessful request, the message body includes details about the error in JSON format (using UTF-8 encoding). Minimally, this includes a short error code and a longer user-readable message describing the reason for the failure.
Errors
When an API request cannot be completed successfully, the response provides information about the failure in the message body and in the HTTP status code.
Error details
Here's what the message body of a response to an invalid request might look like:
{
"code": "request-validation-error",
"message": "Request invalid",
"details": [{
"loc": ["payments", 1, "mobile"],
"msg": "field required"
}]
}
In response to unsuccessful requests, Wave provides details about the error in the message body. This includes, minimally, a short code
and longer user-readable message
describing the error. For validation errors, Wave may also provide details
of what failed including the field that failed validation and the problem with it.
Status codes
The general reason for the failure is reflected in the HTTP response status code. 4xx codes signal a problem with the request from the client and 5xx codes indicate a problem on the server end. Specific details of the problem are provided in the message body.
Some of the status codes we return are listed below.
Code | Title | Descriptions |
---|---|---|
400 | Bad Request | The server cannot process the request because it is badly formed. |
401 | Unauthorized | The API key is invalid. |
403 | Forbidden | The API key doesn't have appropriate permissions for the request. |
404 | Not Found | You requested an object or page that could not be found. |
422 | Unprocessable Entity | The request is properly formed but the server is unable to process the contents. |
429 | Too Many Requests | The rate limit was exceeded i.e. the server received too many requests in a given period of time. |
500 | Internal Server Error | The server encountered an error. Try again later. |
503 | Service Unavailable | The server is unable to handle the request due to a temporary overload or scheduled maintenance. Try again later. |
Data formats
Some of the parameters in Wave API requests or attributes in API objects follow specific data formats.
Amounts
All amounts are represented as strings. When the amount includes decimal places, the separator is a period (.
). The following rules apply to valid amounts:
- Include between zero and two decimal places. (See Currency for the maximum number of allowed decimal places for each currency.)
- No leading zeroes where the value is one or greater.
- One leading zero where the value is less than one.
- May include trailing zeroes.
- Must be positive for requests. May be zero or negative in object attributes.
Currency
Standard ISO 4217 three-letter codes in upper case are used to specify currency.
The code for the West African Franc is XOF
. Decimal places are not allowed for XOF currency amounts.
Timestamps
Timestamp values follow the ISO 8601 standard. Timestamps that we provide in API objects will be of the form YYYY-MM-DDThh:mm:ssZ
where the Z
indicates the UTC time zone.
Transaction Type
Name | Description |
---|---|
merchant_payment |
A payment from a customer to a business. |
merchant_payment_refund |
A refund of a merchant payment. |
api_checkout |
A payment from a customer to a business made through the Checkout API |
api_checkout_refund |
A refund of a checkout payment. |
api_payout |
A payment from a business to a customer, made through the Payout API |
api_payout_reversal |
A reversal of a business payment. |
bulk_payment |
A payment from a business to a customer, made through the Bulk Payments portal. |
bulk_payment_reversal |
A reversal of a business payment. |
b2b_payment |
A payment from a business to another business. |
b2b_payment_reversal |
A reversal of payment from a business to another business. |
merchant_sweep |
A reversal of payment from a business to another business. |
Webhooks
Visit the Webhooks documentation
Balance API
ENDPOINTS:
GET /v1/balance
The Balance API provides a programmatic means to retrieve the balance on your wallet.
The Balance object
BALANCE OBJECT
{
"amount": "10245",
"currency": "XOF"
}
The Balance object represents the amount of money in a Wave wallet.
Attributes
amount string
Balance amount.
currency currency
Three-letter ISO 4217 currency code.
Retrieve balance
GET /v1/balance
curl \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6' \
https://api.wave.com/v1/balance
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wave.com/v1/balance",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
const axios = require('axios');
axios.get('https://api.wave.com/v1/balance', {
headers: {
'Authorization': 'Bearer wave_sn_prod_YhUNb9d...i4bA6'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
HttpResponse<String> response = Unirest.get("https://api.wave.com/v1/balance")
.header("Authorization", "Bearer wave_sn_prod_YhUNb9d...i4bA6")
.asString();
System.out.println(response.getBody());
Retrieves the current balance of the account associated with the API key used to make the request.
Parameters
No parameters.
Returns
Returns a balance object for the account associated with the API key used to make the request.
Retrieve your transactions
GET /v1/transactions
curl -X GET \
--url https://api.wave.com/v1/transactions?date=2022-10-25 \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6'
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wave.com/v1/transactions?date=2022-10-25",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
const axios = require('axios');
axios.get('https://api.wave.com/v1/transactions?date=2022-10-25', {
headers: {
'Authorization': 'Bearer wave_sn_prod_YhUNb9d...i4bA6'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
HttpResponse<String> response = Unirest.get("https://api.wave.com/v1/transactions?date=2022-10-25")
.header("Authorization", "Bearer wave_sn_prod_YhUNb9d...i4bA6")
.asString();
System.out.println(response.getBody());
Example response
{
"page_info": {
"start_cursor": null,
"end_cursor": "TFRfdUZ1MGoyMzVKemtz",
"has_next_page": true
},
"date": "2022-11-07",
"items": [
{
"timestamp": "2022-11-07T14:41:15Z",
"transaction_id": "T_V3TFOUE7VU",
"amount": "99",
"fee": "1",
"currency": "XOF",
"counterparty_name": "Mame Diop",
"counterparty_mobile": "+221761110000"
},
{
"timestamp": "2022-11-07T14:42:06Z",
"transaction_id": "T_2YJNPWMCIY",
"amount": "99",
"fee": "1",
"currency": "XOF",
"counterparty_name": "Fatou Ndiaye",
"counterparty_mobile": "+221761110001"
},
{
"timestamp": "2022-11-07T14:42:41Z",
"transaction_id": "T_2YJNPWMCIY",
"amount": "-99",
"fee": "-1",
"currency": "XOF",
"is_reversal": true
},
{
"timestamp": "2022-11-07T14:42:54Z",
"transaction_id": "pt-1azcvz4081002",
"amount": "-101",
"fee": "1",
"currency": "XOF",
"counterparty_name": "Moustapha Mbaye",
"counterparty_mobile": "+221761110519"
},
{
"timestamp": "2022-11-07T14:43:00Z",
"transaction_id": "pt-1azcw0qkg1004",
"amount": "-121",
"fee": "1",
"currency": "XOF",
"counterparty_name": "Moustapha Mbaye",
"counterparty_mobile": "+221761110519"
},
{
"timestamp": "2022-11-07T14:43:14Z",
"transaction_id": "pt-1azcw0qkg1004",
"amount": "121",
"fee": "1",
"currency": "XOF",
"counterparty_name": "Moustapha Mbaye",
"counterparty_mobile": "+221761110519",
"is_reversal": true
}
]
}
Returns a list of transactions of your account for a given day. Uses pagination if the number of transactions exceeds 1000 entries. The transactions are ordered from older to newer.
Request parameters
URL parameters are passed in the form of https://api.wave.com/v1/transactions?date=value1&after=value2
.
Name | Type | Description |
---|---|---|
date |
URL parameter (optional) | Which day to fetch transactions for. Returns the current day's transactions if not specified. |
after |
URL parameter (optional) | The pointer of the page to fetch. This is an opaque string, and generally you just pass it the end_cursor of the previous page, as returned in the page_info object. See pagination. |
Return attributes
Key | Type | Description |
---|---|---|
timestamp |
Timestamp | The execution time and date of the transaction. |
transaction_id |
String | A unique identifier for a transaction. Up to 20 characters. |
transaction_type |
Transaction Type | The type of transaction.. Can be empty. |
amount |
String | The amount difference that this transaction had on your account. |
fee |
String | The fee for the transaction. |
balance |
String | The wallet's balance after this transaction was executed. |
currency |
Currency code | The 3-letter ISO 4217 currency code of the transaction amount. |
is_reversal |
Boolean (optional) | Marked true if this is a reversal or refund of a previous transaction. |
counterparty_name |
String (optional) | The name of the counterparty (sender or receiver) of the transaction. |
counterparty_mobile |
String (optional) | The mobile number of the counterparty (sender or receiver) of the transaction. |
counterparty_id |
String (optional) | The identifier of the counterparty in B2B payments. |
business_user_name |
String (optional) | The name of the business user involved in the transaction. This is for example the shop assistant/business user, or the depositor for an agent transaction. |
business_user_mobile |
String (optional) | The mobile number of the business user involved in the transaction. |
employee_id |
String (optional) | The employee ID associated with the busienss user involved in the transaction. |
client_reference |
String (optional) | A unique string that you (optionally) provided when submitting the transaction. |
payment_reason |
String (optional) | A payment reason or message that you (optionally) provided when submitting the transaction. |
checkout_api_session_id |
String (optional) | If this payment is linked to a Checkout API session, this is its ID. |
batch_id |
String (optional) | The batch ID if this transaction is part of a bulk payment. |
aggregated_merchant_id |
String (optional) | The ID of the aggregated merchant this transaction is assigned to. Only applicable if you're an aggregator processing payments for a merchant that is integrating via your services. |
aggregated_merchant_name |
String (optional) | The name of the aggregated merchant this transaction is assigned to. Only applicable if you're an aggregator processing payments for a merchant that is integrating via your services. |
custom_fields |
JSON Object (optional) | A key-value map of any custom fields related to this payment. |
Refund a transaction
POST /v1/transactions/:transaction_id/refund
curl -X POST \
-L https://api.wave.com/v1/transactions/T_VZSWJF5MMQ/refund \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6'
Example response
HTTP 200 OK
With this endpoint you can reverse a transaction, including fees. You don't need to indicate a reason, you can simply refund your customers any time you deem necessary.
Request parameters
There are no parameters necessary in the request body. Note that the transaction_id
is passed in the request path.
Response body
There is no response body. The status code will inform you whether a refund was successful (200), or the transaction doesn't exist (404), or something else went wrong (500).
Pagination
Example page info object
"page_info": {
"start_cursor": null,
"end_cursor": "TFRfRGxVVlN5eHhPRmhk",
"has_next_page": true
}
If the number of items of an API request is too many to return in a single request, then the results are paginated. The cutoff amount depends on the API, for example the Balance API transactions export is limited to 1000 transactions.
Name | Type | Description |
---|---|---|
start_cursor |
URL parameter | The opaque id of the current page. |
end_cursor |
URL parameter | The opaque id of the next page. Generally you simply pass this to the next request as the after URL parameter. |
has_next_page |
Boolean | A flag to let you know there are more items to fetch. |
You can simply iterate through the pages by calling https://api.wave.com/v1/<endpoint>?after=<end_cursor>
.
Checkout API
ENDPOINTS:
POST /v1/checkout/sessions
GET /v1/checkout/sessions/:id
GET /v1/checkout/sessions
GET /v1/checkout/sessions/search
POST /v1/checkout/sessions/:id/expire
POST /v1/checkout/sessions/:id/refund
The Checkout API provides a programmatic means to allow you to prompt users from a website or a mobile app to send payments.
The Checkout Session object
CHECKOUT SESSION OBJECT
{
"id": "cos-18qq25rgr100a",
"amount": "1000",
"checkout_status": "complete",
"client_reference": null,
"currency": "XOF",
"error_url": "https://example.com/error",
"last_payment_error": null,
"business_name": "Papa's Penguins",
"payment_status": "succeeded",
"transaction_id": "TDH5TEWTLFE",
"aggregated_merchant_id": "am-7lks22ap113t4",
"success_url": "https://example.com/success",
"wave_launch_url": "https://pay.wave.com/c/cos-18qq25rgr100a",
"when_completed": "2021-12-08T10:15:32Z",
"when_created": "2021-12-08T10:13:04Z",
"when_expires": "2021-12-09T10:13:04Z"
}
The Checkout Session object contains details about the requested payment and its status.
Attributes
id string
Unique identifier for the Checkout Session object. Up to 20 characters.
amount string
Total amount to collect from the customer (gross of fees).
checkout_status enum
The status of the checkout, one of open
, complete
, or expired
.
client_reference string (optional)
A unique string which can be used to correlate the checkout session and subsequent payment with your system. You provide this value in the request to create a checkout session.
currency string
Three-letter ISO 4217 currency code.
error_url string
The URL the customer will be directed to if an error occurs on a payment attempt.
last_payment_error hash (optional)
The reason for the last failed payment attempt. Can only be populated when the payment_status
is processing
or cancelled
.
Contains the following fields:
code string A short string indicated the error code.
message string
A human-readable description of the error.
business_name string
The name of the business as it will be shown to the customer.
payment_status enum
The status of the associated payment, one of processing
, cancelled
, or succeeded
.
aggregated_merchant_id: string (optional)
The aggregated merchant id used for this checkout transaction.
restrict_payer_mobile: string (optional)
This checkout session can only be paid by the Wave account with this number. Note: this field was previously called enforce_payer_mobile, so both are currently returned.
success_url string
The URL the customer will be directed to if the payment succeeds.
transaction_id string
A Wave transaction ID that is also visible in the user's app.
wave_launch_url string
A URL which will open the Wave app to initiate the checkout or give instructions for completing the checkout if Wave is not installed on the device.
when_completed ISO 8601 timestamp
UTC time at which the checkout session either succeeded or expired.
Not populated when the checkout_status
is open
.
when_created ISO 8601 timestamp
UTC time that the checkout session was created.
when_expires ISO 8601 timestamp
UTC time at which the checkout session will expire. By default, checkout sessions expire 30 minutes after their creation. After expiration, payments will not be accepted for the checkout session.
Create a checkout session
POST /v1/checkout/sessions
curl \
-X POST \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6' \
-H 'Content-Type: application/json' \
-d '{
"amount": "1000",
"currency": "XOF",
"error_url": "https://example.com/error",
"success_url": "https://example.com/success"
}' \
https://api.wave.com/v1/checkout/sessions
<?php
# Specify your API KEY
$api_key = "wave_sn_prod_YhUNb9d...i4bA6";
$checkout_params = [
"amount" => "1000",
"currency" => "XOF",
"error_url" => "https://example.com/error",
"success_url" => "https://example.com/success",
];
# Define the request options
$curlOptions = [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($checkout_params),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$api_key}",
"Content-Type: application/json"
],
];
# Execute the request and get a response
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
# You can now decode the response and use the checkout session. Happy coding ;)
$checkout_session = json_decode($response);
# You can redirect the user by using the 'wave_launch_url' field.
$wave_launch_url = $checkout_session["wave_launch_url"]
header('Location: $wave_launch_url');
exit;
}
const axios = require('axios');
const api_key = "wave_sn_prod_YhUNb9d...i4bA6";
const checkout_params = {
amount: "1000",
currency: "XOF",
error_url: "https://example.com/error",
success_url: "https://example.com/success",
};
axios.post('https://api.wave.com/v1/checkout/sessions', checkout_params, {
headers: {
'Authorization': `Bearer ${api_key}`,
'Content-Type': 'application/json',
},
})
.then((response) => {
// You can now use the response to redirect the user to the Wave app
const wave_launch_url = response.data.wave_launch_url;
window.location.href = wave_launch_url;
})
.catch((error) => {
console.error(error);
});
import okhttp3.*;
import org.json.JSONObject;
public class CheckoutSession {
public static void main(String[] args) {
String api_key = "wave_sn_prod_YhUNb9d...i4bA6";
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, new JSONObject() {{
put("amount", "1000");
put("currency", "XOF");
put("error_url", "https://example.com/error");
put("success_url", "https://example.com/success");
}}.toString());
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions")
.post(body)
.addHeader("Authorization", "Bearer " + api_key)
.addHeader("Content-Type", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject jsonResponse = new JSONObject(response.body().string());
String wave_launch_url = jsonResponse.getString("wave_launch_url");
// Redirect the user to the Wave app
System.out.println(wave_launch_url);
} else {
System.out.println("Error: " + response.body().string());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Creates a Checkout Session object.
Parameters
aggregated_merchant_id string (required for Aggregators)
An aggregated merchant ID to use when making this transaction. This is only available to specific businesses and will return an error if you provide it but don't have permission. If you would like to use this feature, please contact your Wave support representative.
amount string
Total amount to collect from the customer (gross of fees).
client_reference string (optional, up to 255 characters)
A unique string that you provide which can be used to correlate the checkout in your system.
currency string
Three-letter ISO 4217 currency code.
restrict_payer_mobile string (optional)
If you provide this, then the checkout session can only be paid by the Wave account with the specified mobile number. This is a feature that can help you protect your users from scams. Phone numbers follow the E.164 standard. They must include a country code preceded by +. Note: this field was previously called enforce_payer_mobile. This field is also still accepted for compatibility reasons, but the new name is preferred.
error_url string
The URL the customer will be directed to if an error occurs on a payment attempt. You must provide a fully-qualified address using https as the scheme. You may include any information you need in the path itself or in query parameters.
success_url string
The URL the customer will be directed to if the payment succeeds. You must provide a fully-qualified address using https as the scheme. You may include any information you need in the path itself or in query parameters.
Returns
Returns a Checkout Session object.
Retrieve a checkout
GET /v1/checkout/sessions/:id
curl \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6' \
https://api.wave.com/v1/checkout/sessions/cos-18qq25rgr100a
<?php
# Specify your API KEY
$api_key = "wave_sn_prod_YhUNb9d...i4bA6";
$checkout_id = "cos-18qq25rgr100a";
# Define the request options
$curlOptions = [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions/{$checkout_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$api_key}",
],
];
# Execute the request and get a response
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
# You can now decode the response and use the checkout session. Happy coding ;)
$checkout_session = json_decode($response);
var_dump($checkout_session);
}
const axios = require('axios');
const api_key = "wave_sn_prod_YhUNb9d...i4bA6";
const checkout_id = "cos-18qq25rgr100a";
axios.get('https://api.wave.com/v1/checkout/sessions/' + checkout_id, { headers: { 'Authorization': `Bearer ${api_key}` } })
.then((response) => {
const checkout_session = response.data;
console.log(checkout_session);
})
.catch((error) => {
console.error(error);
});
import okhttp3.*;
import org.json.JSONObject;
public class CheckoutSession {
public static void main(String[] args) {
String api_key = "wave_sn_prod_YhUNb9d...i4bA6";
String checkout_id = "cos-18qq25rgr100a";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions/" + checkout_id)
.get()
.addHeader("Authorization", "Bearer " + api_key)
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject jsonResponse = new JSONObject(response.body().string());
System.out.println(jsonResponse.toString());
} else {
System.out.println("Error: " + response.body().string());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Retrieves a Checkout Session object.
Parameters
No parameters.
Returns
Returns a Checkout Session object if a valid identifier was provided. Returns an checkout session error otherwise.
Retrieve a checkout by Transaction ID
GET /v1/checkout/sessions
curl -X GET \
--url https://api.wave.com/v1/checkout/sessions?transaction_id=FAH.4827.1734 \
-H 'Authorization : Bearer wave_sn_prod_YhUNb9d...i4bA6'
<?php
# Specify your API KEY
$api_key = "wave_sn_prod_YhUNb9d...i4bA6";
$transaction_id = "FAH.4827.1734";
# Define the request options
$curlOptions = [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions?transaction_id={$transaction_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$api_key}",
],
];
# Execute the request and get a response
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
# You can now decode the response and use the checkout session. Happy coding ;)
$checkout_session = json_decode($response);
var_dump($checkout_session);
}
const axios = require('axios');
const api_key = "wave_sn_prod_YhUNb9d...i4bA6";
const transaction_id = "FAH.4827.1734";
axios.get('https://api.wave.com/v1/checkout/sessions', { params: { transaction_id }, headers: { 'Authorization': `Bearer ${api_key}` } })
.then((response) => {
const checkout_session = response.data;
console.log(checkout_session);
})
.catch((error) => {
console.error(error);
});
import okhttp3.*;
import org.json.JSONObject;
public class CheckoutSession {
public static void main(String[] args) {
String api_key = "wave_sn_prod_YhUNb9d...i4bA6";
String transaction_id = "FAH.4827.1734";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions?transaction_id=" + transaction_id)
.get()
.addHeader("Authorization", "Bearer " + api_key)
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject jsonResponse = new JSONObject(response.body().string());
System.out.println(jsonResponse.toString());
} else {
System.out.println("Error: " + response.body().string());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Parameters
Key | Type | Description |
---|---|---|
transaction_id | string | The transaction ID of the checkout session to retrieve. |
Returns
Returns a Checkout Session object if a valid identifier was provided. Returns an checkout session error otherwise.
Search for checkouts
Retrieves a list of Checkout Session objects that match the search criteria.
GET /v1/checkout/sessions/search
curl -X GET \
--url https://api.wave.com/v1/checkout/sessions/search?client_reference=123456 \
-H 'Authorization : Bearer wave_sn_prod_YhUNb9d...i4bA6'
<?php
# Specify your API KEY
$api_key = "wave_sn_prod_YhUNb9d...i4bA6";
$client_reference = "123456";
# Define the request options
$curlOptions = [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions/search?client_reference={$client_reference}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => [
"Authorization : Bearer {$api_key}",
],
];
# Execute the request and get a response
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
# You can now decode the response and use the checkout session. Happy coding ;)
$checkout_session = json_decode($response);
var_dump($checkout_session);
}
const axios = require('axios');
const api_key = "wave_sn_prod_YhUNb9d...i4bA6";
const client_reference = "123456";
axios.get('https://api.wave.com/v1/checkout/sessions/search', { params: { client_reference }, headers: { 'Authorization': `Bearer ${api_key}` } })
.then((response) => {
const checkout_session = response.data;
console.log(checkout_session);
})
.catch((error) => {
console.error(error);
});
import okhttp3.*;
import org.json.JSONObject;
public class CheckoutSession {
public static void main(String[] args) {
String api_key = "wave_sn_prod_YhUNb9d...i4bA6";
String client_reference = "123456";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions/search?client_reference=" + client_reference)
.get()
.addHeader("Authorization", "Bearer " + api_key)
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject jsonResponse = new JSONObject(response.body().string());
System.out.println(jsonResponse.toString());
} else {
System.out.println("Error: " + response.body().string());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Example response
{
"result": [
{
"id": "cos-18qq25rgr100a",
"amount": "1000",
"checkout_status": "complete",
"client_reference": "123456",
"currency": "XOF",
"error_url": "https://example.com/error",
"last_payment_error": null,
"business_name": "Papa's Penguins",
"payment_status": "succeeded",
"transaction_id": "TDH5TEWTLFE",
"aggregated_merchant_id": "am-7lks22ap113t4",
"success_url": "https://example.com/success",
"wave_launch_url": "https://pay.wave.com/c/cos-18qq25rgr100a",
"when_completed": "2021-12-08T10:15:32Z",
"when_created": "2021-12-08T10:13:04Z",
"when_expires": "2021-12-09T10:13:04Z"
}
]
}
Parameters
Key | Type | Description |
---|---|---|
client_reference | string | A unique string that you provide which can be used to correlate the checkout in your system. |
Return attributes
Key | Type | Description |
---|---|---|
result |
List of checkout sessions | The list of payouts that match the search criteria. |
Refund a checkout
POST /v1/checkout/sessions/:id/refund
curl -X POST \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6' \
https://api.wave.com/v1/checkout/sessions/cos-18qq25rgr100a/refund
<?php
# Specify your API KEY
$api_key = "wave_sn_prod_YhUNb9d...i4bA6";
$checkout_id = "cos-18qq25rgr100a";
# Define the request options
$curlOptions = [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions/{$checkout_id}/refund",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$api_key}",
],
];
# Execute the request and get a response
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
# You can now decode the response and use the checkout session. Happy coding ;)
$checkout_session = json_decode($response);
var_dump($checkout_session);
}
const axios = require('axios');
const api_key = "wave_sn_prod_YhUNb9d...i4bA6";
const checkout_id = "cos-18qq25rgr100a";
axios.post('https://api.wave.com/v1/checkout/sessions/' + checkout_id + '/refund', null, { headers: { 'Authorization': `Bearer ${api_key}` } })
.then((response) => {
const checkout_session = response.data;
console.log(checkout_session);
})
.catch((error) => {
console.error(error);
});
import okhttp3.*;
import org.json.JSONObject;
public class CheckoutSession {
public static void main(String[] args) {
String api_key = "wave_sn_prod_YhUNb9d...i4bA6";
String checkout_id = "cos-18qq25rgr100a";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions/" + checkout_id + "/refund")
.post(RequestBody.create(null, new byte[0]))
.addHeader("Authorization", "Bearer " + api_key)
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject jsonResponse = new JSONObject(response.body().string());
System.out.println(jsonResponse.toString());
} else {
System.out.println("Error: " + response.body().string());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Refunds the user payment associated with a Checkout Session.
Parameters
No parameters.
Returns
Returns an empty body and an HTTP 200 Success code when the payment is refunded, and an error otherwise. If the Checkout Session doesn't exists this returns an HTTP 404 Not Found error.
If you try to refund a checkout twice, no additional transaction will be created, but this endpoint will simply return HTTP 200 Success again.
All normal transaction restrictions apply: if the recipient has reached their monthly limit or their account is for any reason blocked then the corresponding error is returned as well.
Expire a checkout
POST /v1/checkout/sessions/:id/expire
curl -X POST \
-H 'Authorization: Bearer wave_sn_prod_YhUNb9d...i4bA6' \
https://api.wave.com/v1/checkout/sessions/cos-18qq25rgr100a/expire
<?php
# Specify your API KEY
$api_key = "wave_sn_prod_YhUNb9d...i4bA6";
$checkout_id = "cos-18qq25rgr100a";
# Define the request options
$curlOptions = [
CURLOPT_URL => "https://api.wave.com/v1/checkout/sessions/{$checkout_id}/expire",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer {$api_key}",
],
];
# Execute the request and get a response
$curl = curl_init();
curl_setopt_array($curl, $curlOptions);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
# You can now decode the response and use the checkout session. Happy coding ;)
$checkout_session = json_decode($response);
var_dump($checkout_session);
}
const axios = require('axios');
const api_key = "wave_sn_prod_YhUNb9d...i4bA6";
const checkout_id = "cos-18qq25rgr100a";
axios.post('https://api.wave.com/v1/checkout/sessions/' + checkout_id + '/expire', null, { headers: { 'Authorization': `Bearer ${api_key}` } })
.then((response) => {
const checkout_session = response.data;
console.log(checkout_session);
})
.catch((error) => {
console.error(error);
});
import okhttp3.*;
import org.json.JSONObject;
public class CheckoutSession {
public static void main(String[] args) {
String api_key = "wave_sn_prod_YhUNb9d...i4bA6";
String checkout_id = "cos-18qq25rgr100a";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.wave.com/v1/checkout/sessions/" + checkout_id + "/expire")
.post(RequestBody.create(null, new byte[0]))
.addHeader("Authorization", "Bearer " + api_key)
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject jsonResponse = new JSONObject(response.body().string());
System.out.println(jsonResponse.toString());
} else {
System.out.println("Error: " + response.body().string());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Expires an open Checkout Session, preventing it from being completed by any user.
Parameters
No parameters.
Returns
Returns an empty body and an HTTP 200 Success code when successfully expiring the session. Can also return the following errors:
- 404 Not Found: If no Checkout Session is found with the provided id
- 403 Forbidden: If your API key has no permission for this endpoint
- 409 Conflict: If the Checkout Session was already completed or expired
Checkout API errors
A couple of things can go wrong when attempting to create a checkout session, or when a user tries to pay an existing session. The following is the list of errors that can occur when using this API.
This is in addition to the general HTTP code that can be returned as described in the errors section.
Checkout Session errors
error_code |
explanation |
---|---|
authorization-error |
The API key is either missing or incomplete. Make sure you copy-pasted the entire key and refer to the authentication section for instructions. |
missing-auth-header |
The request is missing a Bearer token in the Authorization header. See Authentication for instructions. |
checkout-refund-failed |
You tried to refund a checkout but the transaction couldn't be made. It's possible that the payment wasn't in a success state beforehand, the recipient account was blocked, or your wallet didn't have sufficient funds for the transaction. |
checkout-session-not-found |
You requested a checkout session by ID that we can't match to anything in our system. You should double-check that the ID corresponds to one that you've received in a response. |
internal-server-error |
A technical error has occurred in Wave's system. We work very hard to avoid this, so it is only reserved for unexpected cases. |
request-validation-error |
Your request doesn't match the object type required. These are things like a missing field or an invalid type in a provided field like an invalid phone number. The error_message will help you with details. |
service-unavailable |
In some rare and short cases Wave services are down for maintenance. You can try the request again later. |
unauthorized-wallet |
The account you are using is not authorized to use this API. Please get in touch with a Wave partner representative to discuss getting access. |
Payment errors
These errors will be delivered as part of the webhook that notifies your system of a failed checkout payment attempt. They basically answer why the payment of the user failed. The code will be under the last_payment_error
field of the webhook body.
error_code |
explanation |
---|---|
blocked-account |
The customer used a blocked account to try and pay for the checkout. |
cross-border-payment-not-allowed |
Sending a payment between countries is often restricted for regulatory reasons. |
customer-age-restricted |
The customer is underage (or of unknown age), but is trying to pay for an age restricted product or service. |
insufficient-funds |
The user didn't have enough account balance. |
kyb-limits-exceeded |
Your business has exceeded its account limits. Please contact Wave to find out how you can increase your limits. |
payer-mobile-mismatch |
If you passed the restrict_payer_mobile (formerly enforce_payer_mobile ) parameter, then the checkout session can only be paid by the number you specified. This error is returned if a customer with a different number tried to pay. |
payment-failure |
A technical error has occurred in Wave's system. We work very hard to avoid this, so it error code only reserved for unexpected cases. |
Changelog
2024-03-29
Removes override_business_name
details from the Checkout API
2022-10-17
Added aggregated_merchant_id
details to the Checkout API.
2022-05-10
The Checkout API now validates decimal places following the rules described in the Amount section.
2022-03-29
Adds override_business_name
details to Checkout API
2022-03-23
Initial release of Checkout and Balance APIs.