Skip to main content

Making Your First Request

Ready to make your first API call? This guide walks you through authentication setup and making your first requests to the Wallet API.

Prerequisites

Before starting, ensure you have:

Quick Start Overview

Making an API call involves three steps:

Let's go through each step with practical examples.


Step 1: Prepare Your Credentials

First, gather your credentials based on your authentication method.

MAC Credentials

You should have received:

const credentials = {
client_id: 'wkVd93h2uS', // Your client ID
mac_key: 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU', // Secret key
mac_algorithm: 'hmac-sha-256' // Algorithm
};
Keep Secret

Never commit mac_key to version control or share it publicly!


Step 2: Test with a Simple GET Request

Let's start with the simplest possible request - getting server time (no authentication required).

Why Start Here?

  • ✅ No authentication needed
  • ✅ Quick to test
  • ✅ Verifies API connectivity
  • ✅ Good for clock synchronization
curl -X GET https://wallet.paysera.com/rest/v1/server

Response:

{
"time": 1698675600
}
Success Check

If you got a JSON response with a time field, congratulations! Your connection to the API works. 🎉


Step 3: Make an Authenticated Request

Now let's make a request that requires authentication. We'll get server configuration.

Understanding MAC Authentication:

MAC authentication requires calculating a signature for each request:

timestamp + nonce + HTTP_METHOD + REQUEST_URI + HOST + PORT + ext_params

MAC Authentication Example:

<?php

// Your credentials
$clientId = 'wkVd93h2uS';
$macKey = 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU';

// Request details
$method = 'GET';
$uri = '/rest/v1/configuration';
$host = 'wallet.paysera.com';
$port = 443;

// Generate timestamp and nonce
$timestamp = time();
$nonce = bin2hex(random_bytes(16));

// Build normalized request string
$normalizedString = implode("\n", [
$timestamp,
$nonce,
$method,
$uri,
$host,
$port,
'' // ext params (empty for this request)
]) . "\n";

// Calculate MAC
$mac = base64_encode(hash_hmac('sha256', $normalizedString, $macKey, true));

// Build authorization header
$authHeader = sprintf(
'MAC id="%s", ts="%s", nonce="%s", mac="%s"',
$clientId,
$timestamp,
$nonce,
$mac
);

// Make request
$ch = curl_init("https://{$host}{$uri}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: {$authHeader}",
'User-Agent: MyApp/1.0'
]
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($httpCode === 200) {
$data = json_decode($response, true);
echo "Minimum password length: " . $data['minimum_password_length'] . "\n";
} else {
echo "Error: HTTP {$httpCode}\n";
echo $response . "\n";
}

curl_close($ch);

SSL Certificate Example:

<?php

$ch = curl_init('https://wallet.paysera.com/rest/v1/configuration');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSLCERT => '/path/to/client.crt',
CURLOPT_SSLKEY => '/path/to/client.key',
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
echo "Min password: " . $data['minimum_password_length'];
Expected Response
{
"minimum_password_length": 8
}

Step 4: Make a POST Request

Let's create a simple transaction to see POST requests in action.

<?php

$clientId = 'wkVd93h2uS';
$macKey = 'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU';

// Request data
$requestData = [
'payments' => [
[
'description' => 'Test payment',
'price' => 1000, // 10.00 EUR in cents
'currency' => 'EUR'
]
],
'redirect_uri' => 'https://yoursite.com/return'
];

$requestBody = json_encode($requestData);

// Request details
$method = 'POST';
$uri = '/rest/v1/transaction';
$host = 'wallet.paysera.com';
$port = 443;

// Generate timestamp and nonce
$timestamp = time();
$nonce = bin2hex(random_bytes(16));

// Calculate body hash for POST requests
$bodyHash = base64_encode(hash('sha256', $requestBody, true));
$ext = 'body_hash=' . urlencode($bodyHash);

// Build normalized request string
$normalizedString = implode("\n", [
$timestamp,
$nonce,
$method,
$uri,
$host,
$port,
$ext
]) . "\n";

// Calculate MAC
$mac = base64_encode(hash_hmac('sha256', $normalizedString, $macKey, true));

// Build authorization header
$authHeader = sprintf(
'MAC id="%s", ts="%s", nonce="%s", mac="%s", ext="%s"',
$clientId,
$timestamp,
$nonce,
$mac,
$ext
);

// Make request
$ch = curl_init("https://{$host}{$uri}");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $requestBody,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: {$authHeader}",
'Content-Type: application/json',
'User-Agent: MyApp/1.0'
]
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($httpCode === 200) {
$transaction = json_decode($response, true);
echo "Transaction created!\n";
echo "Transaction key: " . $transaction['transaction_key'] . "\n";
echo "Status: " . $transaction['status'] . "\n";
} else {
echo "Error: HTTP {$httpCode}\n";
$error = json_decode($response, true);
echo "Error: " . ($error['error'] ?? 'Unknown') . "\n";
echo "Description: " . ($error['error_description'] ?? 'No description') . "\n";
}

