Escrow API

The Escrow API enables secure payment handling with customizable terms and conditions that must be fulfilled before funds are released. This comprehensive guide covers authentication flows, escrow operations, term fulfillment, release, and reverse operations with practical examples.

Table of Contents

Authentication Overview

The Escrow API supports multiple authentication methods depending on the payment method and user type:

Authentication Matrix

Payment Method

Registered Users

Unregistered Users

Merchant Actions

piaxis

OAuth2 Bearer Token

N/A (must be registered)

API Key

piaxis_external

OAuth2 Bearer Token

OTP Verification

API Key + Bearer Token

mtn

OAuth2 Bearer Token

OTP Verification

API Key

airtel

OAuth2 Bearer Token

OTP Verification

API Key

card

OAuth2 Bearer Token

OTP Verification

API Key

Required Headers

For all requests:

Content-Type: application/json
X-Piaxis-Client-ID: your_client_id

API Key Authentication (Merchant):

api-key: YOUR_MERCHANT_API_KEY

OAuth2 Authentication (User):

Authorization: Bearer YOUR_ACCESS_TOKEN

Combined Authentication (piaxis_external):

api-key: YOUR_MERCHANT_API_KEY
Authorization: Bearer YOUR_ACCESS_TOKEN

OTP Verification for Unregistered Users

For unregistered users on external payment methods (mtn, airtel, card), OTP verification is required:

  1. Request OTP:

POST /api/request-otp HTTP/1.1
Host: api.gopiaxis.com
Content-Type: application/json
api-key: YOUR_API_KEY

{
  "phone_number": "+256700000000",
  "email": "[email protected]"
}
  1. Use OTP in escrow creation:

