Skip to content

API

Introduction

Bienvenue dans notre documentation API ! Ici, vous trouverez toutes les informations dont vous avez besoin pour interagir avec notre api de paiement. 😃

Structure Générale des Réponses

Toutes nos réponses d'API suivent une structure cohérente pour rendre les choses faciles et uniformes. Voici ce à quoi vous pouvez vous attendre :

  • status: Indique le succès (true) ou l'échec (false) de la requête.
  • message: Un message expliquant la réponse
  • data: Contient les détails de la réponse (le cas échéant).

Réponses d'Erreur

Lorsque quelque chose ne va pas, nous vous le ferons savoir avec une réponse d'erreur. Vous obtiendrez un statut de false, le code d'erreur et le message décrira ce qui a mal tourné.

  • status: Indique le succès (true) ou l'échec (false) de la requête.
  • message: Un message expliquant la réponse
  • error_code: Un code d'erreur, en cas d'erreur lié à la fonction de paiement
  • errors: Erreurs de validation des valeur transmise

Clés API🔑

Assurez-vous de remplacer sk_test_... par votre véritable clé API. Votre clé API est votre identifiant unique, et gardez-la en sécurité !

Paramètres

Lorsque vous voyez :parameter, , assurez-vous de le remplacer par la valeur réelle que vous souhaitez passer à l'API. Par exemple, :checkout_reference doit être remplacé par la vraie référence d'un checkout.

Exemple de Réponse pour Clé API Invalide

Si vous utilisez une clé API incorrecte, vous recevrez une réponse comme celle-ci :

{
    "status": false,
    "message": "Invalid API key"
}

checkouts

C'est quoi un Checkout?

Le checkout est le processus par lequel vos clients finalisent leurs achats. Il implique l'initialisation du checkout et la redirection du client vers une URL d'autorisation qui vous est retourné.

Étapes pour Accepter un Paiement avec l'API de checkout

  1. Initialisation du Checkout: Appeler le endpoint d'initialisation.
  2. Redirection du client: Rediriger le client sur authorization_url retourné quand la requête est OK.

Initialisation du Checkout

Vous pouvez initialiser un checkout à l'aide de la requête suivante:

POST /v1/payment/checkouts/initialize/
curl --location 'https://api.senfenico.com/v1/payment/checkouts/initialize/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...' \
--data '{
    "email": "customer@mail.com",
    "amount": 600,
    "success_url": "https://example.com/sucess",
    "cancel_url": "https://example.com/cancel"
}'
POST /v1/payment/checkouts/initialize/
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n  \"email\": \"customer@mail.com\",\n  \"amount\": 600,\n  \"success_url\": \"https://example.com/sucess\",\n  \"cancel_url\": \"https://example.com/cancel\"\n}");
Request request = new Request.Builder()
.url("https://api.senfenico.com/v1/payment/checkouts/initialize/")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("X-API-KEY", "sk_test_...")
.build();
Response response = client.newCall(request).execute();
POST /v1/payment/checkouts/initialize/
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
    'method': 'POST',
    'hostname': 'api.senfenico.com',
    'path': '/v1/payment/checkouts/initialize/',
    'headers': {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    },
    'maxRedirects': 20
};

var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

var postData = JSON.stringify({
    "email": "customer@mail.com",
    "amount": 600,
    "success_url": "https://example.com/sucess",
    "cancel_url": "https://example.com/cancel"
});

req.write(postData);

req.end();
POST /v1/payment/checkouts/initialize/
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->checkout->initialize([
    'amount' => 1000,
    'success_url' => 'https://yourwebsite.com/success',
    'cancel_url' => 'https://yourwebsite.com/cancel',
]);
POST /v1/payment/checkouts/initialize/
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Checkout.initialize(amount=100, success_url='https://www.website.com/success', cancel_url='http://www.website.com/cancel')
Parametre Type Optionel Description
email string Yes Customer's email address
amount int No Amount to charge
success_url string No URL to redirect on success
cancel_url string No URL to redirect if the customer cancels

Sample Response

Checkout initialized
{
    "status": true,
    "message": "Checkout initialized",
    "data": {
        "reference": "chk_de1ca053573c40a29a9fe95e7ad91d7e",
        "authorization_url": "https://api.senfenico.com/v1/checkout_payment/payment_page/chk_de1ca053573c40a29a9fe95e7ad91d7e/",
        "live_mode": false
    }
}
Response Element Type Description
reference string Unique reference for the checkout
authorization_url string URL to redirect the user to proceed with the payment

Note: Redirect the user to authorization_url to proceed with the payment.

fetch checkout

Fetch the details of a specific checkout:

GET /v1/payment/checkouts/:checkout_reference
curl --location 'https://api.senfenico.com/v1/payment/checkouts/{checkout_reference}' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/checkouts/:checkout_reference
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/checkouts/{checkout_reference}")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();

Response response = client.newCall(request).execute();
GET /v1/payment/checkouts/:checkout_reference
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
    'method': 'GET',
    'hostname': 'api.senfenico.com',
    'path': '/v1/payment/checkouts/{checkout_reference}',
    'headers': {
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    },
    'maxRedirects': 20
};

var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();
GET /v1/payment/checkouts/:checkout_reference
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->checkout->fetch('xxxxxxxx...', []);
GET /v1/payment/checkouts/:checkout_reference
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Checkout.fetch("655342d1-c1a3-44eb-aee7-a2fddcadeaf2")

Sample Response

Checkout details retrieved
{
    "status": true,
    "message": "Checkout details retrieved",
    "data": {
        "email": "customer@mail.com",
        "reference": "8872031d-178e-464c-9261-7984f0a313c0",
        "charge_reference": null,
        "amount": 600,
        "success_url": "https://yourwebsite.com/success",
        "cancel_url": "https://yourwebsite.com/cancel",
        "phone": "",
        "provider": "",
        "live_mode": true,
        "created_at": "2023-07-25T19:55:48.223895Z",
        "updated_at": "2023-07-25T19:55:48.223956Z",
        "status": "pending"
    }
}

