> For the complete documentation index, see [llms.txt](https://plexo.gitbook.io/rest-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://plexo.gitbook.io/rest-api/tools/code-examples.md).

# Code Examples

Complete code examples for integrating with the Plexo Payment Gateway API in multiple programming languages.

## Overview

This guide provides production-ready code examples for common API operations. All examples include:

* ✅ Error handling
* ✅ Environment variable support
* ✅ Best practices
* ✅ Authentication
* ✅ Type safety (where applicable)

## Authentication

All API requests require Basic Authentication. Store credentials securely:

{% tabs %}
{% tab title="Environment Variables" %}

```bash
# .env file
PLEXO_USERNAME=your_username
PLEXO_PASSWORD=your_password
PLEXO_API_URL=https://api.plexo.com.uy
PLEXO_MERCHANT_ID=your_merchant_id
```

{% endtab %}

{% tab title="Never Hardcode" %}

```javascript
// ❌ DON'T DO THIS
const username = 'john@merchant.com';
const password = 'MyPassword123';

// ✅ DO THIS
const username = process.env.PLEXO_USERNAME;
const password = process.env.PLEXO_PASSWORD;
```

{% endtab %}
{% endtabs %}

***

## Language-Specific Examples

### JavaScript / TypeScript

#### Setup

```bash
npm install node-fetch dotenv
# or
npm install axios dotenv
```

#### Fetch API

```javascript
// plexo-client.js
import fetch from 'node-fetch';
import dotenv from 'dotenv';

dotenv.config();

class PlexoClient {
  constructor() {
    this.baseUrl = process.env.PLEXO_API_URL || 'https://api.plexo.com.uy';
    this.username = process.env.PLEXO_USERNAME;
    this.password = process.env.PLEXO_PASSWORD;
    this.merchantId = parseInt(process.env.PLEXO_MERCHANT_ID);

    if (!this.username || !this.password) {
      throw new Error('PLEXO_USERNAME and PLEXO_PASSWORD are required');
    }

    // Base64 encode credentials
    this.authHeader = 'Basic ' + Buffer.from(
      `${this.username}:${this.password}`
    ).toString('base64');
  }

  async request(method, path, body = null) {
    const url = `${this.baseUrl}${path}`;
    const headers = {
      'Authorization': this.authHeader,
      'Content-Type': 'application/json'
    };

    const options = {
      method,
      headers,
      ...(body && { body: JSON.stringify(body) })
    };

    try {
      const response = await fetch(url, options);
      const data = await response.json();

      if (!response.ok) {
        throw new Error(
          `API Error: ${data.message || response.statusText}`
        );
      }

      return data;
    } catch (error) {
      console.error('Request failed:', error);
      throw error;
    }
  }

  // Customer operations
  async createCustomer(customerData) {
    return this.request('POST', '/v1/customers', customerData);
  }

  async getCustomer(customerId) {
    return this.request('GET', `/v1/customers/${customerId}`);
  }

  async listCustomers(params = {}) {
    const query = new URLSearchParams(params).toString();
    const path = `/v1/customers${query ? '?' + query : ''}`;
    return this.request('GET', path);
  }

  // Session operations
  async createSession(sessionData) {
    return this.request('POST', '/v1/sessions', sessionData);
  }

  async getSession(sessionId) {
    return this.request('GET', `/v1/sessions/${sessionId}`);
  }

  // Payment operations
  async createPayment(paymentData) {
    return this.request('POST', '/v1/payments', paymentData);
  }

  async getPayment(paymentId) {
    return this.request('GET', `/v1/payments/${paymentId}`);
  }

  async capturePayment(paymentId, captureData) {
    return this.request(
      'POST',
      `/v1/payments/${paymentId}/capture`,
      captureData
    );
  }

  async cancelPayment(paymentId) {
    return this.request('POST', `/v1/payments/${paymentId}/cancel`);
  }

  async refundPayment(paymentId, refundData) {
    return this.request(
      'POST',
      `/v1/payments/${paymentId}/refund`,
      refundData
    );
  }
}

// Usage example
async function main() {
  const client = new PlexoClient();

  try {
    // Create a customer
    const customer = await client.createCustomer({
      referenceId: `customer-${Date.now()}`,
      email: 'john.doe@example.com',
      firstName: 'John',
      lastName: 'Doe',
      phone: '+1-555-0123'
    });
    console.log('Customer created:', customer.id);

    // Create tokenization session
    const session = await client.createSession({
      merchantId: client.merchantId,
      type: 'tokenization',
      referenceId: `session-${Date.now()}`,
      customerId: customer.id,
      callbackUrl: 'https://yoursite.com/callback'
    });
    console.log('Session URL:', session.actions.find(a => a.rel === 'REDIRECT').href);

    // Later: Create payment with token
    const payment = await client.createPayment({
      merchantId: client.merchantId,
      amount: 100.00,
      currency: 'USD',
      customerId: customer.id,
      instrumentId: 'token-from-session',
      capture: true
    });
    console.log('Payment created:', payment.id);

  } catch (error) {
    console.error('Operation failed:', error.message);
    process.exit(1);
  }
}

main();
```

#### Axios

```javascript
import axios from 'axios';
import dotenv from 'dotenv';

dotenv.config();

const client = axios.create({
  baseURL: process.env.PLEXO_API_URL || 'https://api.plexo.com.uy',
  auth: {
    username: process.env.PLEXO_USERNAME,
    password: process.env.PLEXO_PASSWORD
  },
  headers: {
    'Content-Type': 'application/json'
  }
});

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

// Usage
async function createCustomer(data) {
  return client.post('/v1/customers', data);
}

async function getPayment(paymentId) {
  return client.get(`/v1/payments/${paymentId}`);
}
```

***

### Python

#### Setup

```bash
pip install requests python-dotenv
```

#### requests

```python
# plexo_client.py
import os
import requests
from typing import Optional, Dict, Any
from dotenv import load_dotenv

load_dotenv()

class PlexoClient:
    def __init__(self):
        self.base_url = os.getenv('PLEXO_API_URL', 'https://api.plexo.com.uy')
        self.username = os.getenv('PLEXO_USERNAME')
        self.password = os.getenv('PLEXO_PASSWORD')
        self.merchant_id = int(os.getenv('PLEXO_MERCHANT_ID'))

        if not self.username or not self.password:
            raise ValueError('PLEXO_USERNAME and PLEXO_PASSWORD are required')

        self.auth = (self.username, self.password)
        self.headers = {'Content-Type': 'application/json'}

    def _request(
        self,
        method: str,
        path: str,
        data: Optional[Dict[str, Any]] = None,
        params: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        """Make HTTP request to Plexo API."""
        url = f'{self.base_url}{path}'

        try:
            response = requests.request(
                method=method,
                url=url,
                auth=self.auth,
                headers=self.headers,
                json=data,
                params=params
            )
            response.raise_for_status()
            return response.json()
        except requests.exceptions.HTTPError as e:
            error_data = e.response.json() if e.response.text else {}
            error_msg = error_data.get('message', str(e))
            raise Exception(f'API Error: {error_msg}') from e
        except requests.exceptions.RequestException as e:
            raise Exception(f'Request failed: {str(e)}') from e

    # Customer operations
    def create_customer(self, customer_data: Dict[str, Any]) -> Dict[str, Any]:
        """Create a new customer."""
        return self._request('POST', '/v1/customers', data=customer_data)

    def get_customer(self, customer_id: str) -> Dict[str, Any]:
        """Get customer by ID."""
        return self._request('GET', f'/v1/customers/{customer_id}')

    def list_customers(
        self,
        page: int = 1,
        page_size: int = 20,
        **filters
    ) -> Dict[str, Any]:
        """List customers with pagination."""
        params = {'page': page, 'pageSize': page_size, **filters}
        return self._request('GET', '/v1/customers', params=params)

    # Session operations
    def create_session(self, session_data: Dict[str, Any]) -> Dict[str, Any]:
        """Create tokenization or checkout session."""
        return self._request('POST', '/v1/sessions', data=session_data)

    def get_session(self, session_id: str) -> Dict[str, Any]:
        """Get session by ID."""
        return self._request('GET', f'/v1/sessions/{session_id}')

    # Payment operations
    def create_payment(self, payment_data: Dict[str, Any]) -> Dict[str, Any]:
        """Create a payment."""
        return self._request('POST', '/v1/payments', data=payment_data)

    def get_payment(self, payment_id: str) -> Dict[str, Any]:
        """Get payment by ID."""
        return self._request('GET', f'/v1/payments/{payment_id}')

    def capture_payment(
        self,
        payment_id: str,
        capture_data: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        """Capture authorized payment."""
        return self._request(
            'POST',
        f'/v1/payments/{payment_id}/captures',
            data=capture_data or {}
        )

    def cancel_payment(self, payment_id: str) -> Dict[str, Any]:
        """Cancel authorized payment."""
      return self._request('POST', f'/v1/payments/{payment_id}/cancellations')

    def refund_payment(
        self,
        payment_id: str,
        refund_data: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Refund captured payment."""
        return self._request(
            'POST',
        f'/v1/payments/{payment_id}/refunds',
            data=refund_data
        )

# Usage example
if __name__ == '__main__':
    client = PlexoClient()

    try:
        # Create customer
        customer = client.create_customer({
            'referenceId': f'customer-{int(time.time())}',
            'email': 'john.doe@example.com',
            'firstName': 'John',
            'lastName': 'Doe',
            'phone': '+1-555-0123'
        })
        print(f"Customer created: {customer['id']}")

        # Create tokenization session
        session = client.create_session({
            'merchantId': client.merchant_id,
            'type': 'tokenization',
            'referenceId': f'session-{int(time.time())}',
            'customerId': customer['id'],
            'callbackUrl': 'https://yoursite.com/callback'
        })
        redirect_url = next(
            a['href'] for a in session['actions'] if a['rel'] == 'REDIRECT'
        )
        print(f"Session URL: {redirect_url}")

        # Later: Create payment
        payment = client.create_payment({
            'merchantId': client.merchant_id,
            'amount': 100.00,
            'currency': 'USD',
            'customerId': customer['id'],
            'instrumentId': 'token-from-session',
            'capture': True
        })
        print(f"Payment created: {payment['id']}")

    except Exception as e:
        print(f"Operation failed: {e}")
        exit(1)
```

***

### C# / .NET

#### Setup

```bash
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
```

#### HttpClient

```csharp
// PlexoClient.cs
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;

public class PlexoClient : IDisposable
{
    private readonly HttpClient _client;
    private readonly int _merchantId;

    public PlexoClient(IConfiguration configuration)
    {
        var baseUrl = configuration["PLEXO_API_URL"] ?? "https://api.plexo.com.uy";
        var username = configuration["PLEXO_USERNAME"]
            ?? throw new ArgumentException("PLEXO_USERNAME is required");
        var password = configuration["PLEXO_PASSWORD"]
            ?? throw new ArgumentException("PLEXO_PASSWORD is required");
        _merchantId = int.Parse(configuration["PLEXO_MERCHANT_ID"]
            ?? throw new ArgumentException("PLEXO_MERCHANT_ID is required"));

        _client = new HttpClient
        {
            BaseAddress = new Uri(baseUrl)
        };

        var credentials = Convert.ToBase64String(
            Encoding.ASCII.GetBytes($"{username}:{password}")
        );
        _client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Basic", credentials);
        _client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json")
        );
    }

    // Customer operations
    public async Task<CustomerDto> CreateCustomerAsync(CreateCustomerRequest request)
    {
        var response = await _client.PostAsJsonAsync("/v1/customers", request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<CustomerDto>();
    }

    public async Task<CustomerDto> GetCustomerAsync(string customerId)
    {
        var response = await _client.GetAsync($"/v1/customers/{customerId}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<CustomerDto>();
    }

    public async Task<PagedResult<CustomerDto>> ListCustomersAsync(
        int page = 1,
        int pageSize = 20)
    {
        var response = await _client.GetAsync(
            $"/v1/customers?page={page}&pageSize={pageSize}"
        );
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<PagedResult<CustomerDto>>();
    }

    // Session operations
    public async Task<SessionDto> CreateSessionAsync(CreateSessionRequest request)
    {
        var response = await _client.PostAsJsonAsync("/v1/sessions", request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<SessionDto>();
    }

    public async Task<SessionDto> GetSessionAsync(Guid sessionId)
    {
        var response = await _client.GetAsync($"/v1/sessions/{sessionId}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<SessionDto>();
    }

    // Payment operations
    public async Task<PaymentDto> CreatePaymentAsync(CreatePaymentRequest request)
    {
        var response = await _client.PostAsJsonAsync("/v1/payments", request);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<PaymentDto>();
    }

    public async Task<PaymentDto> GetPaymentAsync(string paymentId)
    {
        var response = await _client.GetAsync($"/v1/payments/{paymentId}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<PaymentDto>();
    }

    public async Task<PaymentDto> CapturePaymentAsync(
        string paymentId,
        CaptureRequest captureRequest = null)
    {
        var response = await _client.PostAsJsonAsync(
        $"/v1/payments/{paymentId}/captures",
            captureRequest ?? new CaptureRequest()
        );
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<PaymentDto>();
    }

    public async Task<PaymentDto> CancelPaymentAsync(string paymentId)
    {
        var response = await _client.PostAsync(
        $"/v1/payments/{paymentId}/cancellations",
            null
        );
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<PaymentDto>();
    }

    public async Task<RefundDto> RefundPaymentAsync(
        string paymentId,
        RefundRequest refundRequest)
    {
        var response = await _client.PostAsJsonAsync(
        $"/v1/payments/{paymentId}/refunds",
            refundRequest
        );
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<RefundDto>();
    }

    public void Dispose()
    {
        _client?.Dispose();
    }
}

// Usage example
public class Program
{
    public static async Task Main(string[] args)
    {
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: true)
            .AddEnvironmentVariables()
            .Build();

        using var client = new PlexoClient(configuration);

        try
        {
            // Create customer
            var customer = await client.CreateCustomerAsync(new CreateCustomerRequest
            {
                ReferenceId = $"customer-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
                Email = "john.doe@example.com",
                FirstName = "John",
                LastName = "Doe",
                Phone = "+1-555-0123"
            });
            Console.WriteLine($"Customer created: {customer.Id}");

            // Create tokenization session
            var session = await client.CreateSessionAsync(new CreateSessionRequest
            {
                MerchantId = client._merchantId,
                Type = "tokenization",
                ReferenceId = $"session-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
                CustomerId = customer.Id,
                CallbackUrl = "https://yoursite.com/callback"
            });
            var redirectUrl = session.Actions
                .FirstOrDefault(a => a.Rel == "REDIRECT")?.Href;
            Console.WriteLine($"Session URL: {redirectUrl}");

            // Later: Create payment
            var payment = await client.CreatePaymentAsync(new CreatePaymentRequest
            {
                MerchantId = client._merchantId,
                Amount = 100.00m,
                Currency = "USD",
                CustomerId = customer.Id,
                InstrumentId = "token-from-session",
                Capture = true
            });
            Console.WriteLine($"Payment created: {payment.Id}");
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"Request failed: {ex.Message}");
            Environment.Exit(1);
        }
    }
}
```

***

## Error Handling Best Practices

### JavaScript

```javascript
async function createPaymentWithRetry(client, paymentData, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await client.createPayment(paymentData);
    } catch (error) {
      // Check if error is retriable
      if (error.statusCode === 429 || error.statusCode >= 500) {
        if (attempt < maxRetries) {
          const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
          console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms`);
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }
      throw error; // Non-retriable or max retries reached
    }
  }
}
```

### Python

```python
import time
from typing import Callable, TypeVar, Any