{
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Quick Start Guide

This section provides a step-by-step walkthrough for common escrow scenarios.

Scenario 1: Simple MTN Escrow with Delivery Confirmation

Step 1: Create the escrow

POST /api/escrows/ HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
X-Piaxis-Client-ID: piaxis_bd97ffb5144c49e4
Content-Type: application/json

{
  "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
  "amount": "50000.00",
  "currency_code": "UGX",
  "payment_method": "mtn",
  "description": "Payment for electronics order #12345",
  "terms": [
    {
      "type": "delivery_confirmation",
      "data": {
        "description": "Confirm receipt of electronics order",
        "deadline": "2024-12-14T23:59:59Z"
      }
    }
  ],
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Response:

{
  "escrow_id": "f530533e-3761-4cde-9c9d-88c5be6493bb",
  "status": "pending",
  "amount": "50000.00",
  "currency": "UGX",
  "payment_method": "mtn",
  "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
  "terms": [
    {
      "term_id": "4215567e-6928-4a9d-85d8-c3b1708bdcec",
      "type": "delivery_confirmation",
      "status": "pending",
      "deadline": "2024-12-14T23:59:59Z"
    }
  ],
  "created_at": "2024-12-07T10:30:00Z"
}

Step 2: Buyer confirms delivery (fulfills term)

POST /api/escrows/f530533e-3761-4cde-9c9d-88c5be6493bb/terms/4215567e-6928-4a9d-85d8-c3b1708bdcec/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "delivery_confirmation",
  "data": {
    "confirmation_method": "confirmation",
    "notes": "Package received in good condition"
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Step 3: Release funds automatically or manually

Once all terms are fulfilled, funds can be released automatically or manually triggered:

POST /api/escrows/f530533e-3761-4cde-9c9d-88c5be6493bb/release HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Creating Escrows

The escrow creation endpoint supports various payment methods and term combinations.

POST /api/escrows/

Create a new escrow payment with specified terms and conditions.

Request Headers:
  • api-key – Merchant API key (required)

  • X-Piaxis-Client-ID – Your client ID (required)

  • Authorization – Bearer token (required for piaxis_external, optional for others)

  • Content-Type – application/json

Status Codes:

Payment Method Examples

MTN Money Escrow:

POST /api/escrows/ HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
X-Piaxis-Client-ID: piaxis_bd97ffb5144c49e4
Content-Type: application/json

{
  "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
  "amount": "25000.00",
  "currency_code": "UGX",
  "payment_method": "mtn",
  "description": "Service payment with location verification",
  "terms": [
    {
      "type": "location_verification",
      "data": {
        "latitude": 0.347596,
        "longitude": 32.582520,
        "radius": 100,
        "description": "Verify location at delivery point"
      }
    }
  ],
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456",
    "device_info": {
      "device_id": "unique_device_id",
      "platform": "android",
      "os_version": "11.0"
    }
  }
}

Airtel Money Escrow:

POST /api/escrows/ HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
X-Piaxis-Client-ID: piaxis_bd97ffb5144c49e4
Content-Type: application/json

{
  "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
  "amount": "75000.00",
  "currency_code": "UGX",
  "payment_method": "airtel",
  "description": "Product purchase with meeting delivery",
  "products": [
    {
      "product_id": "7c8b7cbe-4d52-4097-9fb2-858be26f5338",
      "quantity": 1,
      "selected_location": {
        "latitude": 0.3476,
        "longitude": 32.5825
      }
    }
  ],
  "terms": [
    {
      "type": "meeting_delivery",
      "data": {
        "max_distance_km": 0.1,
        "buyer_coordinates": {
          "latitude": 0.3476,
          "longitude": 32.5825
        },
        "description": "Meet at central market for product delivery"
      }
    }
  ],
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Piaxis External Payment:

POST /api/escrows/ HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Authorization: Bearer YOUR_ACCESS_TOKEN
X-Piaxis-Client-ID: piaxis_bd97ffb5144c49e4
Content-Type: application/json

{
  "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
  "amount": "100000.00",
  "currency_code": "UGX",
  "payment_method": "piaxis_external",
  "description": "High-value transaction with multiple terms",
  "terms": [
    {
      "type": "photo_upload",
      "data": {
        "description": "Upload proof of service completion",
        "required_count": 2,
        "accepted_formats": ["jpeg", "png"]
      }
    },
    {
      "type": "delivery_confirmation",
      "data": {
        "description": "Confirm service completion",
        "deadline": "2024-12-20T18:00:00Z"
      }
    }
  ]
}

Card Payment Escrow:

POST /api/escrows/ HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
X-Piaxis-Client-ID: piaxis_bd97ffb5144c49e4
Content-Type: application/json

{
  "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
  "amount": "50000.00",
  "currency_code": "UGX",
  "payment_method": "card",
  "description": "Online purchase with return period",
  "terms": [
    {
      "type": "return_period",
      "data": {
        "return_period_days": 7,
        "start_date": "2024-12-07T00:00:00Z",
        "description": "7-day return window for online purchase"
      }
    }
  ],
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "654321"
  }
}

Term Types and Data Structures

Available Term Types:

  • delivery_confirmation - Simple confirmation from buyer/seller

  • location_verification - GPS location verification

  • meeting_delivery - In-person meeting with location verification

  • photo_upload - Photo evidence upload

  • return_period - Time-based return window

  • custom - Custom merchant-defined terms

Request Body Structure:

{
  "receiver_id": "string (UUID)",
  "amount": "decimal",
  "currency_code": "string (ISO 4217)",
  "payment_method": "piaxis_external|mtn|airtel|card",
  "description": "string (optional)",
  "products": [
    {
      "product_id": "string (UUID)",
      "quantity": "integer",
      "selected_location": {
        "latitude": "float",
        "longitude": "float"
      }
    }
  ],
  "terms": [
    {
      "type": "string",
      "data": "object (varies by term type)"
    }
  ],
  "user_info": {
    "email": "string",
    "phone_number": "string",
    "otp": "string (for unregistered users)",
    "device_info": {
      "device_id": "string",
      "platform": "string",
      "os_version": "string"
    }
  }
}

Term Fulfillment

The universal fulfillment endpoint handles all term types with role-based authentication.

POST /api/escrows/{escrow_id}/terms/{term_id}/fulfill

Fulfill a specific term of an escrow. The system automatically determines the user’s role (buyer/seller) and validates permissions.

Request Headers:
  • api-key – Merchant API key (required)

  • Authorization – Bearer token (optional, for registered users)

  • Content-Type – application/json

Status Codes:

Delivery Confirmation Examples

Buyer Confirmation:

POST /api/escrows/f530533e-3761-4cde-9c9d-88c5be6493bb/terms/4215567e-6928-4a9d-85d8-c3b1708bdcec/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "delivery_confirmation",
  "data": {
    "confirmation_method": "confirmation",
    "notes": "Package received in excellent condition. Very satisfied!",
    "rating": 5
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Seller Confirmation:

POST /api/escrows/f530533e-3761-4cde-9c9d-88c5be6493bb/terms/4215567e-6928-4a9d-85d8-c3b1708bdcec/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "delivery_confirmation",
  "data": {
    "confirmation_method": "confirmation",
    "notes": "Product delivered successfully to customer",
    "delivery_timestamp": "2024-12-07T14:30:00Z"
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256701000000",
    "otp": "654321"
  }
}

Merchant Acting on Behalf of User:

POST /api/escrows/f530533e-3761-4cde-9c9d-88c5be6493bb/terms/4215567e-6928-4a9d-85d8-c3b1708bdcec/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "delivery_confirmation",
  "data": {
    "confirmation_method": "confirmation",
    "notes": "Confirmed delivery on behalf of customer via customer service",
    "merchant_action": true,
    "confirmation_source": "customer_service_call"
  }
}

Location Verification Examples

User Location Verification:

POST /api/escrows/abc123e4-5678-4def-9012-345678901234/terms/def456a7-8901-4bcd-2345-678901234567/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "location_verification",
  "data": {
    "user_latitude": 0.347596,
    "user_longitude": 32.582520,
    "accuracy": 5.2,
    "timestamp": "2024-12-07T10:15:30Z",
    "device_info": {
      "device_id": "user_device_456",
      "platform": "ios",
      "os_version": "15.0"
    }
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "789123"
  }
}

