CACI - Fiat Transaction Reporting API (1.0.1)

Download OpenAPI specification:

CACI Support Team: support@caci.id License: MIT

CACI - Fiat Transaction Reporting API

API for exchanges to report fiat deposit and withdrawal transactions to CACI for reconciliation and compliance tracking.

Overview

This API allows cryptocurrency exchanges to report completed fiat transactions to CACI in real-time or batch mode.

Key Features:

  • Report deposits and withdrawals with full transaction details
  • Batch processing up to 100 transactions per request
  • Flexible metadata support for additional context
  • Individual status reporting for each transaction
  • Idempotency support with transaction IDs

Authentication

API Key Authentication:

  • API Key authentication via X-Api-Key header
  • Each exchange receives a unique API key
  • API key must match the exchange_id in the request

Generating Signature

To generate the HMAC-SHA512 signature, follow these steps:

  1. Create canonical JSON: Sort the request body JSON keys alphabetically to ensure consistent ordering
  2. Build payload string: Format as "METHOD|PATH|BODY|TIMESTAMP"
  3. Calculate HMAC-SHA512: Use your API secret as the key
  4. Convert to hex: Get the lowercase hexadecimal representation

Python Implementation

import hmac
import hashlib
import json

def generate_signature(method, path, raw_body, timestamp, client_secret):
    """
    Generate HMAC-SHA512 signature for CACI API authentication
    
    Args:
        method: HTTP method (e.g., 'POST', 'GET')
        path: API endpoint path (e.g., '/v1/transactions/fiat')
        raw_body: Raw request body JSON string (empty string for GET/DELETE)
        timestamp: Unix timestamp in milliseconds
        client_secret: Your API secret key
    
    Returns:
        Hexadecimal signature string
    """
    # Create canonical JSON with sorted keys
    if raw_body:
        try:
            # Parse and re-sort JSON to ensure canonical ordering
            body_dict = json.loads(raw_body)
            canonical_body = json.dumps(body_dict, sort_keys=True, separators=(',', ':'))
        except json.JSONDecodeError:
            canonical_body = raw_body
    else:
        canonical_body = ""
    
    # Build payload
    payload = f"{method}|{path}|{canonical_body}|{timestamp}"
    
    # Generate HMAC-SHA512 signature
    signature = hmac.new(
        client_secret.encode("utf-8"),
        payload.encode("utf-8"),
        hashlib.sha512
    ).hexdigest()
    
    return signature

# Example usage
if __name__ == "__main__":
    # Sample request data
    method = "POST"
    path = "/v1/transactions/fiat"
    timestamp = 1763474667930
    client_secret = "your_api_secret_here"
    
    # Sample request body
    request_data = {
        "exchange_id": "EXCHANGE-001",
        "request_id": "3ed3502d-321b-4b84-b1b1-df45629bd46f",
        "request_ts_ms": 1763474667930,
        "transactions": [
            {
                "transaction_id": "5023ed3d-321b-4b84-b1b1-d29bd4f4566f",
                "user_id": "USER-001",
                "transaction_type": "DEPOSIT",
                "amount": "10000000",
                "currency": "IDR",
                "transaction_ts_ms": 1763474667930,
                "status": "COMPLETED",
                "bank_code": "BCA",
                "bank_account_number": "1234567890",
                "bank_account_name": "John Doe",
                "reference_number": "REF-001",
                "fee_amount": "5000",
                "fee_currency": "IDR",
                "metadata": [
                    {
                        "key": "payment_channel",
                        "value_type": "string",
                        "value": "bank_transfer"
                    },
                    {
                        "key": "verification_required",
                        "value_type": "boolean",
                        "value": False
                    }
                ]
            }
        ]
    }
    
    # Convert to canonical JSON
    raw_body = json.dumps(request_data, sort_keys=True, separators=(',', ':'))
    
    # Generate signature
    signature = generate_signature(method, path, raw_body, timestamp, client_secret)
    
    print(f"Payload: {method}|{path}|{raw_body}|{timestamp}")
    print(f"Signature: {signature}")
    
    # Headers to include in request
    headers = {
        "X-Api-Key": "your_api_key_here",
        "X-Signature": signature,
        "X-Timestamp": str(timestamp)
    }

Important Notes

  • Canonical JSON: Always sort JSON keys alphabetically to ensure consistent signature generation
  • Timestamp: Use current Unix timestamp in milliseconds (must be within 5 minutes of server time)
  • Empty body: For GET/DELETE requests, use empty string for the BODY component
  • Path: Use only the path portion, no host or query parameters
  • Encoding: Use UTF-8 encoding for both payload and secret key