T = TypeVar('T')

def retry_on_error(
    func: Callable[..., T],
    max_retries: int = 3,
    backoff_factor: int = 2
) -> T:
    """Retry function with exponential backoff."""
    for attempt in range(1, max_retries + 1):
        try:
            return func()
        except requests.exceptions.HTTPError as e:
            # Retry on rate limit or server errors
            if e.response.status_code in (429, 500, 502, 503, 504):
                if attempt < max_retries:
                    delay = backoff_factor ** attempt
                    print(f"Retry {attempt}/{max_retries} after {delay}s")
                    time.sleep(delay)
                    continue
            raise  # Non-retriable or max retries reached

# Usage
payment = retry_on_error(
    lambda: client.create_payment(payment_data),
    max_retries=3
)
```

### C\#

```csharp
public async Task<T> RetryOnErrorAsync<T>(
    Func<Task<T>> operation,
    int maxRetries = 3,
    int backoffFactor = 2)
{
    for (int attempt = 1; attempt <= maxRetries; attempt++)
    {
        try
        {
            return await operation();
        }
        catch (HttpRequestException ex)
        {
            // Retry on rate limit or server errors
            if (ex.StatusCode == HttpStatusCode.TooManyRequests ||
                (int)ex.StatusCode >= 500)
            {
                if (attempt < maxRetries)
                {
                    var delay = TimeSpan.FromSeconds(Math.Pow(backoffFactor, attempt));
                    Console.WriteLine($"Retry {attempt}/{maxRetries} after {delay.TotalSeconds}s");
                    await Task.Delay(delay);
                    continue;
                }
            }
            throw; // Non-retriable or max retries reached
        }
    }
    throw new InvalidOperationException("Should not reach here");
}