Meeting Delivery Examples

Buyer Meeting Confirmation:

POST /api/escrows/meeting123-4567-4abc-8901-234567890123/terms/meeting456-7890-4def-1234-567890123456/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "meeting_delivery",
  "data": {
    "buyer_latitude": 0.3476,
    "buyer_longitude": 32.5825,
    "meeting_timestamp": "2024-12-07T16:00:00Z",
    "device_info": {
      "device_id": "buyer_device_789",
      "platform": "android",
      "os_version": "12.0"
    }
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "456789"
  }
}

Seller Meeting Confirmation:

POST /api/escrows/meeting123-4567-4abc-8901-234567890123/terms/meeting456-7890-4def-1234-567890123456/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "meeting_delivery",
  "data": {
    "seller_latitude": 0.3476,
    "seller_longitude": 32.5825,
    "meeting_timestamp": "2024-12-07T16:05:00Z",
    "device_info": {
      "device_id": "seller_device_321",
      "platform": "android",
      "os_version": "11.0"
    }
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256701000000",
    "otp": "987654"
  }
}

Photo Upload Examples

Single Photo Upload:

POST /api/escrows/photo123-4567-4abc-8901-234567890123/terms/photo456-7890-4def-1234-567890123456/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "photo_upload",
  "data": {
    "photos": [
      {
        "file_url": "https://storage.gopiaxis.com/uploads/proof-123.jpg",
        "description": "Product delivered and installed",
        "timestamp": "2024-12-07T14:30:00Z"
      }
    ],
    "notes": "Installation completed successfully"
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256702000000",
    "otp": "321654"
  }
}

Multiple Photo Upload:

POST /api/escrows/photo123-4567-4abc-8901-234567890123/terms/photo456-7890-4def-1234-567890123456/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "photo_upload",
  "data": {
    "photos": [
      {
        "file_url": "https://storage.gopiaxis.com/uploads/before-123.jpg",
        "description": "Before installation",
        "timestamp": "2024-12-07T09:00:00Z"
      },
      {
        "file_url": "https://storage.gopiaxis.com/uploads/after-123.jpg",
        "description": "After installation - completed work",
        "timestamp": "2024-12-07T14:30:00Z"
      }
    ],
    "completion_notes": "Full installation with before/after documentation"
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256703000000",
    "otp": "159753"
  }
}

