Transaction API
This document provides information about the Transaction API endpoints in the UBU Finance backend.
Overview
The Transaction API allows you to create, retrieve, update, and delete financial transactions within the UBU Finance system. Transactions represent the movement of funds between accounts and are a core component of the financial system.
Authentication
All Transaction API endpoints require authentication. You must include a valid JWT token in the Authorization header of your requests.
Endpoints
List Transactions
Retrieves a list of transactions with optional filtering.
Endpoint: GET /api/transactions
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number for pagination (default: 1) |
| limit | integer | Number of items per page (default: 10, max: 100) |
| transaction_id | UUID | Filter by transaction ID |
| source_account_id | UUID | Filter by source account ID |
| destination_account_id | UUID | Filter by destination account ID |
| transaction_type | string | Filter by transaction type (e.g., 'deposit', 'withdrawal', 'transfer') |
| status | string | Filter by transaction status (e.g., 'pending', 'completed', 'failed') |
| min_amount | decimal | Filter transactions with amount greater than or equal to this value |
| max_amount | decimal | Filter transactions with amount less than or equal to this value |
| currency | string | Filter by currency code (e.g., 'RWF', 'EUR') |
| created_after | datetime | Filter transactions created after this date and time (ISO 8601 format) |
| created_before | datetime | Filter transactions created before this date and time (ISO 8601 format) |
| completed_after | datetime | Filter transactions completed after this date and time (ISO 8601 format) |
| completed_before | datetime | Filter transactions completed before this date and time (ISO 8601 format) |
Response:
{
"items": [
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440000",
"transaction_type": "deposit",
"amount": 1000.00,
"currency": "RWF",
"source_account_id": null,
"destination_account_id": "550e8400-e29b-41d4-a716-446655440001",
"status": "completed",
"description": "Initial deposit",
"created_at": "2025-01-01T12:00:00Z",
"updated_at": "2025-01-01T12:05:00Z"
}
],
"total": 1,
"page": 1,
"limit": 10,
"pages": 1
}
Get Transaction
Retrieves details of a specific transaction.
Endpoint: GET /api/transactions/{transaction_id}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| transaction_id | UUID | The ID of the transaction to retrieve |
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440000",
"transaction_type": "deposit",
"amount": 1000.00,
"currency": "RWF",
"source_account_id": null,
"destination_account_id": "550e8400-e29b-41d4-a716-446655440001",
"status": "completed",
"description": "Initial deposit",
"created_at": "2025-01-01T12:00:00Z",
"updated_at": "2025-01-01T12:05:00Z",
"metadata": {
"receipt_number": "REC-12345",
"payment_method": "bank_transfer"
}
}
Create Transaction
Creates a new transaction.
Endpoint: POST /api/transactions
Request Body:
{
"transaction_type": "transfer",
"amount": 500.00,
"currency": "RWF",
"source_account_id": "550e8400-e29b-41d4-a716-446655440001",
"destination_account_id": "550e8400-e29b-41d4-a716-446655440002",
"description": "Monthly transfer",
"metadata": {
"category": "savings",
"recurring": true
}
}
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440003",
"transaction_type": "transfer",
"amount": 500.00,
"currency": "RWF",
"source_account_id": "550e8400-e29b-41d4-a716-446655440001",
"destination_account_id": "550e8400-e29b-41d4-a716-446655440002",
"status": "pending",
"description": "Monthly transfer",
"created_at": "2025-01-02T12:00:00Z",
"updated_at": "2025-01-02T12:00:00Z",
"metadata": {
"category": "savings",
"recurring": true
}
}
Update Transaction
Updates an existing transaction. Only transactions with a status of 'pending' can be updated.
Endpoint: PUT /api/transactions/{transaction_id}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| transaction_id | UUID | The ID of the transaction to update |
Request Body:
{
"amount": 600.00,
"description": "Updated monthly transfer",
"metadata": {
"category": "investment",
"recurring": true
}
}
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440003",
"transaction_type": "transfer",
"amount": 600.00,
"currency": "RWF",
"source_account_id": "550e8400-e29b-41d4-a716-446655440001",
"destination_account_id": "550e8400-e29b-41d4-a716-446655440002",
"status": "pending",
"description": "Updated monthly transfer",
"created_at": "2025-01-02T12:00:00Z",
"updated_at": "2025-01-02T12:15:00Z",
"metadata": {
"category": "investment",
"recurring": true
}
}
Cancel Transaction
Cancels a pending transaction.
Endpoint: DELETE /api/transactions/{transaction_id}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| transaction_id | UUID | The ID of the transaction to cancel |
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440003",
"status": "cancelled",
"updated_at": "2025-01-02T12:30:00Z"
}
Get Transaction History
Retrieves the history of status changes for a transaction.
Endpoint: GET /api/transactions/{transaction_id}/history
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| transaction_id | UUID | The ID of the transaction |
Response:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440003",
"history": [
{
"status": "pending",
"timestamp": "2025-01-02T12:00:00Z",
"user_id": "550e8400-e29b-41d4-a716-446655440010"
},
{
"status": "processing",
"timestamp": "2025-01-02T12:05:00Z",
"user_id": null
},
{
"status": "completed",
"timestamp": "2025-01-02T12:10:00Z",
"user_id": null
}
]
}
Client Implementation Examples
Python
import requests
import json
# Configuration
API_URL = "http://localhost:8080"
TOKEN = "your_jwt_token"
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"
}
# List transactions
def list_transactions(account_id=None, transaction_type=None, page=1, limit=10):
params = {
"page": page,
"limit": limit
}
if account_id:
params["account_id"] = account_id
if transaction_type:
params["transaction_type"] = transaction_type
response = requests.get(f"{API_URL}/api/transactions", headers=headers, params=params)
if response.status_code == 200:
return response.json()
else:
print(f"Error: {response.status_code}")
print(response.text)
return None
# Create a transaction
def create_transaction(transaction_type, amount, currency, source_account_id, destination_account_id, description):
payload = {
"transaction_type": transaction_type,
"amount": amount,
"currency": currency,
"source_account_id": source_account_id,
"destination_account_id": destination_account_id,
"description": description
}
response = requests.post(f"{API_URL}/api/transactions", headers=headers, json=payload)
if response.status_code == 201:
return response.json()
else:
print(f"Error: {response.status_code}")
print(response.text)
return None
# Example usage
transactions = list_transactions(account_id="550e8400-e29b-41d4-a716-446655440001")
print(json.dumps(transactions, indent=2))
new_transaction = create_transaction(
transaction_type="transfer",
amount=500.00,
currency="RWF",
source_account_id="550e8400-e29b-41d4-a716-446655440001",
destination_account_id="550e8400-e29b-41d4-a716-446655440002",
description="Monthly transfer"
)
print(json.dumps(new_transaction, indent=2))
JavaScript
// Configuration
const API_URL = 'http://localhost:8080';
const TOKEN = 'your_jwt_token';
const headers = {
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'application/json'
};
// List transactions
async function listTransactions(params = {}) {
const queryParams = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null) {
queryParams.append(key, value);
}
}
const url = `${API_URL}/api/transactions?${queryParams.toString()}`;
try {
const response = await fetch(url, {
method: 'GET',
headers
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error listing transactions:', error);
throw error;
}
}
// Create a transaction
async function createTransaction(transactionData) {
try {
const response = await fetch(`${API_URL}/api/transactions`, {
method: 'POST',
headers,
body: JSON.stringify(transactionData)
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error creating transaction:', error);
throw error;
}
}
// Example usage
async function exampleUsage() {
try {
// List transactions for a specific account
const transactions = await listTransactions({
account_id: '550e8400-e29b-41d4-a716-446655440001',
page: 1,
limit: 10
});
console.log('Transactions:', transactions);
// Create a new transaction
const newTransaction = await createTransaction({
transaction_type: 'transfer',
amount: 500.00,
currency: 'RWF',
source_account_id: '550e8400-e29b-41d4-a716-446655440001',
destination_account_id: '550e8400-e29b-41d4-a716-446655440002',
description: 'Monthly transfer'
});
console.log('New transaction:', newTransaction);
} catch (error) {
console.error('Example usage error:', error);
}
}
exampleUsage();
cURL
# Set your JWT token
TOKEN="your_jwt_token"
# List transactions
curl -X GET "http://localhost:8080/api/transactions?page=1&limit=10" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json"
# Get a specific transaction
curl -X GET "http://localhost:8080/api/transactions/550e8400-e29b-41d4-a716-446655440003" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json"
# Create a transaction
curl -X POST "http://localhost:8080/api/transactions" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transaction_type": "transfer",
"amount": 500.00,
"currency": "RWF",
"source_account_id": "550e8400-e29b-41d4-a716-446655440001",
"destination_account_id": "550e8400-e29b-41d4-a716-446655440002",
"description": "Monthly transfer"
}'
# Update a transaction
curl -X PUT "http://localhost:8080/api/transactions/550e8400-e29b-41d4-a716-446655440003" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"amount": 600.00,
"description": "Updated monthly transfer"
}'
# Cancel a transaction
curl -X DELETE "http://localhost:8080/api/transactions/550e8400-e29b-41d4-a716-446655440003" \
-H "Authorization: Bearer $TOKEN"
C
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace UbuFinanceClient
{
class Program
{
private static readonly HttpClient client = new HttpClient();
private static readonly string ApiUrl = "http://localhost:8080";
private static readonly string Token = "your_jwt_token";
static async Task Main(string[] args)
{
// Configure HttpClient
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// List transactions
await ListTransactionsAsync();
// Create a transaction
await CreateTransactionAsync();
}
static async Task ListTransactionsAsync()
{
try
{
HttpResponseMessage response = await client.GetAsync($"{ApiUrl}/api/transactions?page=1&limit=10");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Transactions:");
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error listing transactions: {e.Message}");
}
}
static async Task CreateTransactionAsync()
{
var transaction = new
{
transaction_type = "transfer",
amount = 500.00,
currency = "RWF",
source_account_id = "550e8400-e29b-41d4-a716-446655440001",
destination_account_id = "550e8400-e29b-41d4-a716-446655440002",
description = "Monthly transfer"
};
var json = JsonSerializer.Serialize(transaction);
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync($"{ApiUrl}/api/transactions", content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("New Transaction:");
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error creating transaction: {e.Message}");
}
}
}
}
Error Handling
The Transaction API returns standard HTTP status codes:
| Status Code | Description |
|---|---|
| 200 | OK - The request was successful |
| 201 | Created - A new resource was created |
| 400 | Bad Request - The request was invalid |
| 401 | Unauthorized - Authentication is required |
| 403 | Forbidden - The user does not have permission |
| 404 | Not Found - The resource was not found |
| 409 | Conflict - The request could not be completed due to a conflict |
| 422 | Unprocessable Entity - The request was well-formed but could not be processed |
| 500 | Internal Server Error - An error occurred on the server |
Error responses include a JSON body with details:
{
"error": {
"code": "insufficient_funds",
"message": "Insufficient funds in source account",
"details": {
"account_id": "550e8400-e29b-41d4-a716-446655440001",
"available_balance": 400.00,
"required_amount": 500.00
}
}
}
Rate Limiting
The Transaction API is subject to rate limiting. See the Rate Limiting documentation for details.
Security Considerations
- All Transaction API endpoints are protected by authentication
- Sensitive operations require appropriate permissions
- All requests are logged for audit purposes
- Transaction amounts are validated against account balances
- Suspicious transactions may trigger additional verification
For more information on security features, see the Security Overview.