Checkout Status:

  • pending: Awaiting payment
  • success: Payment successful
  • failed: Payment failed

list checkout

Retrieve a list of checkouts:

GET /v1/payment/checkouts
curl --location 'https://api.senfenico.com/v1/payment/checkouts' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/checkouts
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/checkouts")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/checkouts
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
    'method': 'GET',
    'hostname': 'api.senfenico.com',
    'path': '/v1/payment/checkouts',
    'headers': {
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    },
    'maxRedirects': 20
};

var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();
GET /v1/payment/checkouts
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->checkout->list([]);
GET /v1/payment/checkouts
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Checkout.list()

Sample Response

{
    "status": true,
    "message": "Checkout list retreived",
    "data": [
        {
            "email": "customer@mail.com",
            "reference": "0ecae2d5-4d8d-47d9-98b2-38826c562c37",
            "charge_reference": "822039fa-9cbc-447b-bd3a-b374e06faa40",
            "amount": 3500,
            "success_url": "https://yourwebsite.com/success",
            "cancel_url": "https://yourwebsite.com/cancel",
            "phone": "77xxxxxx",
            "provider": "orange_bf",
            "live_mode": false,
            "created_at": "2023-07-13T11:36:50.827975Z",
            "updated_at": "2023-07-13T11:41:35.663261Z",
            "status": "pending"
        },
        {
            "email": "customer@mail.com",
            "reference": "e222060a-0f49-4759-a400-c241a88f623c",
            "charge_reference": "734c24d4-a379-47a6-8994-1880a3e63af4",
            "amount": 200,
            "success_url": "https://yourwebsite.com/admin",
            "cancel_url": "https://yourwebsite.com/cancel",
            "phone": "71xxxxxx",
            "provider": "moov_bf",
            "live_mode": false,
            "created_at": "2023-07-11T22:34:44.375268Z",
            "updated_at": "2023-07-12T01:34:21.373271Z",
            "status": "success"
        }
    ]
}

charges

Les charges permettent de gérer l'ensemble des étapes de paiement par vous-même. Elles sont adaptées aux applications mobiles ou de bureau puisqu'elles ne requièrent pas de redirection. Voici comment accepter un paiement via les points d'accès charges :

  1. Création d'une charge : Renseigner les détails de la charge.
  2. Action du client : Il se peut que le client doive saisir un code USSD sur son téléphone pour confirmer la transaction. Cette étape varie selon l'opérateur.
  3. Soumission du OTP

create a charge

Create a new charge for a payment:

POST /v1/payment/charges/
curl --location 'https://api.senfenico.com/v1/payment/charges/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...' \
--data '{
    "amount": "500",
    "currency": "XOF",
    "payment_method": "mobile_money",
    "payment_method_details": {
        "phone": "76xxxxxx",
        "provider": "orange_bf"
    }
}'
POST /v1/payment/charges/
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n  \"amount\": \"500\",\n  \"currency\": \"XOF\",\n  \"payment_method\": \"mobile_money\",\n  \"payment_method_details\": {\n    \"phone\": \"76xxxxxx\",\n    \"provider\": \"orange_bf\"\n  }\n}");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/charges/")
    .method("POST", body)
    .addHeader("Content-Type", "application/json")
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
POST /v1/payment/charges/
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
    'method': 'POST',
    'hostname': 'api.senfenico.com',
    'path': '/v1/payment/charges/',
    'headers': {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    },
    'maxRedirects': 20
};

var req = https.request(options, function (res) {
var chunks = [];

res.on("data", function (chunk) {
    chunks.push(chunk);
});

res.on("end", function (chunk) {
    var body = Buffer.concat(chunks);
    console.log(body.toString());
});

res.on("error", function (error) {
    console.error(error);
});
});

var postData = JSON.stringify({
    "amount": "500",
    "currency": "XOF",
    "payment_method": "mobile_money",
    "payment_method_details": {
        "phone": "76xxxxxx",
        "provider": "orange_bf"
    }
});

req.write(postData);

req.end();
POST /v1/payment/charges/
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->charge->create([
    'amount' => 1000,
    'phone' => '76XXXXXX',
    'provider' => 'orange_bf'
]);
POST /v1/payment/charges/
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Charge.create(amount=2000, phone='65000000', provider='orange_bf')
Parameter Type Optional Description
amount int No Amount to charge
currency string Yes Currency code (default: "XOF")
payment_method string Yes Payment method (default: "mobile_money")
payment_method_details object No Details about the payment method
phone string No your client phone number
provider object No the phone number operator.
Available options:
  • orange_bf
  • moov_bf
  • coris_bf
  • sank_bf

Note on Provider Constraints:

  • For orange_bf: Use an Orange BF phone number (8 digits). Valid prefixes: 04, 05, 06, 07, 54, 55, 56, 57, 64, 65, 66, 67, 74, 75, 76, 77.
  • For moov_bf: Use a Moov BF phone number (8 digits). Valid prefixes: 70, 71, 72, 73, 60, 61, 62, 63, 50, 51, 52, 53, 01, 02, 03.
  • Pour coris_bf: Vous pouvez utiliser n'importe quelle numero de téléphone portable burkinabè
  • Pour sank_bf: Vous pouvez utiliser n'importe quelle numero de téléphone portable burkinabè

Sample Response

provider:orange_bf sample response
{
    "status": true,
    "message": "Charge attempted",
    "data": {
        "reference": "ch_1ba1b4d1268b41079ee84c777e999f51",
        "status": "send_otp",
        "display_text": "Composez *144*4*6*500# pour obtenir un code OTP, puis entrez-le sur notre plateforme pour finaliser la transaction.",
        "live_mode": false
    }
}
provider:moov_bf sample response
{
    "status": true,
    "message": "Charge attempted",
    "data": {
        "reference": "ch_4f60d14ace534fd19ee3cce88fd6ba73",
        "status": "send_otp",
        "display_text": "Veuillez entrer le code OTP reçu sur votre téléphone pour finaliser la transaction.",
        "live_mode": false
    }
}