Custom Term Examples

Custom Verification Term:

POST /api/escrows/custom123-4567-4abc-8901-234567890123/terms/custom456-7890-4def-1234-567890123456/fulfill HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "term_type": "custom",
  "data": {
    "verification_code": "CUSTOM-VERIFY-789",
    "completion_data": {
      "task_completed": true,
      "verification_timestamp": "2024-12-07T18:00:00Z",
      "additional_info": "Custom task completed according to specifications"
    }
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256704000000",
    "otp": "753951"
  }
}

Escrow Operations

Once escrows are created and terms are fulfilled, you can perform various operations to manage the escrow lifecycle.

Releasing Escrows

Release funds from an escrow to the recipient once terms are satisfied.

POST /api/escrows/{escrow_id}/release

Release escrowed funds to the receiver.

Request Headers:
  • api-key – Merchant API key (required)

  • Authorization – Bearer token (optional, for registered users)

  • Content-Type – application/json

Status Codes:

Manual Release Example:

POST /api/escrows/43452aa2-28b4-4e8f-a1d2-d47014c9a33a/release HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "reason": "All delivery terms fulfilled successfully",
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Merchant-Authorized Release:

POST /api/escrows/43452aa2-28b4-4e8f-a1d2-d47014c9a33a/release HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "reason": "Customer service confirmed satisfaction via phone",
  "merchant_authorization": true,
  "authorization_reference": "CS-CALL-2024-001234"
}

Successful Release Response:

{
  "escrow_id": "43452aa2-28b4-4e8f-a1d2-d47014c9a33a",
  "status": "released",
  "amount": "50000.00",
  "currency": "UGX",
  "released_at": "2024-12-07T15:30:00Z",
  "release_transaction_id": "txn_987654321",
  "receiver_info": {
    "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
    "amount_received": "49500.00",
    "fees_deducted": "500.00"
  }
}

Reversing Escrows

Reverse an escrow payment back to the sender when terms cannot be fulfilled or disputes arise.

POST /api/escrows/{escrow_id}/reverse

Reverse an escrow payment back to the original sender.

Request Headers:
  • api-key – Merchant API key (required)

  • Authorization – Bearer token (optional, for registered users)

  • Content-Type – application/json

Status Codes:

Buyer-Initiated Reverse:

POST /api/escrows/43452aa2-28b4-4e8f-a1d2-d47014c9a33a/reverse HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "reason": "Product not as described - requesting full refund",
  "reverse_type": "buyer_dissatisfaction",
  "evidence": {
    "description": "Product condition does not match listing",
    "photos": [
      "https://storage.gopiaxis.com/uploads/evidence-001.jpg"
    ]
  },
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256700000000",
    "otp": "123456"
  }
}

Seller-Initiated Reverse:

POST /api/escrows/43452aa2-28b4-4e8f-a1d2-d47014c9a33a/reverse HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "reason": "Unable to fulfill order - item out of stock",
  "reverse_type": "seller_cancellation",
  "refund_processing_fee": false,
  "user_info": {
    "email": "[email protected]",
    "phone_number": "+256701000000",
    "otp": "654321"
  }
}

Merchant-Mediated Reverse:

POST /api/escrows/43452aa2-28b4-4e8f-a1d2-d47014c9a33a/reverse HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY
Content-Type: application/json

{
  "reason": "Dispute resolution - agreed refund after mediation",
  "reverse_type": "dispute_resolution",
  "merchant_mediation": true,
  "resolution_details": {
    "mediator_id": "mediator_123",
    "resolution_date": "2024-12-07T10:00:00Z",
    "agreed_terms": "Full refund minus processing fees"
  }
}

Successful Reverse Response:

