PHP examples
Using Guzzle as the HTTP client. hash_hmac and hash_equals are from the standard library.
Reusable client
<?php
use GuzzleHttp\Client;
const BASE_URL = 'https://api.internationalfinance.com.br/v1';
function infiRequest(string $path, string $method = 'GET', ?array $body = null, ?array $query = null): array {
$client = new Client(['http_errors' => false]);
$headers = ['Authorization' => 'Bearer ' . getenv('INFI_API_KEY')];
if ($body !== null) $headers['Content-Type'] = 'application/json';
$res = $client->request($method, BASE_URL . $path, [
'headers' => $headers,
'json' => $body,
'query' => $query,
]);
$status = $res->getStatusCode();
$data = json_decode((string) $res->getBody(), true) ?? [];
return ['status' => $status, 'body' => $data];
}
// Create charge
$res = infiRequest('/pix', 'POST', [
'amountCents' => 1000,
'externalRef' => 'order-123',
'customer' => [
'name' => 'Maria Silva',
'email' => 'maria@example.com',
'phone' => '11999998888',
'document' => ['number' => '12345678901', 'type' => 'cpf'],
],
]);
if ($res['status'] >= 400) {
throw new RuntimeException($res['body']['error'] ?? 'INFI error');
}
// Initiate withdrawal — mind 202.
// Currently only the registered account holder's CPF/CNPJ.
$res = infiRequest('/withdraw', 'POST', [
'amountCents' => 5000,
'pixKey' => '12345678901',
'pixKeyType' => 'cpf',
]);
if ($res['status'] === 202) {
// failed_unknown — do not resend
} elseif ($res['status'] >= 400) {
throw new RuntimeException($res['body']['error']);
}Receive webhook
<?php
$ts = $_SERVER['HTTP_X_INFI_TIMESTAMP'] ?? '';
$sigHeader = $_SERVER['HTTP_X_INFI_SIGNATURE'] ?? '';
$sig = str_starts_with($sigHeader, 'sha256=') ? substr($sigHeader, 7) : '';
if (!ctype_digit($ts) || abs(time() - (int)$ts) > 300) {
http_response_code(401);
exit;
}
$raw = file_get_contents('php://input');
$payload = $ts . '.' . $raw;
$expected = hash_hmac('sha256', $payload, getenv('INFI_WEBHOOK_SECRET'));
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit;
}
$event = json_decode($raw, true);
// Idempotency by (transactionId, status). Respond < 8s.
http_response_code(200);