curl --request POST \
--url https://api.payaza.africa/live/subscription/api/v1/subscriptions \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"customerEmail": "johndoe@gmail.com",
"planCode": "PLN_906FE4B",
"cardDetails": {
"cardNumber": "554656xxxxxx742",
"expiryMonth": "01",
"expiryYear": "02",
"securityCode": "123",
"cardHolderName": "John Doe",
"present": true
}
}
'import requests
url = "https://api.payaza.africa/live/subscription/api/v1/subscriptions"
payload = {
"customerEmail": "johndoe@gmail.com",
"planCode": "PLN_906FE4B",
"cardDetails": {
"cardNumber": "554656xxxxxx742",
"expiryMonth": "01",
"expiryYear": "02",
"securityCode": "123",
"cardHolderName": "John Doe",
"present": True
}
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
customerEmail: 'johndoe@gmail.com',
planCode: 'PLN_906FE4B',
cardDetails: {
cardNumber: '554656xxxxxx742',
expiryMonth: '01',
expiryYear: '02',
securityCode: '123',
cardHolderName: 'John Doe',
present: true
}
})
};
fetch('https://api.payaza.africa/live/subscription/api/v1/subscriptions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.payaza.africa/live/subscription/api/v1/subscriptions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'customerEmail' => 'johndoe@gmail.com',
'planCode' => 'PLN_906FE4B',
'cardDetails' => [
'cardNumber' => '554656xxxxxx742',
'expiryMonth' => '01',
'expiryYear' => '02',
'securityCode' => '123',
'cardHolderName' => 'John Doe',
'present' => true
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.payaza.africa/live/subscription/api/v1/subscriptions"
payload := strings.NewReader("{\n \"customerEmail\": \"johndoe@gmail.com\",\n \"planCode\": \"PLN_906FE4B\",\n \"cardDetails\": {\n \"cardNumber\": \"554656xxxxxx742\",\n \"expiryMonth\": \"01\",\n \"expiryYear\": \"02\",\n \"securityCode\": \"123\",\n \"cardHolderName\": \"John Doe\",\n \"present\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.payaza.africa/live/subscription/api/v1/subscriptions")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"customerEmail\": \"johndoe@gmail.com\",\n \"planCode\": \"PLN_906FE4B\",\n \"cardDetails\": {\n \"cardNumber\": \"554656xxxxxx742\",\n \"expiryMonth\": \"01\",\n \"expiryYear\": \"02\",\n \"securityCode\": \"123\",\n \"cardHolderName\": \"John Doe\",\n \"present\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.payaza.africa/live/subscription/api/v1/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customerEmail\": \"johndoe@gmail.com\",\n \"planCode\": \"PLN_906FE4B\",\n \"cardDetails\": {\n \"cardNumber\": \"554656xxxxxx742\",\n \"expiryMonth\": \"01\",\n \"expiryYear\": \"02\",\n \"securityCode\": \"123\",\n \"cardHolderName\": \"John Doe\",\n \"present\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Subscription created",
"data": {
"subscription": {
"id": 20,
"customerId": "null",
"customerEmail": "johndoe@gmail.com",
"firstName": null,
"lastName": null,
"customerAuthorizedAt": null,
"status": "ACTIVE",
"currentPeriodStart": "2026-07-08T19:35:52.348327",
"currentPeriodEnd": "2026-08-08T19:35:55.569925",
"nextChargeDate": "2026-08-08T19:35:55.569925",
"trialEndDate": null,
"pauseResumesAt": null,
"cancelAt": null,
"pausedAt": null,
"cancelledAt": null,
"cancellationReason": null,
"cardExpiryAlertSent": false,
"connectionMode": "Live",
"enrollmentReference": "SUBREF_BFE417ABF6FF49A985",
"enrollmentTxnReference": "SUB_ENROLL_20_1783539352354",
"chargeMode": "DIRECT_CHARGE",
"metadata": null,
"createdAt": "2026-07-08T19:35:52.34833",
"updatedAt": "2026-07-08T19:35:55.573662",
"customerBearsFee": false,
"enrollConfirmed": true
},
"chargeResult": {
"charged": true,
"status": "SUCCESS",
"amount": 100,
"fees": 0,
"currency": "NGN",
"transactionReference": "SUB_ENROLL_20_1783539352354",
"authCode": "581032",
"chargeMode": "DIRECT_CHARGE",
"message": "Approved"
}
}
}Create Subscription
This endpoint creates a new subscription for a customer, enrolls the customer’s card, and initiates the first payment where applicable.
Important Notes
cardDetailsis mandatory when creating a subscription.- If no trial period is configured, the first charge is attempted immediately after the card is enrolled.
- If a trial period is configured, the subscription is created with a status of TRIALING. The card is enrolled immediately, but the first charge is deferred until the trial period ends.
- When additional customer authentication is required, the subscription is created with a status of REQUIRES_ACTION, and the response includes the 3D Secure challenge details.
- Creating another active subscription using the same
customerEmailreturns a 409 Conflict response. - Before the first successful payment, the subscription remains in the INCOMPLETE state.
- The card service determines the charge mode (DIRECT_CHARGE, TOKENIZATION, or AGREEMENT_BASED) during card enrollment and returns it in the response. The subscription service stores this value for future recurring billing.
curl --request POST \
--url https://api.payaza.africa/live/subscription/api/v1/subscriptions \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"customerEmail": "johndoe@gmail.com",
"planCode": "PLN_906FE4B",
"cardDetails": {
"cardNumber": "554656xxxxxx742",
"expiryMonth": "01",
"expiryYear": "02",
"securityCode": "123",
"cardHolderName": "John Doe",
"present": true
}
}
'import requests
url = "https://api.payaza.africa/live/subscription/api/v1/subscriptions"
payload = {
"customerEmail": "johndoe@gmail.com",
"planCode": "PLN_906FE4B",
"cardDetails": {
"cardNumber": "554656xxxxxx742",
"expiryMonth": "01",
"expiryYear": "02",
"securityCode": "123",
"cardHolderName": "John Doe",
"present": True
}
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
customerEmail: 'johndoe@gmail.com',
planCode: 'PLN_906FE4B',
cardDetails: {
cardNumber: '554656xxxxxx742',
expiryMonth: '01',
expiryYear: '02',
securityCode: '123',
cardHolderName: 'John Doe',
present: true
}
})
};
fetch('https://api.payaza.africa/live/subscription/api/v1/subscriptions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.payaza.africa/live/subscription/api/v1/subscriptions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'customerEmail' => 'johndoe@gmail.com',
'planCode' => 'PLN_906FE4B',
'cardDetails' => [
'cardNumber' => '554656xxxxxx742',
'expiryMonth' => '01',
'expiryYear' => '02',
'securityCode' => '123',
'cardHolderName' => 'John Doe',
'present' => true
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.payaza.africa/live/subscription/api/v1/subscriptions"
payload := strings.NewReader("{\n \"customerEmail\": \"johndoe@gmail.com\",\n \"planCode\": \"PLN_906FE4B\",\n \"cardDetails\": {\n \"cardNumber\": \"554656xxxxxx742\",\n \"expiryMonth\": \"01\",\n \"expiryYear\": \"02\",\n \"securityCode\": \"123\",\n \"cardHolderName\": \"John Doe\",\n \"present\": true\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.payaza.africa/live/subscription/api/v1/subscriptions")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"customerEmail\": \"johndoe@gmail.com\",\n \"planCode\": \"PLN_906FE4B\",\n \"cardDetails\": {\n \"cardNumber\": \"554656xxxxxx742\",\n \"expiryMonth\": \"01\",\n \"expiryYear\": \"02\",\n \"securityCode\": \"123\",\n \"cardHolderName\": \"John Doe\",\n \"present\": true\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.payaza.africa/live/subscription/api/v1/subscriptions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customerEmail\": \"johndoe@gmail.com\",\n \"planCode\": \"PLN_906FE4B\",\n \"cardDetails\": {\n \"cardNumber\": \"554656xxxxxx742\",\n \"expiryMonth\": \"01\",\n \"expiryYear\": \"02\",\n \"securityCode\": \"123\",\n \"cardHolderName\": \"John Doe\",\n \"present\": true\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Subscription created",
"data": {
"subscription": {
"id": 20,
"customerId": "null",
"customerEmail": "johndoe@gmail.com",
"firstName": null,
"lastName": null,
"customerAuthorizedAt": null,
"status": "ACTIVE",
"currentPeriodStart": "2026-07-08T19:35:52.348327",
"currentPeriodEnd": "2026-08-08T19:35:55.569925",
"nextChargeDate": "2026-08-08T19:35:55.569925",
"trialEndDate": null,
"pauseResumesAt": null,
"cancelAt": null,
"pausedAt": null,
"cancelledAt": null,
"cancellationReason": null,
"cardExpiryAlertSent": false,
"connectionMode": "Live",
"enrollmentReference": "SUBREF_BFE417ABF6FF49A985",
"enrollmentTxnReference": "SUB_ENROLL_20_1783539352354",
"chargeMode": "DIRECT_CHARGE",
"metadata": null,
"createdAt": "2026-07-08T19:35:52.34833",
"updatedAt": "2026-07-08T19:35:55.573662",
"customerBearsFee": false,
"enrollConfirmed": true
},
"chargeResult": {
"charged": true,
"status": "SUCCESS",
"amount": 100,
"fees": 0,
"currency": "NGN",
"transactionReference": "SUB_ENROLL_20_1783539352354",
"authCode": "581032",
"chargeMode": "DIRECT_CHARGE",
"message": "Approved"
}
}
}Authorizations
Payaza {{Public API Key in Base 64}}
Body
The customer's email address. Used to identify the customer's subscription. An email address can only have one active subscription per plan.
"johndoe@gmail.com"
The unique plan code generated when the subscription plan was created. If omitted, a plan is automatically created from the request.
"PLN_906FE4B"
The card information used to enroll the customer for recurring billing.
Show child attributes
Show child attributes
Response
Subscription Created
Indicates if the request was successful.
true
Descriptive message regarding the subscription creation status.
"Subscription created"
The payload containing the combined results of the subscription enrollment and initialization charge.
Show child attributes
Show child attributes