{
  "escrow_id": "43452aa2-28b4-4e8f-a1d2-d47014c9a33a",
  "status": "reversed",
  "original_amount": "50000.00",
  "refund_amount": "49000.00",
  "fees_retained": "1000.00",
  "currency": "UGX",
  "reversed_at": "2024-12-07T16:45:00Z",
  "reverse_transaction_id": "rev_123456789",
  "sender_info": {
    "refund_method": "mtn",
    "refund_reference": "MTN-REF-789123"
  }
}

Getting Escrow Status

Retrieve comprehensive status information about an escrow.

GET /api/escrows/{escrow_id}/status

Get detailed status and progress of an escrow including term fulfillment status.

Request Headers:
  • api-key – Merchant API key (required)

Status Codes:

Request Example:

GET /api/escrows/7680cfa9-b0cf-43a7-974b-108b89bd5ebe/status HTTP/1.1
Host: api.gopiaxis.com
api-key: YOUR_API_KEY

Detailed Response Example:

{
  "escrow_id": "7680cfa9-b0cf-43a7-974b-108b89bd5ebe",
  "status": "active",
  "amount": "75000.00",
  "currency": "UGX",
  "payment_method": "airtel",
  "created_at": "2024-12-05T09:30:00Z",
  "expires_at": "2024-12-19T23:59:59Z",
  "description": "Electronics purchase with delivery confirmation",

  "participants": {
    "sender": {
      "type": "unregistered",
      "email": "[email protected]",
      "phone_number": "+256700000000",
      "verified": true
    },
    "receiver": {
      "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
      "type": "registered",
      "business_name": "Tech Solutions Ltd"
    }
  },

  "terms": [
    {
      "term_id": "07a17756-a965-452a-9f0a-48ef55c38131",
      "term_type": "delivery_confirmation",
      "status": "fulfilled",
      "description": "Confirm receipt of electronics",
      "deadline": "2024-12-12T18:00:00Z",
      "fulfilled_at": "2024-12-07T14:30:00Z",
      "fulfilled_by": "buyer",
      "fulfillment_data": {
        "confirmation_method": "confirmation",
        "notes": "Package received in excellent condition",
        "rating": 5
      }
    },
    {
      "term_id": "08b28867-b076-463b-af1b-59fg66d49242",
      "term_type": "location_verification",
      "status": "pending",
      "description": "Verify delivery location",
      "deadline": "2024-12-12T18:00:00Z",
      "required_location": {
        "latitude": 0.347596,
        "longitude": 32.582520,
        "radius": 100
      }
    }
  ],

  "progress": {
    "total_terms": 2,
    "fulfilled_terms": 1,
    "pending_terms": 1,
    "all_terms_met": false,
    "completion_percentage": 50
  },

  "timeline": [
    {
      "timestamp": "2024-12-05T09:30:00Z",
      "event": "escrow_created",
      "description": "Escrow created with 2 terms"
    },
    {
      "timestamp": "2024-12-07T14:30:00Z",
      "event": "term_fulfilled",
      "description": "Delivery confirmation completed by buyer",
      "term_id": "07a17756-a965-452a-9f0a-48ef55c38131"
    }
  ]
}

Error Handling

The Escrow API uses standard HTTP status codes and provides detailed error messages to help developers troubleshoot issues.

HTTP Status Codes

Error Response Format

All error responses follow a consistent format:

{
  "detail": "Human-readable error message",
  "error_code": "SPECIFIC_ERROR_CODE",
  "errors": {
    "field_name": ["Field-specific error message"],
    "another_field": ["Another validation error"]
  },
  "request_id": "req_123456789"
}

Common Error Scenarios

Authentication Errors:

{
  "detail": "Authentication failed",
  "error_code": "INVALID_API_KEY",
  "request_id": "req_auth_001"
}

Validation Errors:

{
  "detail": "Validation failed",
  "error_code": "VALIDATION_ERROR",
  "errors": {
    "amount": ["Amount must be greater than 0"],
    "phone_number": ["Invalid phone number format"],
    "terms": ["At least one term is required"]
  },
  "request_id": "req_val_002"
}

Business Logic Errors:

