Getting Started
Welcome to the PIN Banking API. This RESTful API provides secure access to banking transactions and payment creation.
Base URL: https://sandboxau.banking.payitnow.io/api
Use the Postman Collection
Download the ready-made collection and import it directly into Postman: Baas AU API.postman_collection.json.
- Open Postman β Import β choose the JSON file.
- Create an environment that defines
base_url(e.g. https://sandboxau.banking.payitnow.io),access_key(matchesAPI_ACCESS_KEY), and optionaltoken. - Send the Authenticate request first; its test script automatically stores the JWT in the
tokenvariable. - Subsequent requests reuse the JWT and compute the HMAC headers using those environment variables.
Payments are disabled in sandbox mode. Banking Circle blocks non-production settlement, so expect simulated βfailedβ responses whenever BC_SANDBOX=true.
Authentication
The API uses JWT tokens for authentication. Tokens expire after 5 minutes and must be refreshed by obtaining a new token.
Get JWT Token
{
"username": "your_username",
"access_key": "your_access_key"
}
PHP Example
<?php
// Step 1: Get JWT Token
function getAuthToken($username, $accessKey) {
$ch = curl_init('https://sandboxau.banking.payitnow.io/api/v1/auth/token');
$payload = json_encode([
'username' => $username,
'access_key' => $accessKey
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
return $data['token'];
}
throw new Exception('Authentication failed');
}
$token = getAuthToken('your_username', 'your_access_key');
echo "Token: " . $token . "\n";
Response: Returns a JWT token valid for 5 minutes. Store this token securely and use it in the Authorization header for all subsequent requests.
Account Balance Snapshot
Retrieve the latest account balance along with total credits, debits, and funds reserved for outgoing payments.
Endpoint
Sample Response
{
"date": "2025-01-15T03:15:40+00:00",
"balance": {
"available": "1250.00",
"total_credits": "3000.00",
"total_debits": "1500.00",
"reserved_outgoing": "250.00"
}
}
Field reference: available is credits minus debits minus reservations, total_credits/total_debits are raw ledger sums, and reserved_outgoing represents funds already earmarked for outgoing payments that have not failed or been cancelled yet (so they cannot be spent twice).
List Transactions
Retrieve a paginated list of all transactions including both deposits and withdrawals.
Endpoint
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| per_page | integer | Items per page (default: 20, max: 100) |
| from_date | date | Start date (YYYY-MM-DD) |
| to_date | date | End date (YYYY-MM-DD) |
| type | string | Filter: deposit, withdrawal, all (default: all) |
PHP Example with HMAC
<?php
function makeAuthenticatedRequest($method, $endpoint, $token, $accessKey, $data = []) {
$timestamp = time();
$body = $method === 'GET' ? '' : json_encode($data);
// Generate HMAC signature
$signature = hash_hmac('sha256', $body . $timestamp, $accessKey);
$url = 'https://sandboxau.banking.payitnow.io' . $endpoint;
if ($method === 'GET' && !empty($data)) {
$url .= '?' . http_build_query($data);
}
$ch = curl_init($url);
$headers = [
'Authorization: Bearer ' . $token,
'X-Signature: ' . $signature,
'X-Timestamp: ' . $timestamp,
'Content-Type: application/json',
'Accept: application/json'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [
'code' => $httpCode,
'body' => json_decode($response, true)
];
}
// Get transactions
$result = makeAuthenticatedRequest(
'GET',
'/api/v1/transactions',
$token,
'your_access_key',
[
'page' => 1,
'per_page' => 20,
'from_date' => '2025-01-01',
'type' => 'all'
]
);
print_r($result['body']);
Example Response
{
"data": [
{
"id": "txn_123",
"date": "2025-01-15T10:30:00+00:00",
"type": "deposit",
"direction": "credit",
"amount": "1500.00",
"currency": "AUD",
"counterparty": "ABC Corporation",
"reference": "INV-2025-001",
"status": "completed"
},
{
"id": "pmt_456",
"date": "2025-01-14T14:20:00+00:00",
"type": "withdrawal",
"direction": "debit",
"amount": "500.00",
"currency": "AUD",
"counterparty": "Supplier XYZ",
"reference": "Payment for services",
"status": "completed"
}
],
"meta": {
"current_page": 1,
"per_page": 20,
"total": 2,
"last_page": 1,
"from": 1,
"to": 2
}
}
Create Payment
Create a new outgoing payment. The API will validate sufficient balance before processing.
Sandbox calls return demo data only: the JSON matches production, but you will also see meta.sandbox_demo = true to indicate that no funds were moved.
Endpoint
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| amount | number | Yes | Payment amount (minimum: 0.01) |
| account | string | Yes | Account number |
| name | string | Yes | Beneficiary name |
| bsb | string | No | Australian BSB (6 digits) |
| country | string | Yes | 2-letter country code (e.g., AU) |
| reference | string | No | Payment reference |
PHP Example
<?php
$paymentData = [
'amount' => 150.50,
'account' => '12345678',
'name' => 'John Doe',
'bsb' => '123456',
'country' => 'AU',
'reference' => 'Invoice #INV-2025-001',
'remittance_line1' => 'Payment for consulting services'
];
$result = makeAuthenticatedRequest(
'POST',
'/api/v1/payments',
$token,
'your_access_key',
$paymentData
);
if ($result['code'] === 201) {
echo "Payment created successfully!\n";
echo "Payment ID: " . $result['body']['data']['id'] . "\n";
echo "Status: " . $result['body']['data']['status'] . "\n";
} else {
echo "Error: " . $result['body']['message'] . "\n";
}
Response: Returns 201 status code with payment details including payment ID and status.
Check Payment Status
Retrieve the current status of a payment. The API automatically checks with Banking Circle for the latest status.
Endpoint
PHP Example
<?php
$paymentId = 123; // Your payment ID
$result = makeAuthenticatedRequest(
'GET',
'/api/v1/payments/' . $paymentId,
$token,
'your_access_key'
);
if ($result['code'] === 200) {
$payment = $result['body']['data'];
echo "Payment Status: " . $payment['status'] . "\n";
echo "BC Status: " . ($payment['bc_status'] ?? 'N/A') . "\n";
echo "Amount: " . $payment['amount'] . " " . $payment['currency'] . "\n";
} else {
echo "Error: " . $result['body']['message'] . "\n";
}
Security
HMAC Signature Verification
All authenticated requests must include an HMAC signature to prevent tampering and replay attacks.
Required Headers
Authorization: Bearer {jwt_token}X-Signature: {hmac_signature}X-Timestamp: {unix_timestamp}
Signature Calculation
signature = HMAC-SHA256(request_body + timestamp, access_key)
Important: The timestamp must be within 30 seconds of the server time. Ensure your system clock is synchronized using NTP.
Rate Limiting
The API enforces rate limiting of 60 requests per minute per API key. Exceeding this limit will result in 429 (Too Many Requests) responses.
Best Practices
- Never expose your access key in client-side code or public repositories
- Store credentials securely using environment variables
- Implement token refresh logic before the 5-minute expiry
- Use HTTPS for all API requests
- Log and monitor API errors and failed authentication attempts
Error Codes
The API uses standard HTTP response codes to indicate success or failure.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Invalid credentials, expired token, or invalid signature |
| 404 | Not Found | Resource not found |
| 422 | Unprocessable Entity | Validation error |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error occurred |
Error Response Format
{
"error": "Error Type",
"message": "Detailed error message describing what went wrong"
}