Interpretation of Responses:

  • Lorsque le statut est send_otp, l'utilisateur doit saisir un code OTP (One-Time Password) pour finaliser la transaction. En général, cet OTP est envoyé par SMS par son opérateur, sans qu'aucune action supplémentaire ne soit nécessaire. Cependant, dans certains cas, comme avec Orange Money, l'utilisateur devra composer un code USSD indiqué dans le display_text pour recevoir le code OTP.

  • Lorsque le statut est pay_offline, l'utilisateur doit finaliser le paiement directement depuis son téléphone, en exécutant un code USSD et en suivant les instructions affichées dans le display_text. Dans ce cas, aucun code OTP n'est requis. L'intégrateur sera informé une fois le paiement terminé, à condition qu'il ait souscrit aux événements appropriés dans le menu webhook de l'interface d'administration.

submit OTP

Submit the OTP for a charge:

POST /v1/payment/charges/submit
curl --location 'https://api.senfenico.com/v1/payment/charges/submit' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...' \
--data '{
    "otp": "839231",
    "charge_reference": "ch_39728149f97a46f1806a694dbb620b23"
}'
POST /v1/payment/charges/submit
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n  \"otp\": \"839231\",\n  \"charge_reference\": \"ch_39728149f97a46f1806a694dbb620b23\"\n}");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/charges/submit")
    .method("POST", body)
    .addHeader("Content-Type", "application/json")
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
POST /v1/payment/charges/submit
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
    'method': 'POST',
    'hostname': 'api.senfenico.com',
    'path': '/v1/payment/charges/submit',
    'headers': {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    },
    'maxRedirects': 20
};

var req = https.request(options, function (res) {
var chunks = [];

res.on("data", function (chunk) {
    chunks.push(chunk);
});

res.on("end", function (chunk) {
    var body = Buffer.concat(chunks);
    console.log(body.toString());
});

res.on("error", function (error) {
        console.error(error);
    });
});

var postData = JSON.stringify({
    "otp": "839231",
    "charge_reference": "ch_39728149f97a46f1806a694dbb620b23"
});

req.write(postData);

req.end();
POST /v1/payment/charges/submit
$senfenico->charge->submitOtp([
    'otp' => 123456,
    'charge_reference' => 'ch_39728149f97a46f1806a694dbb620b23',
]);
POST /v1/payment/charges/submit
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Charge.submit_otp(otp="123456", charge_reference="ch_39728149f97a46f1806a694dbb620b23")
Parameter Type Optional Description
otp string No One-Time Password (OTP)
charge_reference string No Reference of the charge

Sample Response

Charge completed successfully
{
    "status": true,
    "message": "charge completed successfully",
    "data": {
        "reference": "ch_39728149f97a46f1806a694dbb620b23",
        "amount": 1000,
        "fees": 3.5,
        "currency": "XOF",
        "transaction_date": "2024-08-18T11:43:47.380565+00:00",
        "ip_address": "172.18.0.1",
        "status": "success",
        "live_mode": false,
        "payment_method": "mobile_money",
        "provider": "orange_bf",
        "cancelled_at": null,
        "cancellation_reason": null,
        "confirmation_attempts": [
            {
                "ip_address": "172.18.0.1",
                "attempt_date": "2024-08-18T11:44:16.683423+00:00",
                "confirmation_status": "success"
            }
        ]
    }
}
OTP submission failed
{
    "status": false,
    "message": "Charge operation failed. The OTP is invalid. Please try again.",
    "error_code": "OTP_INVALID"
}
Response Element Type Description
reference string Reference of the charge
amount int Charged amount
fees float Transaction fees in percent (e.g., 2%)
currency string Currency code ["XOF"]
status string Status of the charge
live_mode bool Indicates if it's a live transaction
payment_method string Payment method ["mobile_money"]
provider string Provider name ["orange_bf", "moov_bf", "coris_bf", "sank_bf"]
cancelled_at null Cancellation time (if any)
cancellation_reason null Reason for cancellation (if any)

fetch charge

Retrieve the details of a specific charge:

GET /v1/payment/charges/:charge_reference
curl --location 'https://api.senfenico.com/v1/payment/charges/{charge_reference}' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/charges/:charge_reference
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/charges/{charge_reference}")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/charges/:charge_reference
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
'method': 'GET',
'hostname': 'api.senfenico.com',
'path': '/v1/payment/charges/{charge_reference}',
'headers': {
    'Accept': 'application/json',
    'X-API-KEY': 'sk_test_...'
},
'maxRedirects': 20
};

var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();
GET /v1/payment/charges/:charge_reference
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->charge->fetch('xxxxxx...', []);
GET /v1/payment/charges/:charge_reference
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Charge.fetch(charge_reference='1c32d1c7-dc81-49c5-85b0-7f6f3498e4a2')
Parameter Type Optional Description
charge_reference string No Reference of the charge

Sample Response

Charge retreived
{
    "status": true,
    "message": "Charge attempted",
    "data": {
        "reference": "ch_45a408fd483a4d66b98aeea97aa7c2e2",
        "amount": 1000,
        "fees": "3.50",
        "currency": "XOF",
        "transaction_date": "2024-08-18T12:52:33.569084Z",
        "ip_address": "172.18.0.1",
        "status": "success",
        "live_mode": false,
        "payment_method": "mobile_money",
        "provider": "orange_bf",
        "phone": "76000000",
        "cancelled_at": null,
        "cancellation_reason": null,
        "created_at": "2024-08-18T12:52:33.572801Z",
        "updated_at": "2024-08-18T12:58:04.376754Z",
        "confirmation_attempts": [
            {
                "ip_address": "172.18.0.1",
                "attempt_date": "2024-08-18T12:53:00.220699Z",
                "confirmation_status": "failed"
            },
            {
                "ip_address": "172.18.0.1",
                "attempt_date": "2024-08-18T12:58:04.911978Z",
                "confirmation_status": "success"
            }
        ]
    }
}
Charge not found
{
    "status": false,
    "message": "Charge not found"
}
Response Element Type Description
reference string Reference of the charge
amount int Charged amount
fees string Transaction fees in percent (2 means 2%)
currency string Currency code ["XOF"]
transaction_date string Transaction date and time
status string Status of the charge [success, failed, send_otp, pay_offline, pending, canceled]
live_mode bool Indicates if it's a live transaction
payment_method string Payment method (e.g., "mobile_money")
provider string Provider name (e.g., "orange_bf")
phone string Phone number used for transaction
cancelled_at null Cancellation time (if any)
cancellation_reason null Reason for cancellation (if any)