{
  "detail": "Term already fulfilled",
  "error_code": "TERM_ALREADY_FULFILLED",
  "context": {
    "term_id": "07a17756-a965-452a-9f0a-48ef55c38131",
    "fulfilled_at": "2024-12-07T14:30:00Z",
    "fulfilled_by": "buyer"
  },
  "request_id": "req_biz_003"
}

OTP Verification Errors:

{
  "detail": "OTP verification failed",
  "error_code": "INVALID_OTP",
  "context": {
    "phone_number": "+256700000000",
    "attempts_remaining": 2,
    "expires_at": "2024-12-07T15:45:00Z"
  },
  "request_id": "req_otp_004"
}

Error Handling Best Practices

  1. Always check status codes before processing responses

  2. Log request_id for support and debugging purposes

  3. Handle rate limiting with exponential backoff

  4. Validate data locally before API calls to reduce errors

  5. Implement retry logic for temporary failures (5xx errors)

  6. Store error contexts for debugging and user support

Integration Examples

Complete integration examples showing real-world usage patterns.

Python Integration

Complete Escrow Workflow:

import requests
import time
from typing import Dict, List, Optional

class PiaxisEscrowClient:
    def __init__(self, api_key: str, client_id: str, base_url: str = "https://api.gopiaxis.com"):
        self.api_key = api_key
        self.client_id = client_id
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            'api-key': api_key,
            'X-Piaxis-Client-ID': client_id,
            'Content-Type': 'application/json'
        })

    def request_otp(self, phone_number: str, email: str) -> Dict:
        """Request OTP for unregistered user verification"""
        response = self.session.post(f"{self.base_url}/api/request-otp", json={
            "phone_number": phone_number,
            "email": email
        })
        response.raise_for_status()
        return response.json()

    def create_escrow(self, escrow_data: Dict) -> Dict:
        """Create a new escrow with terms"""
        response = self.session.post(f"{self.base_url}/api/escrows/", json=escrow_data)
        if not response.ok:
            print(f"Error creating escrow: {response.json()}")
            response.raise_for_status()
        return response.json()

    def fulfill_term(self, escrow_id: str, term_id: str, fulfillment_data: Dict) -> Dict:
        """Fulfill a specific escrow term"""
        url = f"{self.base_url}/api/escrows/{escrow_id}/terms/{term_id}/fulfill"
        response = self.session.post(url, json=fulfillment_data)
        if not response.ok:
            print(f"Error fulfilling term: {response.json()}")
            response.raise_for_status()
        return response.json()

    def get_escrow_status(self, escrow_id: str) -> Dict:
        """Get comprehensive escrow status"""
        response = self.session.get(f"{self.base_url}/api/escrows/{escrow_id}/status")
        response.raise_for_status()
        return response.json()

    def release_escrow(self, escrow_id: str, release_data: Dict) -> Dict:
        """Release escrow funds"""
        response = self.session.post(f"{self.base_url}/api/escrows/{escrow_id}/release", json=release_data)
        if not response.ok:
            print(f"Error releasing escrow: {response.json()}")
            response.raise_for_status()
        return response.json()

    def reverse_escrow(self, escrow_id: str, reverse_data: Dict) -> Dict:
        """Reverse escrow payment"""
        response = self.session.post(f"{self.base_url}/api/escrows/{escrow_id}/reverse", json=reverse_data)
        if not response.ok:
            print(f"Error reversing escrow: {response.json()}")
            response.raise_for_status()
        return response.json()