// Usage
var payment = await RetryOnErrorAsync(
    () => client.CreatePaymentAsync(paymentData),
    maxRetries: 3
);
```

***

## Complete Integration Example

### E-commerce Checkout Flow

```javascript
// complete-checkout.js
import { PlexoClient } from './plexo-client.js';

async function processCheckout(orderData) {
  const client = new PlexoClient();

  try {
    // Step 1: Create or retrieve customer
    let customer;
    if (orderData.existingCustomerId) {
      customer = await client.getCustomer(orderData.existingCustomerId);
    } else {
      customer = await client.createCustomer({
        referenceId: orderData.customerReference,
        email: orderData.email,
        firstName: orderData.firstName,
        lastName: orderData.lastName,
        phone: orderData.phone
      });
    }
    console.log(`✓ Customer: ${customer.id}`);

    // Step 2: Create tokenization session
    const session = await client.createSession({
      merchantId: client.merchantId,
      type: 'tokenization',
      referenceId: `checkout-${orderData.orderId}`,
      customerId: customer.id,
      callbackUrl: `${process.env.SITE_URL}/payment/callback`,
      metadata: {
        orderId: orderData.orderId
      }
    });
    const redirectUrl = session.actions.find(a => a.rel === 'REDIRECT').href;
    console.log(`✓ Session created: ${session.id}`);
    console.log(`  Redirect customer to: ${redirectUrl}`);

    // Return session info to frontend
    return {
      success: true,
      customerId: customer.id,
      sessionId: session.id,
      redirectUrl: redirectUrl
    };

  } catch (error) {
    console.error('Checkout failed:', error.message);
    return {
      success: false,
      error: error.message
    };
  }
}