list charges

Retrieve a list of all the charges:

GET /v1/payment/charges
curl --location 'https://api.senfenico.com/v1/payment/charges' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/charges
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/charges")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/charges
var request = require('request');
var options = {
    'method': 'GET',
    'url': 'https://api.senfenico.com/v1/payment/charges',
    'headers': {
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    }
};
request(options, function (error, response) {
if (error) throw new Error(error);
    console.log(response.body);
});
GET /v1/payment/charges
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->charge->list([]);
GET /v1/payment/charges
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Charge.list()

Sample Response

Charge list retreived
{
    "status": true,
    "message": "Charge list retreived",
    "data": [
        {
            "reference": "01b6f627-6123-43e7-89a7-4fcb9079b173",
            "amount": 500,
            "fees": "2.00",
            "currency": "XOF",
            "transaction_date": "2023-07-27T10:26:50.563219Z",
            "ip_address": "172.23.0.1",
            "status": "success",
            "live_mode": false,
            "payment_method": "mobile_money",
            "provider": "orange_bf",
            "phone": "77xxxxxx",
            "cancelled_at": null,
            "cancellation_reason": null,
            "created_at": "2023-07-27T10:26:50.571137Z",
            "updated_at": "2023-07-27T10:27:19.402034Z",
            "confirmation_attempts": [
                {
                    "ip_address": "172.23.0.1",
                    "attempt_date": "2023-07-27T10:27:19.385100Z",
                    "confirmation_status": "success"
                }
            ]
        },
        {
            "reference": "285a232b-a3b0-4af4-92f3-9c07d10aa13c",
            "amount": 500,
            "fees": "2.00",
            "currency": "XOF",
            "transaction_date": "2023-07-14T12:02:10.115968Z",
            "ip_address": "127.0.0.1",
            "status": "success",
            "live_mode": false,
            "payment_method": "mobile_money",
            "provider": "orange_bf",
            "phone": "77xxxxxx",
            "cancelled_at": null,
            "cancellation_reason": null,
            "created_at": "2023-07-14T12:02:10.128193Z",
            "updated_at": "2023-07-14T12:03:59.453015Z",
            "confirmation_attempts": [
                {
                    "ip_address": "127.0.0.1",
                    "attempt_date": "2023-07-14T12:03:59.403481Z",
                    "confirmation_status": "success"
                },
                {
                    "ip_address": "127.0.0.1",
                    "attempt_date": "2023-07-14T12:04:52.029977Z",
                    "confirmation_status": "failed"
                },
                {
                    "ip_address": "127.0.0.1",
                    "attempt_date": "2023-07-14T12:12:23.276340Z",
                    "confirmation_status": "failed"
                }
            ]
        },
    ]
}

(You can refer to the previously explained attributes for this list as they remain the same.)

balance

Retrieve the current balance information:

fetch user balance

GET /v1/payment/balances
curl --location 'https://api.senfenico.com/v1/payment/balances' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/balances
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/balances")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();                 

Response response = client.newCall(request).execute();
GET /v1/payment/balances
var https = require('follow-redirects').https;
var fs = require('fs');

var options = {
    'method': 'GET',
    'hostname': 'api.senfenico.com',
    'path': '/v1/payment/balances',
    'headers': {
        'Accept': 'application/json',
        'X-API-KEY': 'sk_test_...'
    },
    'maxRedirects': 20
};

var req = https.request(options, function (res) {
    var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });

    res.on("end", function (chunk) {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });

    res.on("error", function (error) {
        console.error(error);
    });
});

req.end();
GET /v1/payment/balances
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->balance->fetch([]);
GET /v1/payment/balances
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Balance.fetch()

Sample Response

sample response
{
    "status": true,
    "message": "Balance retrieved",
    "data": {
        "collection_balances": {
            "available": 18692.0,
            "pending": 5000.0,
            "currency": "XOF"
        },
        "transfer_balances": {
            "total_available": 0.0,
            "total_pending": 0.0,
            "orange_money_bf": {
                "available": 0.0,
                "pending": 0.0
            },
            "moov_money_bf": {
                "available": 0.0,
                "pending": 0.0
            },
            "sank_money_bf": {
                "available": 0.0,
                "pending": 0.0
            }
        }
    }
}

available vs pending Balance:

  • available: Ce solde correspond aux fonds qui sont immédiatement accessibles. Ces fonds sont prêts pour des transactions. Aucune restriction n'est appliquée à ce solde.
  • pending: Ce solde inclut les fonds qui sont en cours de transfert ou de règlement. Ces montants ne sont pas disponibles pour utilisation.

transfers

Overview

With Senfenico, you have two distinct types of balances: Collection Balance and Transfer Balance. When you collect or receive payments, the funds are credited to your Collection Balance. Conversely, when you send money, i.e., make a transfer, the amount is deducted from your Transfer Balance. It’s essential to ensure that your Transfer Balance has sufficient funds to cover the intended transfer.

At present, each wallet type maintains its own separate Transfer Balance:

  • Orange Money Transfer Balance
  • Moov Money Transfer Balance
  • Sank Money Transfer Balance

Transfer Balance Management

In the short term, we aim to provide a unified Transfer Balance across all wallets. In the medium term, our goal is to unify the Collection and Transfer Balances into a single, seamless balance. However, for now, you must individually top up each Transfer Balance to make transfers to the corresponding wallet.

For example, to transfer funds to a Moov Africa Burkina Faso account, you must ensure your Moov BF Transfer Balance has sufficient funds. The same applies to Orange Money and Sank Money.