# Usage example
def complete_escrow_workflow():
    client = PiaxisEscrowClient(
        api_key="your_api_key_here",
        client_id="piaxis_your_client_id"
    )

    # Step 1: Request OTP for buyer
    otp_response = client.request_otp(
        phone_number="+256700000000",
        email="[email protected]"
    )
    print("OTP sent to buyer")

    # Step 2: Create escrow (assume buyer enters OTP)
    escrow_data = {
        "receiver_id": "096b723a-45c5-4957-94d7-747835136265",
        "amount": "50000.00",
        "currency_code": "UGX",
        "payment_method": "mtn",
        "description": "Electronics purchase with delivery terms",
        "terms": [
            {
                "type": "delivery_confirmation",
                "data": {
                    "description": "Confirm receipt of electronics",
                    "deadline": "2024-12-14T23:59:59Z"
                }
            }
        ],
        "user_info": {
            "email": "[email protected]",
            "phone_number": "+256700000000",
            "otp": "123456"  # User-provided OTP
        }
    }

    escrow = client.create_escrow(escrow_data)
    escrow_id = escrow["escrow_id"]
    term_id = escrow["terms"][0]["term_id"]
    print(f"Escrow created: {escrow_id}")

    # Step 3: Monitor escrow status
    status = client.get_escrow_status(escrow_id)
    print(f"Escrow status: {status['status']}")

    # Step 4: Fulfill delivery confirmation (buyer confirms)
    fulfillment_data = {
        "term_type": "delivery_confirmation",
        "data": {
            "confirmation_method": "confirmation",
            "notes": "Package received in perfect condition",
            "rating": 5
        },
        "user_info": {
            "email": "[email protected]",
            "phone_number": "+256700000000",
            "otp": "789123"  # New OTP for fulfillment
        }
    }

    fulfillment = client.fulfill_term(escrow_id, term_id, fulfillment_data)
    print("Term fulfilled successfully")

    # Step 5: Release funds
    release_data = {
        "reason": "All terms satisfied - delivery confirmed",
        "user_info": {
            "email": "[email protected]",
            "phone_number": "+256700000000",
            "otp": "456789"  # New OTP for release
        }
    }

    release = client.release_escrow(escrow_id, release_data)
    print(f"Escrow released: {release['release_transaction_id']}")

if __name__ == "__main__":
    complete_escrow_workflow()

Node.js Integration

Complete Escrow Management:

const axios = require('axios');

class PiaxisEscrowClient {
    constructor(apiKey, clientId, baseUrl = 'https://api.gopiaxis.com') {
        this.apiKey = apiKey;
        this.clientId = clientId;
        this.baseUrl = baseUrl;

        this.client = axios.create({
            baseURL: baseUrl,
            headers: {
                'api-key': apiKey,
                'X-Piaxis-Client-ID': clientId,
                'Content-Type': 'application/json'
            }
        });

        // Add response interceptor for error handling
        this.client.interceptors.response.use(
            response => response,
            error => {
                console.error('API Error:', error.response?.data || error.message);
                throw error;
            }
        );
    }

    async requestOtp(phoneNumber, email) {
        const response = await this.client.post('/api/request-otp', {
            phone_number: phoneNumber,
            email: email
        });
        return response.data;
    }

    async createEscrow(escrowData) {
        const response = await this.client.post('/api/escrows/', escrowData);
        return response.data;
    }

    async fulfillTerm(escrowId, termId, fulfillmentData) {
        const response = await this.client.post(
            `/api/escrows/${escrowId}/terms/${termId}/fulfill`,
            fulfillmentData
        );
        return response.data;
    }

    async getEscrowStatus(escrowId) {
        const response = await this.client.get(`/api/escrows/${escrowId}/status`);
        return response.data;
    }

    async releaseEscrow(escrowId, releaseData) {
        const response = await this.client.post(
            `/api/escrows/${escrowId}/release`,
            releaseData
        );
        return response.data;
    }

    async reverseEscrow(escrowId, reverseData) {
        const response = await this.client.post(
            `/api/escrows/${escrowId}/reverse`,
            reverseData
        );
        return response.data;
    }

    // Utility method to poll escrow status until completion
    async waitForTermFulfillment(escrowId, maxWaitTime = 300000) {
        const startTime = Date.now();

        while (Date.now() - startTime < maxWaitTime) {
            const status = await this.getEscrowStatus(escrowId);

            if (status.progress.all_terms_met) {
                return status;
            }

            // Wait 10 seconds before next check
            await new Promise(resolve => setTimeout(resolve, 10000));
        }

        throw new Error('Timeout waiting for term fulfillment');
    }
}

