Before ingesting operations, make sure the related clients have already been ingested. See the Ingesting Clients guide.
Step 1: Ingest Deposits
Deposits represent incoming funds (crypto or fiat) into client accounts. Endpoint:POST /v1/operations/deposits
POST /v1/operations/deposits?upsert=true
Content-Type: application/json
{
"referenceId": "DEP-2024-001",
"initiatedBy": "123e4567-e89b-12d3-a456-426614174000",
"initiatedAt": "2024-01-15T08:30:00Z",
"depositTransaction": {
"referenceId": "TX-BLOCK-888",
"txHash": "0x123abc...",
"amount": {
"amount": 1.5,
"currency": "BTC",
"netAmount": 1.5
},
"convertedAmount": {
"amount": 65000.00,
"currency": "USD"
},
"from": {
"walletAddress": "0xSourceWalletAddress..."
},
"to": {
"walletAddress": "0xYourDepositAddress..."
},
"blockchainNetworkId": "bitcoin-mainnet",
"statusHistory": [
{
"type": "SUCCESS",
"timestamp": "2024-01-15T08:30:00Z"
}
]
}
}
const deposit = await corsa.deposits.createDeposit(
{
referenceId: "DEP-2024-001",
initiatedBy: "123e4567-e89b-12d3-a456-426614174000",
initiatedAt: "2024-01-15T08:30:00Z",
depositTransaction: {
referenceId: "TX-BLOCK-888",
txHash: "0x123abc...",
amount: {
amount: 1.5,
currency: "BTC",
netAmount: 1.5,
},
convertedAmount: {
amount: 65000.0,
currency: "USD",
},
from: {
walletAddress: "0xSourceWalletAddress...",
},
to: {
walletAddress: "0xYourDepositAddress...",
},
blockchainNetworkId: "bitcoin-mainnet",
statusHistory: [
{
type: "SUCCESS",
timestamp: "2024-01-15T08:30:00Z",
},
],
},
},
true // upsert
);
from corsa_sdk.api.deposits.create_deposit import _get_kwargs
from corsa_sdk.models.create_deposit_operation_dto import CreateDepositOperationDto
resp = http.request(**_get_kwargs(
body=CreateDepositOperationDto(
reference_id="DEP-2024-001",
initiated_by="123e4567-e89b-12d3-a456-426614174000",
initiated_at="2024-01-15T08:30:00Z",
deposit_transaction={
"referenceId": "TX-BLOCK-888",
"txHash": "0x123abc...",
"amount": {"amount": 1.5, "currency": "BTC", "netAmount": 1.5},
"convertedAmount": {"amount": 65000.00, "currency": "USD"},
"from": {"walletAddress": "0xSourceWalletAddress..."},
"to": {"walletAddress": "0xYourDepositAddress..."},
"blockchainNetworkId": "bitcoin-mainnet",
"statusHistory": [{"type": "SUCCESS", "timestamp": "2024-01-15T08:30:00Z"}],
},
),
upsert=True,
))
deposit = resp.json()
initiatedBy field should reference the Corsa client id of the client who initiated the deposit.
Set
evaluateSynchronously: true on the transaction object (depositTransaction, withdrawTransaction, or items in a trade’s transactions array) to evaluate the transaction against your active monitoring rules during ingestion. The response will include an evaluationResult with the decision. See Halting transactions for details and response format.Step 2: Ingest Withdrawals
Withdrawals represent outgoing funds (crypto or fiat) from client accounts. Endpoint:POST /v1/operations/withdrawals
Fiat Withdrawal
POST /v1/operations/withdrawals?upsert=true
Content-Type: application/json
{
"referenceId": "WDR-FIAT-2024-005",
"initiatedBy": "123e4567-e89b-12d3-a456-426614174000",
"initiatedAt": "2024-01-16T14:20:00Z",
"withdrawTransaction": {
"referenceId": "TX-BANK-999",
"amount": {
"amount": 5000,
"currency": "USD"
},
"to": {
"bankAccountNumber": "1234567890"
},
"paymentMethod": "WIRE_TRANSFER",
"statusHistory": [
{
"type": "PENDING",
"timestamp": "2024-01-16T14:20:00Z"
}
]
}
}
const withdrawal = await corsa.withdrawals.createWithdrawal(
{
referenceId: "WDR-FIAT-2024-005",
initiatedBy: "123e4567-e89b-12d3-a456-426614174000",
initiatedAt: "2024-01-16T14:20:00Z",
withdrawTransaction: {
referenceId: "TX-BANK-999",
amount: {
amount: 5000,
currency: "USD",
},
to: {
bankAccountNumber: "1234567890",
},
paymentMethod: "WIRE_TRANSFER",
statusHistory: [
{
type: "PENDING",
timestamp: "2024-01-16T14:20:00Z",
},
],
},
},
true // upsert
);
from corsa_sdk.api.withdrawals.create_withdrawal import _get_kwargs
from corsa_sdk.models.create_withdrawal_operation_dto import CreateWithdrawalOperationDto
resp = http.request(**_get_kwargs(
body=CreateWithdrawalOperationDto(
reference_id="WDR-FIAT-2024-005",
initiated_by="123e4567-e89b-12d3-a456-426614174000",
initiated_at="2024-01-16T14:20:00Z",
withdraw_transaction={
"referenceId": "TX-BANK-999",
"amount": {"amount": 5000, "currency": "USD"},
"to": {"bankAccountNumber": "1234567890"},
"paymentMethod": "WIRE_TRANSFER",
"statusHistory": [{"type": "PENDING", "timestamp": "2024-01-16T14:20:00Z"}],
},
),
upsert=True,
))
withdrawal = resp.json()
Crypto Withdrawal
POST /v1/operations/withdrawals?upsert=true
Content-Type: application/json
{
"referenceId": "WDR-2024-005",
"initiatedBy": "123e4567-e89b-12d3-a456-426614174000",
"initiatedAt": "2024-01-16T14:20:00Z",
"withdrawTransaction": {
"referenceId": "TX-BLOCK-999",
"txHash": "0x456def...",
"amount": {
"amount": 5000,
"currency": "USDC"
},
"to": {
"walletAddress": "0xDestWalletAddress..."
},
"blockchainNetworkId": "ethereum-mainnet",
"statusHistory": [
{
"type": "PENDING",
"timestamp": "2024-01-16T14:20:00Z"
}
]
}
}
const withdrawal = await corsa.withdrawals.createWithdrawal(
{
referenceId: "WDR-2024-005",
initiatedBy: "123e4567-e89b-12d3-a456-426614174000",
initiatedAt: "2024-01-16T14:20:00Z",
withdrawTransaction: {
referenceId: "TX-BLOCK-999",
txHash: "0x456def...",
amount: {
amount: 5000,
currency: "USDC",
},
to: {
walletAddress: "0xDestWalletAddress...",
},
blockchainNetworkId: "ethereum-mainnet",
statusHistory: [
{
type: "PENDING",
timestamp: "2024-01-16T14:20:00Z",
},
],
},
},
true // upsert
);
resp = http.request(**_get_kwargs(
body=CreateWithdrawalOperationDto(
reference_id="WDR-2024-005",
initiated_by="123e4567-e89b-12d3-a456-426614174000",
initiated_at="2024-01-16T14:20:00Z",
withdraw_transaction={
"referenceId": "TX-BLOCK-999",
"txHash": "0x456def...",
"amount": {"amount": 5000, "currency": "USDC"},
"to": {"walletAddress": "0xDestWalletAddress..."},
"blockchainNetworkId": "ethereum-mainnet",
"statusHistory": [{"type": "PENDING", "timestamp": "2024-01-16T14:20:00Z"}],
},
),
upsert=True,
))
withdrawal = resp.json()
Step 3: Ingest Trades
Trades represent exchange operations between two assets. They can be ingested in two ways:- Atomic Ingestion - Send the entire trade with all its transactions in a single request.
- Incremental Ingestion (Fills) - Send parts of the trade as separate requests that get grouped into the same trade entity.
POST /v1/operations/trades
Atomic Ingestion
Send the full trade with all transactions at once:POST /v1/operations/trades
Content-Type: application/json
{
"referenceId": "TRADE-100",
"initiatedBy": "123e4567-e89b-12d3-a456-426614174000",
"initiatedAt": "2024-01-17T10:00:00Z",
"tradeType": "BUY",
"instrumentBaseAsset": "BTC",
"instrumentQuoteAsset": "USD",
"price": 60000,
"quantity": 1,
"status": "SUCCESS",
"transactions": [
{
"referenceId": "TX-FILL-1",
"initiatedAt": "2024-01-17T10:00:00Z",
"amount": { "amount": 0.4, "currency": "BTC" },
"paymentMethod": "CRYPTO_TRANSFER",
"statusHistory": [{ "type": "SUCCESS", "timestamp": "2024-01-17T10:00:00Z" }]
},
{
"referenceId": "TX-FILL-2",
"initiatedAt": "2024-01-17T10:00:05Z",
"amount": { "amount": 0.6, "currency": "BTC" },
"paymentMethod": "CRYPTO_TRANSFER",
"statusHistory": [{ "type": "SUCCESS", "timestamp": "2024-01-17T10:00:05Z" }]
}
]
}
const trade = await corsa.trades.createTrade({
referenceId: "TRADE-100",
initiatedBy: "123e4567-e89b-12d3-a456-426614174000",
initiatedAt: "2024-01-17T10:00:00Z",
tradeType: "BUY",
instrumentBaseAsset: "BTC",
instrumentQuoteAsset: "USD",
price: 60000,
quantity: 1,
status: "SUCCESS",
transactions: [
{
referenceId: "TX-FILL-1",
initiatedAt: "2024-01-17T10:00:00Z",
amount: { amount: 0.4, currency: "BTC" },
paymentMethod: "CRYPTO_TRANSFER",
statusHistory: [{ type: "SUCCESS", timestamp: "2024-01-17T10:00:00Z" }],
},
{
referenceId: "TX-FILL-2",
initiatedAt: "2024-01-17T10:00:05Z",
amount: { amount: 0.6, currency: "BTC" },
paymentMethod: "CRYPTO_TRANSFER",
statusHistory: [{ type: "SUCCESS", timestamp: "2024-01-17T10:00:05Z" }],
},
],
});
from corsa_sdk.api.trades.create_trade import _get_kwargs
from corsa_sdk.models.create_trade_operation_dto import CreateTradeOperationDto
resp = http.request(**_get_kwargs(
body=CreateTradeOperationDto(
reference_id="TRADE-100",
initiated_by="123e4567-e89b-12d3-a456-426614174000",
initiated_at="2024-01-17T10:00:00Z",
trade_type="BUY",
instrument_base_asset="BTC",
instrument_quote_asset="USD",
price=60000,
quantity=1,
status="SUCCESS",
transactions=[
{"referenceId": "TX-FILL-1", "initiatedAt": "2024-01-17T10:00:00Z", "amount": {"amount": 0.4, "currency": "BTC"}, "paymentMethod": "CRYPTO_TRANSFER", "statusHistory": [{"type": "SUCCESS", "timestamp": "2024-01-17T10:00:00Z"}]},
{"referenceId": "TX-FILL-2", "initiatedAt": "2024-01-17T10:00:05Z", "amount": {"amount": 0.6, "currency": "BTC"}, "paymentMethod": "CRYPTO_TRANSFER", "statusHistory": [{"type": "SUCCESS", "timestamp": "2024-01-17T10:00:05Z"}]},
],
),
))
trade = resp.json()
Incremental Ingestion (Fills)
UseshouldAppendToExistingTrade=true and the same referenceId to append transactions to an existing trade.
Request 1 (First Fill):
POST /v1/operations/trades?shouldAppendToExistingTrade=true
Content-Type: application/json
{
"referenceId": "TRADE-100",
"initiatedBy": "123e4567-e89b-12d3-a456-426614174000",
"initiatedAt": "2024-01-17T10:00:00Z",
"tradeType": "BUY",
"instrumentBaseAsset": "BTC",
"instrumentQuoteAsset": "USD",
"price": 60000,
"quantity": 1,
"status": "PENDING",
"transactions": [
{
"referenceId": "TX-FILL-1",
"initiatedAt": "2024-01-17T10:00:00Z",
"amount": { "amount": 0.4, "currency": "BTC" },
"paymentMethod": "CRYPTO_TRANSFER",
"statusHistory": [{ "type": "SUCCESS", "timestamp": "2024-01-17T10:00:00Z" }]
}
]
}
const trade = await corsa.trades.createTrade(
{
referenceId: "TRADE-100",
initiatedBy: "123e4567-e89b-12d3-a456-426614174000",
initiatedAt: "2024-01-17T10:00:00Z",
tradeType: "BUY",
instrumentBaseAsset: "BTC",
instrumentQuoteAsset: "USD",
price: 60000,
quantity: 1,
status: "PENDING",
transactions: [
{
referenceId: "TX-FILL-1",
initiatedAt: "2024-01-17T10:00:00Z",
amount: { amount: 0.4, currency: "BTC" },
paymentMethod: "CRYPTO_TRANSFER",
statusHistory: [{ type: "SUCCESS", timestamp: "2024-01-17T10:00:00Z" }],
},
],
},
true // shouldAppendToExistingTrade
);
resp = http.request(**_get_kwargs(
body=CreateTradeOperationDto(
reference_id="TRADE-100",
initiated_by="123e4567-e89b-12d3-a456-426614174000",
initiated_at="2024-01-17T10:00:00Z",
trade_type="BUY",
instrument_base_asset="BTC",
instrument_quote_asset="USD",
price=60000,
quantity=1,
status="PENDING",
transactions=[
{"referenceId": "TX-FILL-1", "initiatedAt": "2024-01-17T10:00:00Z", "amount": {"amount": 0.4, "currency": "BTC"}, "paymentMethod": "CRYPTO_TRANSFER", "statusHistory": [{"type": "SUCCESS", "timestamp": "2024-01-17T10:00:00Z"}]},
],
),
should_append_to_existing_trade=True,
))
trade = resp.json()
POST /v1/operations/trades?shouldAppendToExistingTrade=true
Content-Type: application/json
{
"referenceId": "TRADE-100",
"initiatedBy": "123e4567-e89b-12d3-a456-426614174000",
"initiatedAt": "2024-01-17T10:00:00Z",
"tradeType": "BUY",
"instrumentBaseAsset": "BTC",
"instrumentQuoteAsset": "USD",
"price": 60000,
"quantity": 1,
"status": "SUCCESS",
"transactions": [
{
"referenceId": "TX-FILL-2",
"initiatedAt": "2024-01-17T10:00:05Z",
"amount": { "amount": 0.6, "currency": "BTC" },
"paymentMethod": "CRYPTO_TRANSFER",
"statusHistory": [{ "type": "SUCCESS", "timestamp": "2024-01-17T10:00:05Z" }]
}
]
}
const trade = await corsa.trades.createTrade(
{
referenceId: "TRADE-100",
initiatedBy: "123e4567-e89b-12d3-a456-426614174000",
initiatedAt: "2024-01-17T10:00:00Z",
tradeType: "BUY",
instrumentBaseAsset: "BTC",
instrumentQuoteAsset: "USD",
price: 60000,
quantity: 1,
status: "SUCCESS",
transactions: [
{
referenceId: "TX-FILL-2",
initiatedAt: "2024-01-17T10:00:05Z",
amount: { amount: 0.6, currency: "BTC" },
paymentMethod: "CRYPTO_TRANSFER",
statusHistory: [{ type: "SUCCESS", timestamp: "2024-01-17T10:00:05Z" }],
},
],
},
true // shouldAppendToExistingTrade
);
resp = http.request(**_get_kwargs(
body=CreateTradeOperationDto(
reference_id="TRADE-100",
initiated_by="123e4567-e89b-12d3-a456-426614174000",
initiated_at="2024-01-17T10:00:00Z",
trade_type="BUY",
instrument_base_asset="BTC",
instrument_quote_asset="USD",
price=60000,
quantity=1,
status="SUCCESS",
transactions=[
{"referenceId": "TX-FILL-2", "initiatedAt": "2024-01-17T10:00:05Z", "amount": {"amount": 0.6, "currency": "BTC"}, "paymentMethod": "CRYPTO_TRANSFER", "statusHistory": [{"type": "SUCCESS", "timestamp": "2024-01-17T10:00:05Z"}]},
],
),
should_append_to_existing_trade=True,
))
trade = resp.json()
Step 4: Ingest Transfers
Transfers represent internal peer-to-peer movements of funds between two clients in your platform — for example, a user sending crypto or fiat to another user. Bothfrom.client and to.client are required on the transaction so Corsa can link the movement to both parties.
Endpoint: POST /v1/operations/transfers
POST /v1/operations/transfers?upsert=true
Content-Type: application/json
{
"referenceId": "TRF-2024-001",
"initiatedBy": "sender-client-uuid",
"initiatedAt": "2024-01-18T09:00:00Z",
"transferTransaction": {
"referenceId": "TX-TRF-001",
"amount": {
"amount": 500,
"currency": "USDC"
},
"convertedAmount": {
"amount": 500,
"currency": "USD"
},
"from": {
"client": "sender-client-uuid"
},
"to": {
"client": "recipient-client-uuid"
},
"blockchainNetworkId": "ethereum-mainnet",
"statusHistory": [
{
"type": "SUCCESS",
"timestamp": "2024-01-18T09:00:05Z"
}
]
}
}
const transfer = await corsa.transfers.createTransfer(
{
referenceId: "TRF-2024-001",
initiatedBy: "sender-client-uuid",
initiatedAt: "2024-01-18T09:00:00Z",
transferTransaction: {
referenceId: "TX-TRF-001",
amount: {
amount: 500,
currency: "USDC",
},
convertedAmount: {
amount: 500,
currency: "USD",
},
from: {
client: "sender-client-uuid",
},
to: {
client: "recipient-client-uuid",
},
blockchainNetworkId: "ethereum-mainnet",
statusHistory: [
{
type: "SUCCESS",
timestamp: "2024-01-18T09:00:05Z",
},
],
},
},
true // upsert
);
from corsa_sdk.api.transfers.create_transfer import _get_kwargs
from corsa_sdk.models.create_transfer_operation_dto import CreateTransferOperationDto
resp = http.request(**_get_kwargs(
body=CreateTransferOperationDto(
reference_id="TRF-2024-001",
initiated_by="sender-client-uuid",
initiated_at="2024-01-18T09:00:00Z",
transfer_transaction={
"referenceId": "TX-TRF-001",
"amount": {"amount": 500, "currency": "USDC"},
"convertedAmount": {"amount": 500, "currency": "USD"},
"from": {"client": "sender-client-uuid"},
"to": {"client": "recipient-client-uuid"},
"blockchainNetworkId": "ethereum-mainnet",
"statusHistory": [{"type": "SUCCESS", "timestamp": "2024-01-18T09:00:05Z"}],
},
),
upsert=True,
))
transfer = resp.json()
Unlike deposits and withdrawals, both
from.client and to.client are required on the transferTransaction. Both must reference Corsa client IDs that have already been ingested.Step 5: Update Operation & Transaction Statuses
As operations progress through their lifecycle, you can update their statuses.Available Statuses
Operation Statuses (Deposits, Withdrawals, Trades)
| Status | Description |
|---|---|
PENDING | The operation has been initiated but is not yet final. |
SUCCESS | The operation completed successfully. |
FAILED | The operation failed. |
REJECTED | The operation was rejected. |
EXPIRED | The operation expired (specific to time-bound operations). |
Transaction Statuses
| Status | Description |
|---|---|
PENDING | The transaction is processing. |
SUCCESS | The transaction was confirmed. |
FAILED | The transaction failed on-chain or during processing. |
CANCELLED | The transaction was cancelled. |
FROZEN | The transaction has been frozen. |
Updating a Trade Status
Endpoint:PUT /v1/operations/trades/{id}/updateStatus
PUT /v1/operations/trades/TRADE-100/updateStatus
Content-Type: application/json
{
"status": "SUCCESS",
"timestamp": "2024-01-17T10:05:00Z",
"reason": "Trade executed successfully",
"subStatus": "FILLED"
}
const updated = await corsa.trades.updateTradeStatus("TRADE-100", {
status: "SUCCESS",
timestamp: "2024-01-17T10:05:00Z",
reason: "Trade executed successfully",
subStatus: "FILLED",
});
from corsa_sdk.api.trades.update_trade_status import _get_kwargs
from corsa_sdk.models.operation_status_update_dto import OperationStatusUpdateDto
resp = http.request(**_get_kwargs(
id="TRADE-100",
body=OperationStatusUpdateDto(
status="SUCCESS",
timestamp="2024-01-17T10:05:00Z",
reason="Trade executed successfully",
sub_status="FILLED",
),
))
updated = resp.json()
Updating a Transaction Status
Endpoint:PUT /v1/transactions/{id}/updateStatus
PUT /v1/transactions/TX-FILL-1/updateStatus
Content-Type: application/json
{
"type": "SUCCESS",
"timestamp": "2024-01-17T10:05:00Z",
"reason": "Blockchain confirmation received",
"subStatus": "CONFIRMED_6_BLOCKS"
}
await corsa.transactions.updateTransactionStatus("TX-FILL-1", {
type: "SUCCESS",
timestamp: "2024-01-17T10:05:00Z",
reason: "Blockchain confirmation received",
subStatus: "CONFIRMED_6_BLOCKS",
});
from corsa_sdk.api.transactions.update_transaction_status import _get_kwargs
from corsa_sdk.models.transaction_status_dto import TransactionStatusDto
resp = http.request(**_get_kwargs(
id="TX-FILL-1",
body=TransactionStatusDto(
type="SUCCESS",
timestamp="2024-01-17T10:05:00Z",
reason="Blockchain confirmation received",
sub_status="CONFIRMED_6_BLOCKS",
),
))
What’s Next?
With clients and operations ingested, you can now set up alerting and case management.Ingest Alerts & Cases
Push external alerts and escalate them to investigation cases.
Ingesting Clients
Review the client ingestion guide.