single transfer

POST /v1/payment/transfers/
curl --location 'https://api.senfenico.com/v1/payment/transfers/' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: sk_live_...' \
--data '{
    "amount": 100,
    "recipient_phone": "63xxxxxx",
    "recipient_wallet": "sank_bf",
    "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064"
}'
POST /v1/payment/transfers/
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\r\n    \"amount\": 100,\r\n    \"recipient_phone\": \"63xxxxxx\",\r\n    \"recipient_wallet\": \"sank_bf\",\r\n    \"ext_id\": \"98b96ea4-210d-4ea0-9b03-8d7fd96e4064\"\r\n}");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/transfers/")
    .method("POST", body)
    .addHeader("Content-Type", "application/json")
    .addHeader("X-API-KEY", "sk_live_...")
    .build();
Response response = client.newCall(request).execute();
POST /v1/payment/transfers/
const axios = require('axios');
let data = JSON.stringify({
    "amount": 100,
    "recipient_phone": "63xxxxxx",
    "recipient_wallet": "sank_bf",
    "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064",
});

let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://api.senfenico.com/v1/payment/transfers/',
headers: { 
    'Content-Type': 'application/json', 
    'X-API-KEY': 'sk_live_...'
},
data : data
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
POST /v1/payment/transfers/
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->transfer->create([
    'amount' => 100,
    'recipient_phone' => '72184746',
    'recipient_wallet' => 'moov_bf',
    'ext_id' => '98b96ea4-210d-4ea0-9b03-8d7fd96e4064'
]);
POST /v1/payment/transfers/
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Transfer.create(
    amount=100,
    recipient_phone='63000000',
    recipient_wallet='sank_bf',
    ext_id='98b96ea4-210d-4ea0-9b03-8d7fd96e4064'
)
Parameter Type Optional Description
amount int No The amount you wish to transfer. (min: 100)
recipient_phone string No The phone number of the recipient.
recipient_wallet string Yes (Optional) The wallet to which the transfer is being made. If not provided, Senfenico will determine the wallet based on the recipient’s phone number. For example, a Moov BF number will automatically direct the transfer to a Moov BF wallet, and the same logic applies to Orange Money. Available options: [orange_bf, moov_bf, sank_bf]
ext_id string Yes External ID

Sample Response

Transfer has been queued
{
    "status": true,
    "message": "Transfer has been queued",
    "data": {
        "reference": "tr_ef733c5a98b04a51b00773256d8b8f2f",
        "amount": 100,
        "fees": 1.5,
        "recipient_phone": "63000000",
        "currency": "XOF",
        "ip_address": "172.18.0.1",
        "status": "pending",
        "live_mode": true,
        "recipient_wallet": "sank_bf",
        "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064",
        "created_at": "2024-03-21T21:08:33.336879Z"
    }
}
Insufficient balance
{
    "status": false,
    "message": "Insufficient balance for Sank BF transfer including fees.",
    "error_code": "INSUFFICIENT_FUNDS"
}
Response Element Type Description
reference string Reference of the transfer
amount int Transfered amount
fees string Transaction fees in percent (2 means 2%)
recipient_phone string Phone number used for transaction
currency string Currency code ["XOF"]
status string Status of the charge [success, failed, pending]
live_mode bool Indicates if it's a live transaction
recipient_wallet string recipient wallet [orange_bf, moov_bf, sank_bf]
ext_id string Unique external identifier provided by the client for tracking and referencing this transfer within their own system. Typically generated using methods like UUID.

bulk transfer

Senfenico supports bulk transfers, allowing you to process multiple transfers in a single request. However, please note the following constraints:

  • Batch Size: Limited to 100 transfers per request. If you require a larger batch size, please contact our support team.
  • Rate Limit: You cannot call the bulk transfer endpoint more than 5 times per second.