Use Cases:

  • Daily transaction batch reporting
  • Real-time transaction sync for compliance
  • Historical transaction backfill
  • Regulatory reporting support

System Health

System health check

System health check

Check the overall health of the CACI system

Responses

Response samples

Content type
application/json
{
  • "status": "healthy",
  • "service": "caci-transaction-system",
  • "version": "1.0.0",
  • "timestamp": "2019-08-24T14:15:22Z"
}

Transaction Reporting

Fiat transaction reporting API for exchanges

Report Fiat Transactions

Report fiat deposit and withdrawal transactions from exchange to CACI for reconciliation and compliance tracking.

Functionality:

  • Exchanges report completed fiat transactions (deposits/withdrawals) to CACI
  • Supports batch reporting (up to 100 transactions per request)
  • Each transaction includes transaction details, amounts, fees, and optional metadata
  • CACI validates and stores transaction records for reconciliation
  • Returns individual status for each transaction in the batch

Use Cases:

  • Daily transaction reporting from exchange to CACI
  • Real-time transaction sync for compliance monitoring
  • Historical transaction backfill
  • Reconciliation support for regulatory reporting

Authentication:

  • Requires API Key authentication (X-Api-Key header)
  • API key must be associated with a valid exchange
  • Exchange ID in request must match authenticated exchange

Rate Limits:

  • Maximum 100 transactions per request
  • Recommended batch size: 50 transactions for optimal performance

Metadata Support:

  • Each transaction can include optional metadata (key-value pairs)
  • Metadata values support three types: string, number, boolean
  • Useful for storing additional context like promo codes, user segments, etc.

Note: Trade report submission is processed asynchronously. The API will accept the payload and enqueue it for processing. You can check the processing status of a trade report from the ICEx dashboard.

Authorizations:
ApiKeyAuth
header Parameters
X-Api-Key
required
string
Example: 42a5eef831b2df8cb4a1106c1d6e623df7424322324afe73

Exchange API key for authentication

X-Signature
required
string
Example: 4b2f8a0e6c3c1a9d5f8b2c4e7a1d3f9b0c2e4a6d8f0b1c3d5e7f9a1b2c3d4e5f

HMAC-SHA512 signature in lowercase hex format generated using the exchange's clientSecret. Payload format: "METHOD|PATH|BODY|X-Timestamp" where METHOD is the HTTP method, PATH is the request path (no host/query), BODY is the raw request body, and X-Timestamp is the same header value.

X-Timestamp
required
string
Example: 1760599371260

Unix timestamp in milliseconds used in signature payload

Request Body schema: application/json
required
request_id
string

Optional unique identifier generated by client for idempotency

payload_type
required
string
Value: "transactions-fiat-v1"

Payload type identifier, must be "transactions-fiat-v1"

request_ts_ms
required
integer <int64>

UNIX timestamp in milliseconds when client initiates request

required
Array of objects (FiatTransactionPayload) [ 1 .. 100 ] items

Array of transaction objects (maximum 100 per request)

Responses

Request samples

Content type
application/json
Example
{
  • "request_id": "05ca8afa-3912-4e2c-bdbb-5cb254b2b6db",
  • "payload_type": "transactions-fiat-v1",
  • "request_ts_ms": 1760599371260,
  • "payload": {
    }
}

Response samples

Content type
application/json
{
  • "timestamp": 1760662221648,
  • "request_id": "5023ed3d-321b-4b84-b1b1-d29bd4f4566f",
  • "code": 200,
  • "message": "SUCCESS",
  • "data": { }
}

Changelog

v1.0.1 — 2026-05-20

  • Added include_fee boolean field to FiatTransactionPayload to indicate whether the transaction amount already includes the transfer fee
  • Added fiat_partner field to capture the fiat payment partner used by the exchange (e.g. XENDIT, DOKU)
  • Added fiat_partner_trx_id field for payment partner transaction reference tracking
  • Renamed provider_trx_id field clarification — use fiat_partner_trx_id for partner-level reference

v1.0.0 — Initial Release

  • Fiat deposit and withdrawal transaction reporting for exchanges
  • Batch processing support (up to 100 transactions per request)
  • transactions-fiat-v1 envelope payload format with payload_type discriminator
  • Support for TRANSFER, VIRTUAL_ACCOUNT, EWALLET, and QRIS transaction channels
  • HMAC-SHA512 request signature authentication (X-Api-Key, X-Signature, X-Timestamp)
  • Optional metadata support via typed key-value pairs (string, number, boolean)
  • Idempotency support via client-generated request_id