Initialize Transaction
Overview
The Initialise Transaction endpoint is the core operation for creating payment transactions. It accepts payment details, customer information, and optional settlement configurations to generate a transaction reference that can be used to process payments through various channels.
Endpoint Details
Endpoint: POST /api/v1/transactions/in/initialize
Purpose: Creates a new transaction for a selected payment item with specified amount and customer details
AuthorisationAuthentication: Requires Bearer token (merchant_secret_key) in Authorization header
Code Snippets
- JavaScript
- TypeScript
- Java
- Python
- C#
const url = "https://ags.payislands.com/api/v1/transactions/in/initialize";
const payload = {
callback_url: "https://example.com/webhooks/payislands",
payment_item_id: "3",
transaction_reference: "your_reference",
channel: "card",
amount: "1000",
customer_info: {
email: "test@gmail.com",
phone_number: "08011112222",
first_name: "John",
last_name: "Doe",
},
};
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.MERCHANT_SECRET_KEY}`,
},
body: JSON.stringify(payload),
});
const json = await res.json();
console.log(json);
type InitializePayload = {
callback_url: string;
payment_item_id: string;
transaction_reference: string;
channel: "bank" | "card" | "bank-transfer";
amount: string;
customer_info: {
email: string;
phone_number: string;
first_name: string;
last_name: string;
};
};
const url = "https://ags.payislands.com/api/v1/transactions/in/initialize";
const payload: InitializePayload = {
callback_url: "https://example.com/webhooks/payislands",
payment_item_id: "3",
transaction_reference: "your_reference",
channel: "card",
amount: "1000",
customer_info: {
email: "test@gmail.com",
phone_number: "08011112222",
first_name: "John",
last_name: "Doe",
},
};
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.MERCHANT_SECRET_KEY as string}`,
},
body: JSON.stringify(payload),
});
const json = (await res.json()) as unknown;
console.log(json);
import okhttp3.*;
import java.io.IOException;
public class InitializeTransaction {
public static void main(String[] args) throws IOException {
String url = "https://ags.payislands.com/api/v1/transactions/in/initialize";
String merchantSecretKey = System.getenv("MERCHANT_SECRET_KEY");
OkHttpClient client = new OkHttpClient();
String jsonBody = """
{
"callback_url": "https://example.com/webhooks/payislands",
"payment_item_id": "3",
"transaction_reference": "your_reference",
"channel": "card",
"amount": "1000",
"customer_info": {
"email": "test@gmail.com",
"phone_number": "08011112222",
"first_name": "John",
"last_name": "Doe"
}
}
""";
RequestBody body = RequestBody.create(
jsonBody, MediaType.parse("application/json")
);
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("Authorization", "Bearer " + merchantSecretKey)
.addHeader("Content-Type", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
}
import os
import requests
url = "https://ags.payislands.com/api/v1/transactions/in/initialize"
payload = {
"callback_url": "https://example.com/webhooks/payislands",
"payment_item_id": "3",
"transaction_reference": "your_reference",
"channel": "card",
"amount": "1000",
"customer_info": {
"email": "test@gmail.com",
"phone_number": "08011112222",
"first_name": "John",
"last_name": "Doe"
}
}
headers = {
"Authorization": f"Bearer {os.environ['MERCHANT_SECRET_KEY']}",
"Content-Type": "application/json",
}
resp = requests.post(url, json=payload, headers=headers, timeout=30)
print(resp.status_code, resp.text)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
var url = "https://ags.payislands.com/api/v1/transactions/in/initialize";
var merchantSecretKey = Environment.GetEnvironmentVariable("MERCHANT_SECRET_KEY");
var payload = new {
callback_url = "https://example.com/webhooks/payislands",
payment_item_id = "3",
transaction_reference = "your_reference",
channel = "card",
amount = "1000",
customer_info = new {
email = "test@gmail.com",
phone_number = "08011112222",
first_name = "John",
last_name = "Doe"
}
};
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", merchantSecretKey);
var content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var resp = await http.PostAsync(url, content);
var body = await resp.Content.ReadAsStringAsync();
Console.WriteLine(body);
Request Body Structure
Required Fields
{
"callback_url": "string",
"payment_item_id": "string",
"transaction_reference":"your_reference",
"channel": "string",
"amount": "string",
"customer_info": {
"email": "string",
"phone_number": "string",
"first_name": "string",
"last_name": "string"
}
}
Optional Fields
{
"subaccounts": [
{
"account_code": "string",
"amount": integer
}
]
}
Field Descriptions
Request Fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
callback_url | string (URL) | Yes | Public HTTPS endpoint to receive transaction updates. Must accept POST requests. | https://example.com/webhooks/payislands |
payment_item_id | string (numeric) | Yes | Payment item ID (must exist and be active). | "3" |
transaction_reference | string | Yes | Your internal reference for reconciliation (returned back as client_reference). | "your_reference" |
channel | string | Yes | Payment channel to use: bank, card, bank-transfer. | "card" |
amount | string | Yes | Amount in smallest unit (kobo). Must match the payment item amount for fixed items. For variable items, set the payment item amount to 0 when creating it. | "1000" |
customer_info | object | Yes | Customer details (see table below). | {...} |
subaccounts | array | No | Optional split override (see table below). | [{...}] |
customer_info Fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
customer_info.email | string | Yes | Customer email address. | test@gmail.com |
customer_info.phone_number | string | Yes | Customer phone number. | 08011112222 |
customer_info.first_name | string | Yes | Customer first name. | John |
customer_info.last_name | string | Yes | Customer last name. | Doe |
subaccounts[] Fields (Optional)
| Field | Type | Required | Description |
|---|---|---|---|
subaccounts[].account_code | string | Yes (if provided) | Settlement account code. |
subaccounts[].amount | integer | Yes (if provided) | Amount to settle to this account. The sum of all subaccounts[].amount should equal the transaction amount. |
Response Structure
Success Response (200 OK)
{
"status": true,
"message": "transaction generated successfully",
"data": {
"payment_status": "pending",
"authorization_url": "https://checkout.payislands.com/?reference=PISL2510010000000093",
"amount": "100.00",
"amount_to_be_paid": 101.7,
"transaction_fee": "1.70",
"reference": "PISL2510010000000093",
"client_reference": "your_reference"
},
"statusCode": 200
}
Response Fields
| Field | Type | Description |
|---|---|---|
data.payment_status | string | Current status (usually pending immediately after initialization). |
data.authorization_url | string | null | Checkout URL to redirect the customer (typically present for card). |
data.amount | string | Base amount for the transaction. |
data.amount_to_be_paid | number | string | Total amount expected (may include fees). |
data.transaction_fee | string | Processing fee (if applicable). |
data.reference | string | Payislands transaction reference. Store this for verification, webhooks, and support. |
data.client_reference | string | Your transaction_reference echoed back. |
Failure Response (400 Bad Request)
{
"status": false,
"message": "Payment amount does not match",
"data": null,
"statusCode": 400
}
Common Error Scenarios
| Scenario | Typical status | Error / message | Cause | Fix |
|---|---|---|---|---|
| Amount mismatch | 400 | "Payment amount does not match" | Submitted amount doesn’t match the payment item’s configured amount (for fixed items). | Fetch the payment item details and submit the exact amount. For variable items, set the payment item amount to 0 when creating it. |
| Invalid payment item | 400 | Payment item not found | payment_item_id doesn’t exist or is inactive. | Call “Get Payment Items” and use a valid active ID. |
| Authentication failure | 403 | "Forbidden resource" | Missing/invalid Authorization: Bearer <merchant_secret_key>. | Confirm you are using the correct key (Test vs Live) and sending the header. |
| Invalid customer info | 400 | Validation error | Missing or malformed customer_info fields. | Ensure all required fields exist and formats are valid (email, phone, name). |
| Subaccounts issues | 400 | Validation error | Invalid subaccounts[].account_code or the split amounts don’t add up. | Verify each account_code and ensure the sum of subaccounts[].amount equals the transaction amount. |
Implementation Flow
1. Pre-Transaction Steps
1. Fetch payment item details (GET /payment-item/{id})
2. Validate the amount matches the payment item configuration
3. Collect customer information
4. Prepare callback URL endpoint
2. Transaction Initialisation
1. Construct the request body with all required fields
2. Send POST request with Bearer token
3. Handle response (success or error)
4. Store transaction reference
3. Post-Initialisation
1. If authorization_url is provided:
- Redirect the customer to the payment page
- Wait for webhook callback
2. If no authorization_url:
- Provide payment instructions (for bank transfers)
- Monitor transaction status via webhook or polling
Best Practices
Amount Handling
- Always retrieve and verify the payment item amount before initialisation
- For variable-amount items, implement amount validation on your end
- Store amounts as strings to avoid floating-point precision issues
- Never hardcode amounts - always fetch from the payment items endpoint
Customer Data
- Validate email format before submission
- Normalise phone numbers (remove spaces, special characters)
- Implement input validation for names (no special characters)
- Consider data privacy regulations when storing customer information
Reference Management
- Store transaction references in your database immediately
- Use references as primary keys for transaction tracking
- Include references in all customer communications
- Implement reference-based transaction lookup functionality
Webhook Configuration
- Use HTTPS endpoints for callback_url
- Implement webhook signature verification (if available)
- Handle duplicate webhook deliveries (idempotency)
- Set up retry logic for failed webhook processing
- Log all webhook payloads for debugging
Error Handling
- Implement retry logic with exponential backoff for network errors
- Log full error responses for debugging
- Have fallback mechanisms for transaction verification
Security Considerations
- Never expose merchant_secret_key in client-side code
- Use HTTPS for all API communications
Subaccount
- Only use subaccounts when custom splits are required
- Verify account codes before use
- Ensure split amounts sum to the transaction amount exactly
Channel Selection
- Verify channel availability for specific payment items
- Provide appropriate user experience per channel:
- Card: Immediate redirect to authorization_url
- Bank Transfer: Display account details and expiry time
- Bank
- Handle channel-specific error messages appropriately