GET /v1/payment/transfers/bulk/
curl --location 'https://api.senfenico.com/v1/payment/transfers/bulk/' \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: sk_live_...' \
--data '{
    "transfers": [
        {
            "amount": 100,
            "recipient_phone": "65xxxxxx",
            "recipient_wallet": "orange_bf"
        },
        {
            "amount": 100,
            "recipient_phone": "63xxxxxx"
        }
    ]
}'
GET /v1/payment/transfers/bulk/
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\r\n    \"transfers\": [\r\n        {\r\n            \"amount\": 100,\r\n            \"recipient_phone\": \"65xxxxxx\",\r\n            \"recipient_wallet\": \"orange_bf\"\r\n        },\r\n        {\r\n            \"amount\": 100,\r\n            \"recipient_phone\": \"63xxxxxx\"\r\n        }\r\n    ]\r\n}");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/transfers/bulk/")
    .method("POST", body)
    .addHeader("Content-Type", "application/json")
    .addHeader("X-API-KEY", "sk_live_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/transfers/bulk/
const axios = require('axios');
let data = JSON.stringify({
"transfers": [
    {
        "amount": 100,
        "recipient_phone": "65xxxxxx",
        "recipient_wallet": "orange_bf"
    },
    {
        "amount": 100,
        "recipient_phone": "63xxxxxx"
    }
]
});

let config = {
    method: 'post',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/transfers/bulk/',
    headers: { 
        'Content-Type': 'application/json', 
        'X-API-KEY': 'sk_live_...'
    },
    data : data
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
GET /v1/payment/transfers/bulk/
$senfenico = new \Senfenico\Senfenico('sk_test_...');

$senfenico->transfer->bulkCreate([
    'transfers' => [
        [
            'amount' => 100,
            'recipient_phone' => '65xxxxxx',
            'recipient_wallet' => 'orange_bf'
        ],
        [
            'amount' => 100,
            'recipient_phone' => '63xxxxxx',
            'ext_id' => '98b96ea4-210d-4ea0-9b03-8d7fd96e4064'
        ]
    ]
]);
GET /v1/payment/transfers/bulk/
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Transfer.bulk_create(
    transfers=[
        {"amount": 100, "recipient_phone": "65xxxxxx", "recipient_wallet": "orange_bf"},
        {"amount": 100, "recipient_phone": "63xxxxxx", "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064"}
    ]
)

Sample Response

2 transfers queued for processing
{
    "status": true,
    "message": "2 transfers queued for processing",
    "failed_transfers": []
}
1 transfers queued
{
    "status": true,
    "message": "1 transfers queued for processing",
    "failed_transfers": [
        {
            "data": {
                "amount": 100,
                "recipient_phone": "63xxxxxx",
                "recipient_wallet": null,
                "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064"
            },
            "errors": {
                "non_field_errors": [
                    "Insufficient balance for Moov BF transfer including fees."
                ]
            }
        }
    ]
}
Bad reauest
{
    "status": false,
    "message": "Maximum of 100 transfers allowed per request",
    "error_code": "BATCH_SIZE_LIMIT_EXCEEDED"
}

(You can refer to the previously explained attributes for this list as they remain the same.)

list transfers

This endpoint is used to retrieve a list of all transfers.

GET /v1/payment/transfers
curl --location 'https://api.senfenico.com/v1/payment/transfers/' \
--header 'X-API-KEY: sk_live_...'
GET /v1/payment/transfers
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/transfers/")
    .method("GET", body)
    .addHeader("X-API-KEY", "sk_live_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/transfers
const axios = require('axios');

let config = {
    method: 'get',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/transfers/',
    headers: { 
        'X-API-KEY': 'sk_live_...'
    }
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
GET /v1/payment/transfers
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$transfers = $senfenico->transfer->list([]);
GET /v1/payment/transfers
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Transfer.list()

Sample Response

settlement list retrieved
{
    "status": true,
    "message": "Transfer list retrieved",
    "data": [
        {
            "reference": "tr_61242504fdf24d1b9f5344deed8657f9",
            "amount": 100,
            "fees": "1.50",
            "currency": "XOF",
            "ip_address": "172.18.0.1",
            "status": "pending",
            "live_mode": true,
            "recipient_wallet": "orange_bf",
            "recipient_phone": "65xxxxxx",
            "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064",
            "created_at": "2024-03-21T13:34:34.268389Z"
        },
        {
            "reference": "tr_f93b234379994c4498c0014d87936dae",
            "amount": 100,
            "fees": "1.50",
            "currency": "XOF",
            "ip_address": "172.18.0.1",
            "status": "pending",
            "live_mode": true,
            "recipient_wallet": "orange_bf",
            "recipient_phone": "76xxxxxx",
            "ext_id": "73b96ea4-210d-4ea0-9b03-8d7fd96e4052",
            "created_at": "2024-03-21T13:22:51.139807Z"
        }
    ]
}

(You can refer to the previously explained attributes for this list as they remain the same.)

fetch single transfer

You can fetch details of a single transfer using this endpoint:

GET /v1/payment/transfers/:transfer_reference
curl --location 'https://api.senfenico.com/v1/payment/transfers/tr_61242504fdf24d1b9f5344deed8657f9' \
--header 'X-API-KEY: sk_live_...'
GET /v1/payment/transfers/:transfer_reference
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/transfers/tr_61242504fdf24d1b9f5344deed8657f9")
    .method("GET", body)
    .addHeader("X-API-KEY", "sk_live_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/transfers/:transfer_reference
const axios = require('axios');

let config = {
    method: 'get',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/transfers/tr_61242504fdf24d1b9f5344deed8657f9',
    headers: { 
        'X-API-KEY': 'sk_live_...'
    }
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
GET /v1/payment/transfers/:transfer_reference
$senfenico = new \Senfenico\Senfenico('sk_test_...');

$senfenico->transfer->fetch('tr_c6ddbab683424a8e8b906b46da52aea8', []);
GET /v1/payment/transfers/:transfer_reference
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Transfer.fetch("tr_61242504fdf24d1b9f5344deed8657f9")

Sample Response

Transfer details retrieved
{
    "status": true,
    "message": "Transfer details retrieved",
    "data": {
        "reference": "tr_61242504fdf24d1b9f5344deed8657f9",
        "amount": 100,
        "fees": "1.50",
        "currency": "XOF",
        "ip_address": "172.18.0.1",
        "status": "pending",
        "live_mode": true,
        "recipient_wallet": "orange_bf",
        "recipient_phone": "65xxxxxx",
        "created_at": "2024-03-21T13:34:34.268389Z",
        "ext_id": "98b96ea4-210d-4ea0-9b03-8d7fd96e4064",
    }
}

(You can refer to the previously explained attributes for this list as they remain the same.)

Important Considerations Transfers in Senfenico are processed asynchronously. Therefore, we strongly advise you to implement webhooks to monitor the status of your transfers in real-time. This ensures that your application can respond to transfer updates promptly and accurately.

settlements

Settlements allow you to transfer funds from your account to a designated payment account. Use this section to manage settlements.

create settlement

This endpoint is used to create a settlement to a designated payment account.

Note: If a payment account is not created, the settlement creation request will fail because the system needs to know where to send the money. You can create a payment account from the administration interface in the business setting menu.

POST /v1/payment/settlements/
curl --location 'https://api.senfenico.com/v1/payment/settlements/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...' \
--data '{
    "amount": "1000"
}'
POST /v1/payment/settlements/
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n  \"amount\": \"1000\"\n}");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/settlements/")
    .method("POST", body)
    .addHeader("Content-Type", "application/json")
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
POST /v1/payment/settlements/
const axios = require('axios');
let data = JSON.stringify({
    "amount": "1000"
});

let config = {
    method: 'post',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/settlements/',
    headers: { 
        'Content-Type': 'application/json', 
        'Accept': 'application/json', 
        'X-API-KEY': 'sk_test_...', 
    },
    data : data
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
POST /v1/payment/settlements/
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->settlement->create([
    'amount' => 5000
]);
POST /v1/payment/settlements/
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Settlement.create(amount=5000)
Parameter Type Optional Description
amount int No Amount to settlement

Sample Response

Settlement created
{
    "status": true,
    "message": "Settlement created",
    "data": {
        "reference": "d1b19637-3cce-45e7-898b-265ddfbc981c",
        "amount": 1000,
        "settlement_fees": 2,
        "currency": "XOF",
        "status": "processing",
        "live_mode": false,
        "created_at": "2023-07-30T19:23:01.658300Z",
        "updated_at": "2023-07-30T19:23:01.659013Z",
        "account_type": "bank",
        "iban": null,
        "rib": "YOUR RIB",
        "bank_name": null,
        "bank_address": null,
        "account_holder_name": null,
        "account_holder_address": null,
        "swift_bic_code": null,
        "provider": null,
        "phone": null,
        "usdt_wallet_address": null
    }
}
Response Element Type Possible Values Description
reference string - Reference of the settlement
amount int - Settlement amount
settlement_fees int - Settlement fees
currency string "XOF" Currency code
status string "processing", "in_transit", "success", "cancelled" Status of the settlement
live_mode bool true, false Indicates if it's a live transaction
account_type string "bank", "mobile", "usdt" Account type
rib string - RIB of the bank
other banking details null - Other banking information as null if not provided

fetch settlement

This endpoint is used to retrieve the details of a specific settlement

GET /v1/payment/settlements/:settlement_reference
curl --location 'https://api.senfenico.com/v1/payment/settlements/{settlement_reference}' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/settlements/:settlement_reference
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/settlements/{settlement_reference}")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/settlements/:settlement_reference
const axios = require('axios');

let config = {
    method: 'get',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/settlements/{settlement_reference}',
    headers: { 
        'Accept': 'application/json', 
        'X-API-KEY': 'sk_test_...', 
    }
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
GET /v1/payment/settlements/:settlement_reference
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->settlement->fetch('xxxxxx...', []);
GET /v1/payment/settlements/:settlement_reference
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Settlement.fetch(settlement_reference="655342d1-c1a3-44eb-aee7-a2fddcadeaf2")

Sample Response

Settlement retrieved
{
    "status": true,
    "message": "Settlement retrieved",
    "data": {
        "reference": "dc5a902d-a4eb-4025-b4f1-3c9b30468b64",
        "amount": 1000,
        "settlement_fees": 2,
        "currency": "XOF",
        "status": "processing",
        "live_mode": false,
        "created_at": "2023-07-30T20:42:31.147100Z",
        "updated_at": "2023-07-30T20:42:31.147612Z",
        "account_type": "bank",
        "iban": null,
        "rib": "YOUR RIB",
        "bank_name": null,
        "bank_address": null,
        "account_holder_name": null,
        "account_holder_address": null,
        "swift_bic_code": null,
        "provider": null,
        "phone": null,
        "usdt_wallet_address": null
    }
}

(You can refer to the previously explained attributes for this list as they remain the same.)

list settlements

This endpoint is used to retrieve a list of all settlements.

GET /v1/payment/settlements
curl --location 'https://api.senfenico.com/v1/payment/settlements' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...'
GET /v1/payment/settlements
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/settlements")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();
Response response = client.newCall(request).execute();
GET /v1/payment/settlements
const axios = require('axios');

let config = {
    method: 'get',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/settlements',
    headers: { 
        'Accept': 'application/json', 
        'X-API-KEY': 'sk_test_...', 
    }
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
GET /v1/payment/settlements
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->settlement->list([]);
GET /v1/payment/settlements
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Settlement.list()

Sample Response

settlement list retrieved
{
    "status": true,
    "message": "settlement list retrieved",
    "data": [
        {
            "reference": "c067a1ce-0112-44d0-bd1f-ed1c004ee98b",
            "amount": 1000,
            "settlement_fees": 2,
            "currency": "XOF",
            "status": "in_transit",
            "live_mode": false,
            "created_at": "2023-07-30T20:59:33.794435Z",
            "updated_at": "2023-07-30T21:11:43.494159Z",
            "account_type": "bank",
            "iban": null,
            "rib": "YOUR RIB",
            "bank_name": null,
            "bank_address": null,
            "account_holder_name": null,
            "account_holder_address": null,
            "swift_bic_code": null,
            "provider": null,
            "phone": null,
            "usdt_wallet_address": null
        }
    ]
}

(You can refer to the previously explained attributes for this list as they remain the same.)

cancel settlement

This endpoint is used to cancel a specific settlement. A settlement can only be canceled if it's in 'processing' status.

GET /v1/payment/settlements/{settlement_reference}/cancel/
curl --location 'https://api.senfenico.com/v1/payment/settlements/{settlement_reference}/cancel/' \
--header 'Accept: application/json' \
--header 'X-API-KEY: sk_test_...' \
--header 'Cookie: csrftoken=OikaoS1C0Byqwl75MmMDTbgiKoESKNK1'
GET /v1/payment/settlements/{settlement_reference}/cancel/
OkHttpClient client = new OkHttpClient().newBuilder()
    .build();

MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
    .url("https://api.senfenico.com/v1/payment/settlements/{settlement_reference}/cancel/")
    .method("GET", body)
    .addHeader("Accept", "application/json")
    .addHeader("X-API-KEY", "sk_test_...")
    .build();

Response response = client.newCall(request).execute();
GET /v1/payment/settlements/{settlement_reference}/cancel/
const axios = require('axios');

let config = {
    method: 'get',
    maxBodyLength: Infinity,
    url: 'https://api.senfenico.com/v1/payment/settlements/{settlement_reference}/cancel/',
    headers: { 
        'Accept': 'application/json', 
        'X-API-KEY': 'sk_test_...', 
    }
};

axios.request(config)
.then((response) => {
    console.log(JSON.stringify(response.data));
})
.catch((error) => {
    console.log(error);
});
GET /v1/payment/settlements/{settlement_reference}/cancel/
$senfenico = new \Senfenico\Senfenico('sk_test_...');
$senfenico->settlement->cancel('xxxxxx...', []);
GET /v1/payment/settlements/{settlement_reference}/cancel/
import senfenico
senfenico.api_key = 'sk_test_...'

senfenico.Settlement.cancel(settlement_reference="74bba04a-16e0-491d-a991-c4726799f68e")

Sample Response

Settlement cancelled
{
    "status": true,
    "message": "Settlement cancelled",
    "data": {
        "reference": "dc5a902d-a4eb-4025-b4f1-3c9b30468b64",
        "amount": 1000,
        "settlement_fees": 2,
        "currency": "XOF",
        "status": "cancelled",
        "live_mode": false,
        "created_at": "2023-07-30T20:42:31.147100Z",
        "updated_at": "2023-07-30T20:57:18.909852Z",
        "account_type": "bank",
        "iban": null,
        "rib": "YOUR RIB",
        "bank_name": null,
        "bank_address": null,
        "account_holder_name": null,
        "account_holder_address": null,
        "swift_bic_code": null,
        "provider": null,
        "phone": null,
        "usdt_wallet_address": null
    }
}
Settlement can only be cancelled if it's in 'processing' status
{
    "status": false,
    "message": "Validation error: [\"Settlement can only be cancelled if it's in 'processing' status.\"]"
}

(You can refer to the previously explained attributes for this cancel response as they remain the same.)

Tester votre intégration

Before going live with your integration, we recommend thoroughly testing it to ensure everything works as expected. To facilitate this, we've provided test numbers and balances that you can use to simulate transactions.

provider phone amount OTP
orange_bf 76000000 1000 123456
orange_bf 77000000 1500 123456
orange_bf 65000000 2000 123456
moov_bf 70000000 1000 123456
moov_bf 71000000 1500 123456
moov_bf 72000000 2000 123456
coris_bf 72000000 1000 123456
coris_bf 75000000 1500 123456
coris_bf 68000000 2000 123456
sank_bf 72000000 1000 123456
sank_bf 75000000 1500 123456
sank_bf 68000000 2000 123456

For testing transfers, you can initiate a transfer to any valid Burkina Faso number. We've topped up your test transfer balances with 100,000 FCFA for each wallet, giving you ample room to test the feature.

We recommend using the same numbers listed above for payment testing to ensure consistency across your tests.

Once you've successfully tested your integration and are satisfied with the results, you can proceed to use your live API key for real transactions.

Error Codes

In this section, you will find a comprehensive list of error codes that our API might return. Each error code is accompanied by a brief description of the issue, both in English and French, to help you understand and resolve any issues that may arise during integration or usage.

Error Codes Overview When something goes wrong with an API request, you will receive an error response that includes the following fields:

  • status: Always false for error responses.
  • message: A human-readable message explaining the response.
  • error_code: A unique code identifying the error.
  • description: A detailed description of the error.
  • description_fr: La description détaillée de l'erreur en français.

Below is a list of possible error codes along with their descriptions:

Code Description Description(fr)
BATCH_SIZE_LIMIT_EXCEEDED The request exceeds the maximum batch size of 100 items. Please reduce the number of items in the batch and try again. La requête dépasse la taille maximale autorisée de 100 éléments. Veuillez réduire le nombre d'éléments dans le lot et réessayer.
RATE_LIMIT_EXCEEDED You have exceeded the rate limit for API requests. Please wait before making further requests. Vous avez dépassé la limite de taux pour les requêtes API. Veuillez patienter avant de faire d'autres requêtes.
UNSUPPORTED_PROVIDER UNSUPPORTED_PROVIDER UNSUPPORTED_PROVIDER
OTP_INVALID The OTP is invalid. Please try again. OTP invalide fournies. Veuillez vérifier et réessayer.
OTP_EXPIRED The OTP has expired. Please request a new one. Le code OTP a expiré. Veuillez en demander un nouveau.
OTP_STILL_VALID The current OTP is still valid. Please use the existing OTP or wait until it expires to request a new one. Le code OTP actuel est toujours valide. Veuillez utiliser le code OTP existant ou attendre qu'il expire pour en demander un nouveau.
INSUFFICIENT_FUNDS Account holder does not have enough funds to complete this transaction. Le titulaire du compte n'a pas suffisamment de fonds pour effectuer cette transaction.
INVALID_ACCOUNT The phone number is not valid or is not associated with an account with operator. Please check the phone number and try again. Le numéro de téléphone n'est pas valide ou n'est pas associé à un compte chez l'opérateur. Veuillez vérifier le numéro de téléphone et réessayer.
NETWORK_ERROR A network error occurred. Please try again later. Une erreur de réseau est survenue. Veuillez réessayer plus tard.
CHARGE_NOT_FOUND Charge with the given reference not found. La transaction avec la référence donnée est introuvable.
INTERNAL_ERROR An internal error occurred. Please try again later. Une erreur interne est survenue. Veuillez réessayer plus tard.
UNKNOWN_ERROR An unknown error occurred. Please try again later. Une erreur inconnue est survenue. Veuillez réessayer plus tard.
TRANSACTION_NOT_FOUND Transaction not found. Transaction introuvable.
UNAUTHORIZED_CHARGE_PROVIDER You are not authorized to charge this provider. If you think this is an error, please contact Senfenico team. Vous n'êtes pas autorisé à collecter les paiement de cet opérateur. Si vous pensez qu'il s'agit d'une erreur, veuillez contacter l'équipe de Senfenico.
EXTERNAL_API_ERROR The OTP is invalid. Please try again. An error occurred with an external API. Please try again later or contact support if the issue persists. Veuillez réessayer plus tard ou contacter le support si le problème persiste.
INVALID_DATA Invalid data provided. Please check the input and try again. Données invalides fournies. Veuillez vérifier les données saisies et réessayer.

Once you've successfully tested your integration, you can proceed to use your live API key for real transactions

Conclusion

Cette documentation de l'API offre un aperçu des endpoint disponibles pour gérer les paiements avec l'API de Senfenico. En suivant les directives et exemples fournis, vous pouvez intégrer Senfenico dans votre application et commencer à accepter les paiements de manière fluide.

Si vous avez des questions ou besoin d'assistance supplémentaire, n'hésitez pas à contacter l'équipe de support de Senfenico à contact@senfenico.com.