Skip to content

Best Practices

Guidelines for building robust Pixlpay integrations.

Security

Protect Your API Token

javascript
// Good: Use environment variables
const token = process.env.PIXLPAY_TOKEN;

// Bad: Hardcoded tokens
const token = 'abc123...';  // Never do this!

Verify Webhooks

Always verify webhook signatures before processing:

javascript
const computed = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(signature))) {
    throw new Error('Invalid signature');
}

Use Minimal Scopes

Request only the permissions you need:

// Good: Specific scopes
orders:read, products:read

// Avoid: Full access when not needed
full_access

Rotate Tokens

Regularly rotate API tokens, especially if:

  • Team members leave
  • A token may have been exposed
  • As part of regular security practices

Error Handling

Handle All Status Codes

javascript
async function apiCall(endpoint) {
    const response = await client.get(endpoint);

    switch (response.status) {
        case 200:
        case 201:
            return response.data;
        case 401:
            await refreshToken();
            return apiCall(endpoint);
        case 429:
            await sleep(response.data.retry_after * 1000);
            return apiCall(endpoint);
        case 500:
        case 502:
        case 503:
            await sleep(5000);
            return apiCall(endpoint);
        default:
            throw new ApiError(response);
    }
}

Log Errors

Maintain error logs for debugging:

javascript
function logError(context, error) {
    console.error(JSON.stringify({
        timestamp: new Date().toISOString(),
        context,
        status: error.status,
        message: error.message,
        endpoint: error.endpoint
    }));
}

Performance

Use Pagination Efficiently

Fetch appropriate page sizes:

javascript
// Good: Reasonable page size
const response = await client.get('/orders?per_page=50');

// Bad: Too many small requests
for (let i = 1; i <= 100; i++) {
    await client.get(`/orders?page=${i}&per_page=1`);
}

Cache When Appropriate

Cache data that doesn't change frequently:

javascript
// Products change infrequently - cache for 5 minutes
const products = await getCached('products', 5 * 60, () =>
    client.get('/products')
);

// Orders change often - shorter cache or no cache
const orders = await client.get('/orders');

Use Webhooks Over Polling

javascript
// Bad: Polling every minute
setInterval(() => checkForNewOrders(), 60000);

// Good: React to webhooks instantly
app.post('/webhooks', (req, res) => {
    handleNewOrder(req.body.data);
    res.sendStatus(200);
});

Reliability

Implement Retries

For transient failures, retry with backoff:

javascript
async function fetchWithRetry(endpoint, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            const response = await client.get(endpoint);
            if (response.status < 500) return response;
        } catch (error) {
            if (attempt === maxRetries - 1) throw error;
        }

        // Exponential backoff
        await sleep(Math.pow(2, attempt) * 1000);
    }
}

Handle Idempotency

Process webhooks idempotently - the same event may be delivered multiple times:

javascript
const processedEvents = new Set();

function handleWebhook(event) {
    // Skip if already processed
    if (processedEvents.has(event.id)) {
        return;
    }

    processEvent(event);
    processedEvents.add(event.id);
}

Timeout Requests

Set reasonable timeouts:

javascript
const client = axios.create({
    timeout: 30000,  // 30 seconds
    baseURL: 'https://yourstore.pixlpay.net/api/external/v1'
});

Webhooks

Respond Quickly

Respond with 200 before processing:

javascript
app.post('/webhooks', async (req, res) => {
    // Respond immediately
    res.sendStatus(200);

    // Process asynchronously
    setImmediate(() => {
        processWebhook(req.body);
    });
});

Use a Queue

For complex processing, use a job queue:

javascript
app.post('/webhooks', (req, res) => {
    // Add to queue
    queue.add('process-webhook', req.body);
    res.sendStatus(200);
});

// Process in background
queue.process('process-webhook', async (job) => {
    await processWebhook(job.data);
});

Log Everything

Log webhook deliveries for debugging:

javascript
function handleWebhook(event) {
    console.log('Webhook received:', {
        id: event.id,
        type: event.event,
        timestamp: event.timestamp
    });

    try {
        processEvent(event);
        console.log('Webhook processed:', event.id);
    } catch (error) {
        console.error('Webhook failed:', event.id, error);
        throw error;
    }
}

Testing

Use Test Mode

When available, test with sandbox/test mode before production.

Mock API Responses

Test your integration without hitting the real API:

javascript
// In tests
jest.mock('./pixlpay-client', () => ({
    get: jest.fn().mockResolvedValue({
        status: 200,
        data: { data: mockProducts }
    })
}));

Test Error Scenarios

Ensure your code handles errors gracefully:

javascript
test('handles 429 rate limit', async () => {
    mockClient.get.mockResolvedValueOnce({
        status: 429,
        data: { retry_after: 60 }
    });

    // Verify backoff is implemented
    await expect(fetchWithRetry('/products')).resolves.toBeDefined();
});

Built for game developers, by game developers.