curl_close($ch);

Troubleshooting Common Errors

❌ Error: unauthorized (401)

Cause: Authentication failed

Solutions:

  • ✅ Verify your credentials are correct
  • ✅ Check timestamp isn't too far from server time (max ±5 minutes)
  • ✅ Ensure MAC signature calculation is correct
  • ✅ Verify nonce is randomly generated and unique

Check Time Synchronization:

# Check server time
curl https://wallet.paysera.com/rest/v1/server

# Compare with your local time
date +%s

# If difference > 300 seconds, sync your clock

Debug MAC Calculation:

// Output normalized string for debugging
echo "Normalized string:\n";
echo $normalizedString;
echo "\n\nMAC: " . $mac . "\n";
❌ Error: forbidden (403)

Cause: No permission for this action

Solutions:

  • ✅ Verify your client has necessary permissions
  • ✅ Check if using correct project_id in ext parameter
  • ✅ Ensure you're accessing resources you own
  • ✅ Contact support if permissions seem incorrect

Example with project_id:

$ext = 'project_id=123';  // Add your project ID
❌ Error: invalid_parameters (400)

Cause: Request parameters are invalid

Solutions:

  • ✅ Check request JSON syntax is valid
  • ✅ Verify all required fields are present
  • ✅ Ensure correct data types (string vs number)
  • ✅ Check parameter formats (e.g., currency codes must be 3 letters)

Example Error Response:

{
"error": "invalid_parameters",
"error_description": "Currency must be 3-letter code (e.g., EUR)",
"errors": [
{
"field": "currency",
"message": "Invalid format"
}
]
}
❌ SSL Certificate Errors

Error: SSL certificate problem: unable to get local issuer certificate

Solutions:

  • ✅ Verify certificate file paths are correct
  • ✅ Check certificate hasn't expired
  • ✅ Ensure private key matches certificate
  • ✅ Verify server certificate validation is enabled
  • ✅ Update CA bundle if needed

PHP Solutions:

// Option 1: Specify CA bundle (recommended)
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');

// Option 2: Update PHP's default CA bundle
// Download from: https://curl.se/docs/caextract.html

Node.js Solutions:

// Specify CA bundle
const options = {
ca: fs.readFileSync('/path/to/ca-bundle.crt')
};
Testing Only

Never disable SSL verification in production:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  // DANGEROUS!
❌ Error: invalid_grant

Cause: Token refresh failed or authorization code already used

Solutions:

  • ✅ Ensure authorization code hasn't been used before
  • ✅ Check refresh token is still valid
  • ✅ Verify code hasn't expired
  • ✅ Request new authorization if needed
❌ Timeout Errors

Cause: Request took too long or network issues

Solutions:

  • ✅ Increase timeout settings (default 30s)
  • ✅ Check network connectivity
  • ✅ Implement retry logic with exponential backoff
  • ✅ Monitor API status page

PHP Timeout Configuration:

curl_setopt($ch, CURLOPT_TIMEOUT, 60);  // 60 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 10s to connect

Retry Logic Example:

function makeRequestWithRetry($url, $maxRetries = 3) {
$attempt = 0;

while ($attempt < $maxRetries) {
try {
return makeRequest($url);
} catch (TimeoutException $e) {
$attempt++;
if ($attempt >= $maxRetries) throw $e;

// Exponential backoff: 1s, 2s, 4s
sleep(pow(2, $attempt - 1));
}
}
}

Using Libraries

Instead of implementing authentication manually, use official libraries:

PHP Library:

composer require paysera/lib-wallet-php-client
<?php
require 'vendor/autoload.php';

use Paysera\WalletApi\WalletApi;
use Paysera\WalletApi\Util\Router;

$api = new WalletApi(
'wkVd93h2uS', // client_id
'IrdTc8uQodU7PRpLzzLTW6wqZAO6tAMU', // mac_key
Router::createForProduction() // Production environment
);

// Get server time
$server = $api->walletClient()->getServerInformation();
echo "Server time: " . $server->getTime() . "\n";

// Get configuration
$config = $api->walletClient()->getConfiguration();
echo "Min password length: " . $config->getMinimumPasswordLength() . "\n";

📚 Library Documentation


What's Next?

Now that you can make API requests, explore specific features:

For User Information:

For Payments:

  • 💳 Payments Overview - Learn about payment features (see Payments section in sidebar)
  • 📝 Payment Examples - See practical examples (see Payments > Payment Basics in sidebar)

Advanced Topics:


Need Help?

Stuck on something?

Pro Tip

Keep your first successful request code as a reference. It's helpful for troubleshooting future issues!