async function processPayment(customerId, instrumentId, orderData) {
  const client = new PlexoClient();

  try {
    // Create payment with saved token
    const payment = await client.createPayment({
      merchantId: client.merchantId,
      customerId: customerId,
      instrumentId: instrumentId,
      amount: orderData.amount,
      currency: orderData.currency,
      capture: false, // Authorize only, capture after shipment
      metadata: {
        orderId: orderData.orderId,
        items: JSON.stringify(orderData.items)
      }
    });

    console.log(`✓ Payment authorized: ${payment.id}`);
    console.log(`  Status: ${payment.status}`);
    console.log(`  Amount: ${payment.amount} ${payment.currency}`);

    return {
      success: true,
      paymentId: payment.id,
      status: payment.status
    };

  } catch (error) {
    console.error('Payment failed:', error.message);
    return {
      success: false,
      error: error.message
    };
  }
}

async function capturePaymentAfterShipment(paymentId, trackingNumber) {
  const client = new PlexoClient();

  try {
    const payment = await client.capturePayment(paymentId, {
      metadata: {
        trackingNumber: trackingNumber,
        capturedAt: new Date().toISOString()
      }
    });

    console.log(`✓ Payment captured: ${payment.id}`);
    console.log(`  Final status: ${payment.status}`);

    return { success: true, payment };

  } catch (error) {
    console.error('Capture failed:', error.message);
    return {
      success: false,
      error: error.message
    };
  }
}

// Export functions
export { processCheckout, processPayment, capturePaymentAfterShipment };
```

***

## Additional Resources

* [API Reference](/rest-api/api-reference/api-reference.md) - Complete endpoint documentation
* [Getting Started Guide](/rest-api/payments/first-payment.md) - Step-by-step tutorial
* [Authentication Guide](/rest-api/getting-started/authentication.md) - Auth setup and best practices
* [Error Codes Reference](/rest-api/reference/error-codes.md) - Error codes and solutions
* [Postman Collection](/rest-api/tools/postman-collection.md) - Pre-built API collection

***

**Need Help?**

* **Email**: <soporte@plexo.com.uy>
* **Documentation**: [docs.plexo.com](https://docs.plexo.com)
* **GitHub**: [github.com/plexouy/gitbook-public-docs](https://github.com/plexouy/gitbook-public-docs)

***

**Last Updated**: December 11, 2025 **API Version**: v1


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://plexo.gitbook.io/rest-api/tools/code-examples.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
