Getting Started
The Jemeni.NET API enables you to create and manage payments, subscriptions, OTP verifications, and transaction tracking.
To access the API, you'll need an API Key. Please sign in to retrieve your credentials.
BASE_URL: https://jemeni.net/api
Authentication
Every request must include an auth-signature
in the headers. The signature is a SHA-512 hash of the following string:
SHA512(SK + "+" + TK + "+" + METHOD + "+" + URL + "+" + BODY + "+" + TIMESTAMP)
- SK: Your secret key (from your credentials)
- TK: Your token key (Bearer token)
- METHOD: HTTP method (e.g. POST)
- URL: Full request URL
- BODY: Raw request body (empty for GET)
- TIMESTAMP: Current UNIX timestamp (in seconds)
π¦ Example Request (cURL)
curl -X POST {BASE_URL}/{resource} \
-H "Authorization: Bearer your_token_key" \
-H "auth-signature: 2a4e9b10a57e4c3e7b2..." \
-H "Timestamp: 1700000000" \
-H "Content-Type: application/json" \
-d '{"data":"test"}'
You can adapt this request in any programming language using your preferred HTTP client (e.g. Axios, Guzzle, `http` in Dart, etc.).
π Security Notes
- Keep your
SK
confidential. Never expose it in client-side code. - Use the current UNIX
TIMESTAMP
to prevent replay attacks. - Ensure all requests are sent over HTTPS.
Check Transaction Status
To retrieve the current state of a transaction, send a GET request to the endpoint below, including your authentication headers.
π Endpoint
GET {BASE_URL}/sandbox/payment/verify/state?transaction_id={id}
π¦ Example Request (cURL)
curl -X GET "{BASE_URL}/sandbox/payment/verify/state?transaction_id=01HJXYZ..." \
-H "auth-apiKey: pk_test_37........bf76b6dc218" \
-H "auth-timestamp: 2024-04-24 16:55:00" \
-H "auth-token: your_access_token" \
-H "auth-signature: your_signature_hash" \
-H "Content-Type: application/json" \
-H "Accept: application/json"
π§Ύ Required Headers
Header | Type | Description |
---|---|---|
auth-apiKey |
String | Required. Your public API key. |
auth-timestamp |
String | Required. Current timestamp (used in signature). |
auth-token |
String | Required. Userβs access token. |
auth-signature |
String | Required. Signature generated using your credentials. |
π€ Example Response
{
"status": "success",
"message": "Transaction retrieved successfully.",
"data": {
"id": '132132132',
"amount": "500.00",
"state": 2,
"customer": {
"id": 45,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "+22370000000",
"country_code": 1,
},
"client_merchants": [...],
"client": {
"id": 8,
"name": "Acme Corp",
"status": 1,
...
},
"payment": {
"id": "xyz123",
"subscription_id": "sub_456",
"amount": "500.00",
"due_at": "2024-11-22 19:57:14",
"status": "completed",
"payment_reference": "JP-XXXXXXXXXX"
}
}
}
You can refer to the transaction state codes in the error/code reference section for more details on what each state value represents.
Initiate a Transaction
This endpoint allows you to initiate a payment from a customer's mobile account. Send a POST request with the required information and authentication headers.
π Endpoint
POST {BASE_URL}/sandbox/send/payment
π¦ Example Request (cURL)
curl -X POST "{BASE_URL}/sandbox/send/payment" \
-H "auth-apiKey: pk_test_37........bf76b6dc218" \
-H "auth-timestamp: 2024-04-24 16:55:00" \
-H "auth-token: your_access_token" \
-H "auth-signature: your_signature_hash" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{
"customer_phone":"78000000",
"amount":9000,
"device":"FCFA",
"country_code":"ml",
"notifiable":true
}'
π§Ύ Required Headers
Header | Type | Description |
---|---|---|
auth-apiKey |
String | Your public API key. |
auth-timestamp |
String | Current timestamp (used for signature). |
auth-token |
String | User's access token. |
auth-signature |
String | SHA-512 signature of the request payload. |
π¨ Request Body
Field | Type | Description |
---|---|---|
customer_phone |
String | Required. Customer's phone number (with country code). |
amount |
Number | Required. Amount to charge. |
device |
String | Optional. Device used for the transaction. |
lang |
String | Optional. Language preference (e.g., en , fr ). |
version |
String | Optional. API version (default: v1 ). |
country_code |
Number | Required. Code of the country (e.g., Ml for Mali). |
return_url |
String | Optional. Callback URL after transaction processing. |
π€ Example Response
{
"status": "success",
"message": "Payment initiated successfully.",
"data": {
"id": "01jz0p4y6g5jxe0abeazw12j55",
"amount": 9000,
"state": 1,
"reference": "6862a8914c1d5bbabd99cf54",
"created_at": "2025-06-30 15:09:05",
"customer": {
"id": "01jxk881aztej3mnd5aj4yt7hk",
"first_name": "Kadiatou",
"last_name": "Maiga",
"email": "kmaiga@ktminnov.com",
"phone": "78521436",
"country_code": "ml"
},
"client": {
"id": "01jwvrvjswcex8n3ajv0njfpx6",
"name": "KTM SHOP",
"client_type_code": "shop",
"location": "Segou"
},
"payment": {
"id": "01jz0p4y6g5jxe0abeazw12j55",
"subscription_id": null,
"amount": "500.00",
"status": "pending",
"payment_reference": "JP-ABC123456",
}
}
}
Create a Subscription
This endpoint allows you to create a recurring subscription for a customer based on a predefined plan and billing frequency.
π Endpoint
POST {BASE_URL}/sandbox/subscriptions/create
π¦ Example Request (cURL)
curl -X POST "{BASE_URL}/sandbox/subscriptions/create" \
-H "auth-apiKey: pk_test_fce1β’β’β’β’β’β’c821c60e" \
-H "auth-timestamp: 2024-04-24 16:55:00" \
-H "auth-token: your_access_token" \
-H "auth-signature: your_signature_hash" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{
"phone": "+22370000000",
"plan_id": 1,
"frequency_id": 1,
"start_at": "2024-10-27"
}'
π§Ύ Required Headers
Header | Type | Description |
---|---|---|
auth-apiKey |
String | Your public API key. |
auth-timestamp |
String | Current UNIX timestamp (used in signature). |
auth-token |
String | User access token. |
auth-signature |
String | SHA-512 signature of the request payload. |
π¨ Request Body
Field | Type | Description |
---|---|---|
phone |
String | Required. Customer's phone number (with country code). |
plan_id |
Integer | Required. The ID of the subscription plan. |
frequency_id |
Integer | Required. The frequency ID (e.g. monthly, weekly). |
start_at |
String (date) | Required. Subscription start date (format: YYYY-MM-DD). |
π€ Example Response
{
"status": "success",
"message": "Subscription created successfully",
"data": {
"id": '01ezezezezraezaez',
"client_id": 3,
"plan_id": 1,
"customer_id": 2,
"status": "active",
"start_at": "2024-10-27 00:00:00",
"expire_at": "2025-01-09 21:55:07",
"archived": false,
"renewal_date": null,
"renewed": false
}
}
List Subscription Plans
This endpoint allows you to retrieve all available subscription plans configured for your account.
π Endpoint
POST {BASE_URL}/sandbox/subscriptions/plans
π¦ Example Request (cURL)
curl -X POST "{BASE_URL}/sandbox/subscriptions/plans" \
-H "auth-apiKey: pk_test_fce1β’β’β’β’β’β’c821c60e" \
-H "auth-timestamp: 2024-09-17 23:08:00" \
-H "auth-token: your_access_token" \
-H "auth-signature: your_signature_hash" \
-H "Content-Type: application/json" \
-H "Accept: application/json"
π§Ύ Required Headers
Header | Type | Description |
---|---|---|
auth-apiKey |
String | Your public API key. |
auth-timestamp |
String | Current timestamp (format: YYYY-MM-DD HH:mm:ss ). |
auth-token |
String | User access token. |
auth-signature |
String | SHA-512 signature of the request payload. |
π€ Example Response
{
"status": "success",
"message": "List of subscription plans",
"data": [
{
"id": '01zedqfdfqsdfqfqfsqdf',
"client_id": '01sdsd3123sdsdsdsd',
"name": "Basic Plan",
"price": "2000.00",
"frequency_id": 1,
"archived": false,
},
...
]
}
Cancel a Subscription
This endpoint allows you to cancel an active subscription linked to a specific customer's phone number.
π Endpoint
POST {BASE_URL}/sandbox/subscriptions/disable
π¦ Example Request (cURL)
curl -X POST "{BASE_URL}/sandbox/subscriptions/disable" \
-H "auth-apiKey: pk_test_β’β’β’β’β’β’β’β’β’β’β’β’β’β’β’β’β’β’β’β’" \
-H "auth-timestamp: 2024-09-24 22:06:00" \
-H "auth-token: your_access_token" \
-H "auth-signature: your_signature_hash" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{
"phone": "+22370000000"
}'
π§Ύ Required Headers
Header | Type | Description |
---|---|---|
auth-apiKey |
String | Your public API key. |
auth-timestamp |
String | Current timestamp (format: YYYY-MM-DD HH:mm:ss ). |
auth-token |
String | User access token. |
auth-signature |
String | SHA-512 signature of the request payload. |
π¨ Request Body
Field | Type | Description |
---|---|---|
phone |
String | Required. The phone number of the customer. |
π€ Example Response
{
"status": "success",
"message": "Customer subscription disabled successfully",
"data": {
"id": "01zezezezerdfezdez",
"first_name": "Awa",
"last_name": "Sow",
"email": "awa.sow@email.ml",
"phone": "+22370000000",
"country_code": 'ml',
}
}
Generate a Payment Link
Jemeni.NET allows you to receive payments without needing to integrate the API. You can create secure payment links and share them directly with your customers.
π§ How It Works
- Step 1 - Generate the Link: Log into your dashboard and create a new payment link for your customer.
- Step 2 - Share the Link: Send the link via SMS, email, WhatsApp, or any messaging platform.
- Step 3 - Receive Payment: The customer clicks the link, fills out payment info, and completes the transaction securely.
β Benefits
- No technical integration required.
- Perfect for freelancers, small businesses, or quick one-time charges.
- Real-time payment tracking via your dashboard.
Use cases: Remote sales, invoice payments, social commerce, donation campaigns, and more.
Ready to start? Log in to generate your first payment link today.
Send a Payment Notification
The payment notification system lets you trigger payment requests directly to a customerβs JemeniPay account, without using a public payment link.
π§ How It Works
- Step 1 - Initiate a Notification: From your system or dashboard, send a payment request tied to the customer's phone number.
- Step 2 - Customer is Notified: The customer receives an instant notification within their JemeniPay app or channel.
- Step 3 - Direct Payment: The customer can pay securely, without the need to click on any external link.
β Benefits
- No link sharing required.
- Secure and personalized experience via JemeniPay interface.
- Ideal for in-app payments, recurring charges, or enterprise scenarios.
Use case examples: utility bill reminders, subscription renewals, loan installments, or payment follow-ups.
Ready to try it? Log in to your dashboard and start sending payment notifications to your customers.
Webhooks Integration
JemeniPay supports webhooks to notify your system in real time when key events occur (e.g., successful payments, subscription renewals, invoice creations). This enables automated and efficient workflows between JemeniPay and your backend systems.
π¦ How Webhooks Work
- 1. Event Triggered: A specific event (e.g.,
payment.success
) is detected by JemeniPay. - 2. Notification Sent: JemeniPay sends an HTTP POST request to your configured webhook endpoint.
- 3. Payload Received: Your server receives the JSON payload and processes it (e.g., updates a transaction status).
- 4. Signature Validation: You verify the authenticity of the payload using the signature provided.
- 5. Acknowledgement: Your endpoint responds with a
200 OK
status to confirm receipt. If not, JemeniPay retries the request.
π Security & Reliability
- Signature verification: Every webhook request includes a signature hash. We recommend validating it to ensure trust.
- Retry mechanism: JemeniPay automatically retries failed webhook deliveries up to a few times.
- Event filtering: You can choose which events trigger notifications via your dashboard or API settings.
π¨ Example Payload
{
"event": "payment.success",
"data": {
"reference": "TX12345",
"amount": 1000,
"currency": "XOF",
"status": "success",
"customer_id": "CUST6789"
},
"timestamp": "2024-12-30T12:34:56Z",
"signature": "abcdef1234567890"
}
You can use the reference
field to reconcile the transaction in your system, and the signature
to validate the payload.
π§ Status
Webhooks are currently in active development. More event types and customization options will be released soon.
HTTP Codes
The JΙmΙnipay API uses the following error codes:
HTTP Code Descriptions for API Documentation
2xx Success
- 200 OK: The request was successful, and the response contains the requested data.
- 201 Created: The request was successful, and a new resource was created.
- 202 Accepted: The request has been accepted for processing but is not yet complete.
- 204 No Content: The request was successful, but there is no content to return.
3xx Redirection
- 301 Moved Permanently: The resource has been permanently moved to a new URL.
- 302 Found: The resource is temporarily located at a different URL.
- 304 Not Modified: The resource has not been modified since the last request.
4xx Client Errors
- 400 Bad Request: The server could not understand the request due to invalid syntax.
- 401 Unauthorized: Authentication is required, or it has failed.
- 403 Forbidden: The server understands the request but refuses to authorize it.
- 404 Not Found: The requested resource could not be found.
- 429 Too Many Requests: The client has sent too many requests in a given amount of time (rate limiting).
5xx Server Errors
- 500 Internal Server Error: The server encountered an unexpected condition.
- 501 Not Implemented: The server does not support the functionality required to fulfill the request.
- 502 Bad Gateway: The server received an invalid response from the upstream server.
- 503 Service Unavailable: The server is currently unable to handle the request due to maintenance or overload.
- 504 Gateway Timeout: The server did not receive a timely response from the upstream server.
Custom Error Ranges
3000-3999 (Custom Redirection Codes)
Reserved for API-specific redirection behaviors.
4000-4999 (Custom Client Errors)
- 4001 Invalid Input Data: The input data provided is invalid.
- 4002 Resource Constraint Exceeded: A request exceeded a defined limit.
5000-5999 (Custom Server Errors)
- 5001 Database Connection Failed: The server could not connect to the database.
- 5002 Service Dependency Timeout: A dependent service did not respond in time.