GraphQL API Reference
The iNPAY GraphQL API provides a flexible and efficient way to interact with our payment services. GraphQL allows you to request exactly the data you need in a single request.
🔗 Endpoint
- Production:
https://api.inpaycheckout.com/graphql - Development:
https://sandbox-api.inpaycheckout.com/graphql
🔑 Authentication
Include your secret key in the Authorization header:
Authorization: Bearer sk_live_your_secret_key_here
Content-Type: application/json
🚀 Basic Usage
Making Requests
curl -X POST https://api.inpaycheckout.com/graphql \
-H "Authorization: Bearer sk_live_your_secret_key" \
-H "Content-Type: application/json" \
-d '{
"query": "query { healthCheck { success message timestamp version } }"
}'
📋 Mutations
Create Dynamic PayID
mutation CreateDynamicPayId($input: CreateDynamicPayIdInput!) {
createDynamicPayId(input: $input) {
success
message
data {
payId
name
reference
expiresAt
status
type
}
}
}
Variables:
{
"input": {
"reference": "unique-ref-123",
"metadata": {
"orderId": "ORDER-456",
"customerEmail": "customer@example.com"
}
}
}
Create Static PayID
mutation CreateStaticPayId($input: CreateStaticPayIdInput!) {
createStaticPayId(input: $input) {
success
message
data {
payId
name
reference
status
type
}
}
}
Variables:
{
"input": {
"name": "My Custom PayID",
"reference": "unique-ref-456",
"metadata": {
"businessUnit": "sales",
"region": "lagos"
}
}
}
Create Virtual Account
mutation CreateVirtualAccount($input: CreateVirtualAccountInput!) {
createVirtualAccount(input: $input) {
success
message
data {
accountNumber
accountName
bankName
reference
amount
currency
expiresAt
validityTime
amountValidation
}
}
}
Variables:
{
"input": {
"amount": 50000,
"name": "Custom Account Name",
"reference": "unique-ref-789",
"validityTime": 1440,
"amountValidation": "A0",
"metadata": {
"productId": "PROD-123",
"campaignId": "CAMP-456"
}
}
}
Verify Transaction
mutation VerifyTransaction($input: VerifyTransactionInput!) {
verifyTransaction(input: $input) {
success
message
data {
reference
type
payId
accountNumber
status
verified
customerEmail
customerName
amount
createdAt
updatedAt
}
}
}
Variables:
{
"input": {
"reference": "unique-ref-123"
}
}
Response (Verified - Completed):
{
"success": true,
"message": "Transaction verified successfully",
"data": {
"reference": "unique-ref-123",
"type": "virtual_account",
"accountNumber": "1036262911",
"status": "completed",
"verified": true,
"customerEmail": "customer@example.com",
"customerName": "John Doe",
"amount": 100000,
"createdAt": "2025-09-14T10:00:00.000Z",
"updatedAt": "2025-09-14T10:15:00.000Z"
}
}
Response (Not Verified - Pending):
{
"success": true,
"message": "Payment verification completed",
"data": {
"reference": "unique-ref-123",
"type": "virtual_account",
"accountNumber": "1036262911",
"status": "pending",
"verified": false,
"customerEmail": "customer@example.com",
"customerName": "John Doe",
"amount": 100000,
"createdAt": "2025-09-14T10:00:00.000Z",
"updatedAt": "2025-09-14T10:00:00.000Z"
}
}
Note: The amount field behavior:
- When
statusispending: Returns the expected amount (in kobo) that was specified when creating the virtual account/PayID - When
statusiscompleted: Returns the actual amount received (in kobo) from the transaction record
This ensures:
- Backward compatibility:
amountis always a number, nevernull - Merchants see the expected amount while waiting for payment
- Once payment is received, merchants see the actual amount (which may differ if user sent less than expected)
- The
statusfield clearly indicates whether payment is pending or completed
Verify PayID
mutation VerifyPayId($input: VerifyPayIdInput!) {
verifyPayId(input: $input) {
success
message
data {
payId
accountName
isVirtualPayId
isActive
expiresAt
type
}
}
}
Variables:
{
"input": {
"payId": "merchant123.dpid"
}
}
PayID-to-PayID Transfer
mutation TransferPayId($input: PayIdTransferInput!) {
transferPayId(input: $input) {
success
message
data {
transactionId
reference
fromPayId
toPayId
amount
narration
status
completedAt
destinationAccountName
}
}
}
Variables:
{
"input": {
"fromPayId": "mywallet123.wallet",
"toPayId": "customer456.dpid",
"amount": 5000,
"narration": "Payment for order #12345",
"reference": "TXN-789"
}
}
Verify External Account
mutation VerifyExternalAccount($input: VerifyExternalAccountInput!) {
verifyExternalAccount(input: $input) {
success
message
data {
accountNumber
accountName
bankCode
bankName
bankLogo
verified
}
}
}
Variables:
{
"input": {
"accountNumber": "1234567890",
"bankCode": "058"
}
}
External Bank Transfer
mutation TransferExternal($input: ExternalTransferInput!) {
transferExternal(input: $input) {
success
message
data {
transactionId
reference
fromPayId
toAccountNumber
toAccountName
bankCode
bankName
amount
narration
status
completedAt
}
}
}
Variables:
{
"input": {
"fromPayId": "mywallet123.wallet",
"accountNumber": "1234567890",
"bankCode": "058",
"amount": 10000,
"narration": "Payment to supplier",
"reference": "PAY-456",
"accountName": "John Doe"
}
}
🔍 Queries
Get Transaction Status
query GetTransactionStatus($input: GetTransactionStatusInput!) {
getTransactionStatus(input: $input) {
success
message
data {
reference
type
payId
accountNumber
status
verified
customerEmail
customerName
amount
createdAt
updatedAt
}
}
}
Variables:
{
"input": {
"reference": "unique-ref-123"
}
}
Response (Completed Payment):
{
"success": true,
"message": "Transaction status retrieved successfully",
"data": {
"reference": "unique-ref-123",
"type": "virtual_payid",
"payId": "mydyn456.dpid",
"status": "completed",
"verified": true,
"customerEmail": "customer@example.com",
"customerName": "Customer",
"amount": 100000,
"createdAt": "2025-09-14T10:00:00.000Z",
"updatedAt": "2025-09-14T10:15:00.000Z"
}
}
Response (Pending Payment):
{
"success": true,
"message": "Transaction status retrieved successfully",
"data": {
"reference": "unique-ref-123",
"type": "virtual_account",
"accountNumber": "1036262911",
"status": "pending",
"verified": false,
"customerEmail": "customer@example.com",
"customerName": "Customer",
"amount": 100000,
"createdAt": "2025-09-14T10:00:00.000Z",
"updatedAt": "2025-09-14T10:00:00.000Z"
}
}
Note: The amount field behavior:
- When
statusispending: Returns the expected amount (in kobo) that was specified when creating the virtual account/PayID - When
statusiscompleted: Returns the actual amount received (in kobo) from the transaction record
This ensures:
- Backward compatibility:
amountis always a number, nevernull - Merchants see the expected amount while waiting for payment
- Once payment is received, merchants see the actual amount (which may differ if user sent less than expected)
- The
statusfield clearly indicates whether payment is pending or completed
Health Check
query HealthCheck {
healthCheck {
success
message
timestamp
version
}
}
Get Bank List
query GetBankList {
getBankList {
success
message
data {
banks {
bankCode
bankName
logoUrl
}
total
}
}
}
💻 Code Examples
JavaScript/Node.js
const axios = require('axios');
class InpayGraphQLClient {
constructor(secretKey, endpoint = 'https://api.inpaycheckout.com/graphql') {
this.secretKey = secretKey;
this.endpoint = endpoint;
this.headers = {
'Authorization': `Bearer ${secretKey}`,
'Content-Type': 'application/json'
};
}
async execute(query, variables = {}) {
try {
const response = await axios.post(this.endpoint, {
query,
variables
}, {
headers: this.headers
});
if (response.data.errors) {
throw new Error(`GraphQL Error: ${response.data.errors[0].message}`);
}
return response.data.data;
} catch (error) {
console.error('GraphQL execution error:', error.message);
throw error;
}
}
// Create Dynamic PayID
async createDynamicPayID(reference, metadata = {}) {
const query = `
mutation CreateDynamicPayId($input: CreateDynamicPayIdInput!) {
createDynamicPayId(input: $input) {
success
message
data {
payId
name
reference
expiresAt
status
type
}
}
}
`;
const variables = {
input: {
reference,
metadata
}
};
return await this.execute(query, variables);
}
// Create Virtual Account
async createVirtualAccount(amount, reference, options = {}) {
const query = `
mutation CreateVirtualAccount($input: CreateVirtualAccountInput!) {
createVirtualAccount(input: $input) {
success
message
data {
accountNumber
accountName
bankName
reference
amount
currency
expiresAt
validityTime
amountValidation
}
}
}
`;
const variables = {
input: {
amount,
reference,
name: options.name,
validityTime: options.validityTime || 1440,
amountValidation: options.amountValidation || 'A1',
metadata: options.metadata || {}
}
};
return await this.execute(query, variables);
}
// Transfer PayID
async transferPayID(fromPayID, toPayID, amount, narration, reference) {
const query = `
mutation TransferPayId($input: PayIdTransferInput!) {
transferPayId(input: $input) {
success
message
data {
transactionId
reference
fromPayId
toPayId
amount
narration
status
completedAt
destinationAccountName
}
}
}
`;
const variables = {
input: {
fromPayId: fromPayID,
toPayId: toPayID,
amount,
narration,
reference
}
};
return await this.execute(query, variables);
}
// Get Bank List
async getBankList() {
const query = `
query GetBankList {
getBankList {
success
message
data {
banks {
bankCode
bankName
logoUrl
}
total
}
}
}
`;
return await this.execute(query);
}
// Health Check
async healthCheck() {
const query = `
query HealthCheck {
healthCheck {
success
message
timestamp
version
}
}
`;
return await this.execute(query);
}
}
// Usage
const client = new InpayGraphQLClient(process.env.INPAY_SECRET_KEY);
// Create Dynamic PayID
const payID = await client.createDynamicPayID('order-123', {
orderId: 'ORDER-456',
customerEmail: 'customer@example.com'
});
console.log('PayID created:', payID.createDynamicPayId.data.payId);
// Create Virtual Account
const virtualAccount = await client.createVirtualAccount(50000, 'order-456', {
name: 'Order Payment',
validityTime: 1440,
metadata: {
productId: 'PROD-123'
}
});
console.log('Virtual Account created:', virtualAccount.createVirtualAccount.data.accountNumber);
// Transfer PayID
const transfer = await client.transferPayID(
'mywallet123.wallet',
'customer456.dpid',
5000,
'Payment for order #12345',
'TXN-789'
);
console.log('Transfer completed:', transfer.transferPayId.data.transactionId);
// Get Bank List
const bankList = await client.getBankList();
console.log('Supported banks:', bankList.getBankList.data.banks.length);
Python
import requests
import json
class InpayGraphQLClient:
def __init__(self, secret_key, endpoint='https://api.inpaycheckout.com/graphql'):
self.secret_key = secret_key
self.endpoint = endpoint
self.headers = {
'Authorization': f'Bearer {secret_key}',
'Content-Type': 'application/json'
}
def execute(self, query, variables=None):
"""Execute GraphQL query"""
try:
response = requests.post(
self.endpoint,
json={
'query': query,
'variables': variables or {}
},
headers=self.headers
)
data = response.json()
if 'errors' in data:
raise Exception(f"GraphQL Error: {data['errors'][0]['message']}")
return data['data']
except Exception as e:
print(f'GraphQL execution error: {e}')
raise
def create_dynamic_payid(self, reference, metadata=None):
"""Create Dynamic PayID"""
query = """
mutation CreateDynamicPayId($input: CreateDynamicPayIdInput!) {
createDynamicPayId(input: $input) {
success
message
data {
payId
name
reference
expiresAt
status
type
}
}
}
"""
variables = {
'input': {
'reference': reference,
'metadata': metadata or {}
}
}
return self.execute(query, variables)
def create_virtual_account(self, amount, reference, **options):
"""Create Virtual Account"""
query = """
mutation CreateVirtualAccount($input: CreateVirtualAccountInput!) {
createVirtualAccount(input: $input) {
success
message
data {
accountNumber
accountName
bankName
reference
amount
currency
expiresAt
validityTime
amountValidation
}
}
}
"""
variables = {
'input': {
'amount': amount,
'reference': reference,
'name': options.get('name'),
'validityTime': options.get('validityTime', 1440),
'amountValidation': options.get('amountValidation', 'A1'),
'metadata': options.get('metadata', {})
}
}
return self.execute(query, variables)
def transfer_payid(self, from_payid, to_payid, amount, narration, reference):
"""Transfer PayID"""
query = """
mutation TransferPayId($input: PayIdTransferInput!) {
transferPayId(input: $input) {
success
message
data {
transactionId
reference
fromPayId
toPayId
amount
narration
status
completedAt
destinationAccountName
}
}
}
"""
variables = {
'input': {
'fromPayId': from_payid,
'toPayId': to_payid,
'amount': amount,
'narration': narration,
'reference': reference
}
}
return self.execute(query, variables)
def get_bank_list(self):
"""Get Bank List"""
query = """
query GetBankList {
getBankList {
success
message
data {
banks {
bankCode
bankName
logoUrl
}
total
}
}
}
"""
return self.execute(query)
def health_check(self):
"""Health Check"""
query = """
query HealthCheck {
healthCheck {
success
message
timestamp
version
}
}
"""
return self.execute(query)
# Usage
client = InpayGraphQLClient(os.getenv('INPAY_SECRET_KEY'))
# Create Dynamic PayID
payid = client.create_dynamic_payid('order-123', {
'orderId': 'ORDER-456',
'customerEmail': 'customer@example.com'
})
print(f"PayID created: {payid['createDynamicPayId']['data']['payId']}")
# Create Virtual Account
virtual_account = client.create_virtual_account(
50000,
'order-456',
name='Order Payment',
validityTime=1440,
metadata={'productId': 'PROD-123'}
)
print(f"Virtual Account created: {virtual_account['createVirtualAccount']['data']['accountNumber']}")
# Transfer PayID
transfer = client.transfer_payid(
'mywallet123.wallet',
'customer456.dpid',
5000,
'Payment for order #12345',
'TXN-789'
)
print(f"Transfer completed: {transfer['transferPayId']['data']['transactionId']}")
# Get Bank List
bank_list = client.get_bank_list()
print(f"Supported banks: {len(bank_list['getBankList']['data']['banks'])}")
🔍 GraphQL vs REST
| Feature | GraphQL | REST |
|---|---|---|
| Data Fetching | Request only needed fields | Get complete resources |
| Multiple Operations | Single request for multiple operations | Multiple requests required |
| Type Safety | Strong typing with schema | No built-in typing |
| Caching | More complex caching | Standard HTTP caching |
| Learning Curve | Steeper learning curve | Familiar HTTP concepts |
🚨 Error Handling
GraphQL errors are returned in the errors field:
{
"data": null,
"errors": [
{
"message": "Invalid secret key",
"locations": [{"line": 2, "column": 3}],
"path": ["createDynamicPayId"]
}
]
}
💡 Best Practices
✅ Do's
- Use specific field selection - Request only the fields you need
- Handle errors gracefully - Check for errors in the response
- Use variables - Pass data through variables, not string interpolation
- Implement retry logic - Handle network failures and retries
- Cache responses - Implement appropriate caching strategies
❌ Don'ts
- Don't request all fields - Be specific about what data you need
- Don't ignore errors - Always check and handle GraphQL errors
- Don't use string interpolation - Use variables for dynamic data
- Don't make unnecessary requests - Batch operations when possible
Next Steps:
- REST API Reference - Learn about REST endpoints
- Resources - Addons and integration tools
- Webhooks Guide - Handle real-time notifications