Skip to content

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.

Authorization: Bearer <your_token>

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.