// Usage example with error handling
async function handleEscrowWorkflow() {
    const client = new PiaxisEscrowClient(
        'your_api_key_here',
        'piaxis_your_client_id'
    );

    try {
        // Create escrow with location verification term
        const escrowData = {
            receiver_id: "096b723a-45c5-4957-94d7-747835136265",
            amount: "75000.00",
            currency_code: "UGX",
            payment_method: "airtel",
            description: "Service delivery with location verification",
            terms: [
                {
                    type: "location_verification",
                    data: {
                        latitude: 0.347596,
                        longitude: 32.582520,
                        radius: 100,
                        description: "Verify service location"
                    }
                }
            ],
            user_info: {
                email: "[email protected]",
                phone_number: "+256700000000",
                otp: "123456"
            }
        };

        const escrow = await client.createEscrow(escrowData);
        console.log('Escrow created:', escrow.escrow_id);

        // Monitor for fulfillment
        console.log('Waiting for term fulfillment...');
        const completedStatus = await client.waitForTermFulfillment(escrow.escrow_id);
        console.log('All terms fulfilled!');

        // Auto-release escrow
        const releaseData = {
            reason: "Location verified successfully - auto-release",
            merchant_authorization: true
        };

        const release = await client.releaseEscrow(escrow.escrow_id, releaseData);
        console.log('Escrow released:', release.release_transaction_id);

    } catch (error) {
        console.error('Escrow workflow failed:', error.response?.data || error.message);

        // Handle specific error cases
        if (error.response?.status === 422) {
            console.log('Validation errors:', error.response.data.errors);
        } else if (error.response?.status === 429) {
            console.log('Rate limited - waiting before retry');
            // Implement retry logic
        }
    }
}

module.exports = { PiaxisEscrowClient };

Best Practices

Security Best Practices

  1. API Key Management: - Store API keys securely (environment variables, key vaults) - Rotate API keys regularly - Use different keys for different environments - Never commit API keys to version control

  2. Authentication Flow: - Validate OTP expiration times - Implement proper session management - Use HTTPS for all API communications - Validate user permissions before operations

  3. Data Validation: - Validate all inputs client-side and server-side - Sanitize user-provided data - Implement proper error handling - Log security-relevant events

Performance Best Practices

  1. Request Optimization: - Batch operations when possible - Implement caching for frequently accessed data - Use appropriate timeouts - Handle rate limiting gracefully

  2. Error Handling: - Implement exponential backoff for retries - Log detailed error information - Provide meaningful error messages to users - Monitor error rates and patterns

  3. Monitoring: - Track escrow completion rates - Monitor API response times - Set up alerts for high error rates - Analyze term fulfillment patterns

Operational Best Practices

  1. Escrow Lifecycle Management: - Set appropriate term deadlines - Monitor pending escrows regularly - Implement automated release for simple terms - Handle dispute resolution processes

  2. User Experience: - Provide clear term descriptions - Send status update notifications - Implement progress tracking - Offer customer support integration

  3. Business Logic: - Design terms that are easily verifiable - Implement fair dispute resolution - Consider regional payment preferences - Plan for edge cases and exceptions

Testing and Validation

  1. Integration Testing: - Test all payment methods - Validate term fulfillment flows - Test error scenarios - Verify webhook delivery

  2. User Acceptance Testing: - Test with real user scenarios - Validate mobile device compatibility - Test network connectivity edge cases - Verify OTP delivery across carriers

  3. Production Readiness: - Implement comprehensive logging - Set up monitoring and alerting - Plan for disaster recovery - Document operational procedures

Troubleshooting Guide

Common Issues and Solutions:

Issue: OTP not received Solution: - Check phone number format - Verify carrier compatibility - Implement alternative delivery methods - Check OTP expiration times

Issue: Term fulfillment failures Solution: - Validate location accuracy requirements - Check device permissions - Verify user authentication - Review term-specific requirements

Issue: High escrow reversal rates Solution: - Review term clarity and fairness - Improve product/service descriptions - Implement better dispute resolution - Analyze reversal reasons

Issue: Performance problems Solution: - Check API rate limits - Optimize request patterns - Implement proper caching - Monitor database performance

Support and Resources

Emergency Contact: For critical issues affecting production systems, contact support@piaxis.com with “URGENT” in the subject line.