IDs, Reference IDs, and Idempotency
Understanding how NextAPI handles identification and ensures data consistency across your payment operations.
ID Types in NextAPI
System-Generated IDs
NextAPI generates unique IDs for all major entities:
// Payout ID
"payout_1234567890abcdef"
// Wallet ID
"wallet_abcdef1234567890"
// Payment Link ID
"plink_1234abcdef567890"
// Transaction ID
"txn_5678901234abcdef"
// Event ID
"evt_9012345678abcdef"
Reference IDs
Client-provided identifiers for your tracking:
// Your reference
{
"reference_id": "your-order-12345",
"metadata": {
"invoice_number": "INV-2024-001",
"customer_id": "cust-789"
}
}
ID Formats and Validation
Format Structure
- Prefix: Entity type (payout_, wallet_, etc.)
- Length: 24-32 characters total
- Charset: Hexadecimal (0-9, a-f)
- Uniqueness: Globally unique across NextAPI
Validation Patterns
// Payout ID validation
const payoutIdPattern = /^payout_[a-f0-9]{16,24}$/;
// Wallet ID validation
const walletIdPattern = /^wallet_[a-f0-9]{16,24}$/;
// Reference ID validation
const referenceIdPattern = /^[a-zA-Z0-9_-]{1,100}$/;
Idempotency
What is Idempotency?
Idempotency ensures that making the same request multiple times produces the same result as making it once. This prevents duplicate operations when network issues cause retries.
Idempotency Keys
Include an idempotency key in your requests:
const response = await fetch('https://api.nextapi.com/v1/payouts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'Idempotency-Key': 'unique-key-for-this-operation'
},
body: JSON.stringify({
amount: 10000,
currency: 'PHP',
recipient: { type: 'wallet', id: 'wallet_123' }
})
});
Key Requirements
- Uniqueness: Must be unique per operation
- Format: String, up to 255 characters
- Scope: Per API endpoint and method
- Duration: Keys expire after 24 hours
Generating Idempotency Keys
// Using UUID
import { v4 as uuidv4 } from 'uuid';
const idempotencyKey = uuidv4();
// Using timestamp and random
const idempotencyKey = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
// Using business identifiers
const idempotencyKey = `order-${orderId}-${timestamp}`;
Reference ID Best Practices
Choosing Reference IDs
- Business Meaning: Use meaningful identifiers
- Uniqueness: Ensure uniqueness within your scope
- Consistency: Follow consistent naming patterns
- Length: Keep under 100 characters
- Characters: Use alphanumeric, hyphens, underscores
Examples
// Good examples
"ORDER-2024-001"
"CUST-789-PAYMENT-001"
"INV-20240115-001"
"PAYROLL-JAN-2024-EMP-123"
// Bad examples
"payment" // Too generic
"a very long reference id that exceeds reasonable limits" // Too long
"payment@#$%" // Invalid characters
Error Handling
Duplicate Reference IDs
// Response when reference ID already exists
{
"error": {
"code": "DUPLICATE_REFERENCE",
"message": "Reference ID already exists",
"existing_id": "payout_123",
"reference_id": "ORDER-2024-001"
}
}
Idempotency Conflicts
// Response when idempotency key was used with different parameters
{
"error": {
"code": "IDEMPOTENCY_KEY_CONFLICT",
"message": "Idempotency key was used with different parameters",
"idempotency_key": "key-123",
"existing_request_id": "req_456"
}
}
Tracking and Reconciliation
Storing Mappings
Maintain mappings between your IDs and NextAPI IDs:
// Database schema example
CREATE TABLE payout_mappings (
id SERIAL PRIMARY KEY,
your_reference_id VARCHAR(100) UNIQUE NOT NULL,
nextapi_payout_id VARCHAR(50) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
Reconciliation Process
async function reconcilePayouts() {
// Get your recent orders
const yourOrders = await getYourRecentOrders();
for (const order of yourOrders) {
// Find corresponding payout
const payout = await findPayoutByReference(order.reference_id);
if (!payout) {
// Handle missing payout
console.log(`Missing payout for order: ${order.reference_id}`);
} else if (payout.status !== 'completed') {
// Handle incomplete payout
console.log(`Incomplete payout: ${payout.id}`);
}
}
}
API Usage
Query by Reference ID
GET /v1/payouts?reference_id=ORDER-2024-001
Query by Multiple References
GET /v1/payouts?reference_id[]=ORDER-2024-001&reference_id[]=ORDER-2024-002
Include in Requests
POST /v1/payouts
{
"amount": 10000,
"currency": "PHP",
"reference_id": "ORDER-2024-001",
"metadata": {
"invoice_number": "INV-2024-001"
}
}
Best Practices
- Always use idempotency keys for POST/PUT operations
- Store reference ID mappings in your database
- Implement reconciliation processes
- Use meaningful reference IDs for business tracking
- Handle duplicate errors gracefully
- Log ID mappings for debugging
- Validate ID formats before using
Related Concepts
- [The Lifecycle of a Payout](./the-lifecycle-of-a-payout
- [Understanding Webhooks](./understanding-webhooks
- [Security & Compliance](./security-compliance