# Payout Callbacks

To receive callbacks make sure you registered your URLs on [AkashicPay.com](https://akashic-1.gitbook.io/akashicpay/sdk/terminology#akashicpay.com). You can receive callbacks for transactions in the "Pending", "Confirmed", and "Failed" status. We recommend setting all three, though you could skip "Pending" if desired. Only transactions with "Confirmed" or "Failed" status are final.

Note: If the response to the callback has a status code >= 400, the callback is retried up to 15 times with increasing delays up to around 10hrs since the first attempt.

Note: `l2Txnhash` (the "L2-hash") should always be used as the unique identifier of a transaction. This is a unique transaction-hash for any transaction on [AkashicChain](/introduction/terminology.md#akashicchain). It is present for Confirmed deposits and Pending/Confirmed payouts. This is particularly important for the case of [Layer 2](/introduction/terminology.md#layer-2) transactions, which will not have a Layer 1 hash (`txHash`).

> **Note:** When retrying a callback, the request will be sent only to the callback URL that was configured at the time the original callback was created. Any newly added callback URLs, or changes made to existing callback URLs after the initial attempt, will not be used during the retry process.

> **Note:** While we aim for stability and consistency at Akashic, we cannot guarantee that the below object remains unchanged. For example, new features might necessitate additional fields in the callback. We will however aim to not remove existing fields. For convenience, we recommend filtering and handling the callback as per your needs while being open to the possibility of future additions.

## <mark style="color:blue;">Example</mark>

### <mark style="color:blue;">Pending Payout (L1Transaction)</mark>

```json
 {
  "fromAddress": "TTVkK6hGoAFhALG9NTkUDHjcFFXKmWcScU", // sending wallet/account of transaction
  "toAddress": "TQH8ygbS8BAnzSQ9uxR9vXHJYMQVRvbgPg", // receiving wallet/account of transaction
  "layer": "L1Transaction", // 'L1Transaction' or 'L2Transaction'
  "initiatedAt": "2024-08-19T10:02:54.000Z", // ISO8601 format
  "amount": "1.000000",  // Amount sent
  "coinSymbol": "TRX", // NetworkSymbol, e.g. 'ETH' or 'TRX'
  "status": "Confirmed", // TransactionStatus. 'Pending', 'Confirmed', or 'Failed'
  "txHash": "28a9880ad2ef3b7be1c40763128ec9630ab74e4749a3c81037c3501e4209bfcc", // Network's hash if L1. Not present for L2
  "feesEstimate": "6.114654", // Gas fee estimated by Akashic. Not present for L2
  "l2TxnHash": "ASe7eb1cb8193787040fcffa02a224a6ced7415ff2205343c0ab661e898e8d6eef", // Akashic Transaction Hash. For both L1 and L2 
  "senderInfo": {
    "identity": "ASbb8efead2d5ff2f618a85895bac8e8ac1bae236d4d730bf113400b7e6f108ca5", // Akashic Address of sender
  },
  "senderIdentity": "ASbb...", // DEPRECATED. Same as above. Please use senderInfo.identity instead
  "tokenSymbol": "USDT", // TokenSymbol. Present only if token-transaction
  "internalFee": {
    "withdraw": "0.100000"
  }, // Akashic Fee { deposit?: string, withdraw?: string}
   "referenceId": "tx123", // txn-identifier
   "feeIsDelegated": false, // Whether L1 gas fees were paid using token instead of native coin
   "directResolution": false // true if the transaction was never registered in the "Pending" state
}
```

### <mark style="color:blue;">Payout (L1Transaction)</mark>

```json
  {
  "fromAddress": "TTVkK6hGoAFhALG9NTkUDHjcFFXKmWcScU", // sending wallet/account of transaction
  "toAddress": "TQH8ygbS8BAnzSQ9uxR9vXHJYMQVRvbgPg", // receiving wallet/account of transaction
  "layer": "L1Transaction", // 'L1Transaction' or 'L2Transaction'
  "initiatedAt": "2024-08-19T10:02:54.000Z", // ISO8601 format
  "confirmedAt": "2024-08-19T10:04:02.000Z", // Only present if status is 'Confirmed' or 'Failed'
  "amount": "1.000000",  // Amount sent
  "coinSymbol": "TRX", // NetworkSymbol, e.g. 'ETH' or 'TRX'
  "status": "Confirmed", // TransactionStatus. 'Pending', 'Confirmed', or 'Failed'
  "txHash": "28a9880ad2ef3b7be1c40763128ec9630ab74e4749a3c81037c3501e4209bfcc", // Network's hash if L1. Not present for L2
  "feesEstimate": "6.114654", // Gas fee estimated by Akashic. Not present for L2
  "feesPaid": "5.822220", // Gas Fee paid on network. Not present for L2
  "l2TxnHash": "ASe7eb1cb8193787040fcffa02a224a6ced7415ff2205343c0ab661e898e8d6eef", // Akashic Transaction Hash. For both L1 and L2 
  "senderInfo": {
    "identity": "ASbb8efead2d5ff2f618a85895bac8e8ac1bae236d4d730bf113400b7e6f108ca5", // Akashic Address of sender
  },
  "senderIdentity": "ASbb...", // DEPRECATED. Same as above. Please use senderInfo.identity instead
  "tokenSymbol": "USDT", // TokenSymbol. Present only if token-transaction
  "internalFee": {
    "withdraw": "0.100000"
  }, // Akashic Fee { deposit?: string, withdraw?: string}
   "referenceId": "tx123", // txn-identifier
   "feeIsDelegated": false, // Whether L1 gas fees were paid using token instead of native coin
   "directResolution": false // true if the transaction was never registered in the "Pending" state
}

```

For a pending transaction, `feesPaid` and `confirmedAt` are not know yet and thus not present.&#x20;

#### *<mark style="color:blue;">**A note on withdrawal fees**</mark>*

There are a few different components in play regarding fees when doing a withdrawal. These are:&#x20;

* Akashic Fee (`internalFee.withdraw` in callback), *always* in the *same currency* as the transaction. I.e. ETH for an ETH transfer, USDT for a USDT transfer, USDC for a USDC transfer, etc. **Normally 0 unless "fee delegation" happens, see below.**&#x20;
* [Gas Fee](/introduction/terminology.md#fees-gas) (`feesPaid` in callback), always in [native coin](/introduction/terminology.md#coins) (e.g. ETH for a ERC20 USDT and USDC transfer, TRX for a TRC20 USDT transfer, BNB for a BEP20 USDT and USDC transfer, etc.). Charged by the [L1 networks ](/introduction/terminology.md#layer-1)(Ethereum, Tron, BNB Smart Chain (BSC), Solana, etc.)
* "Fee Delegation". The Akashic system lets you pay for the aforementioned native fee in tokens instead of native coin to simplify matters. If this is done, `feeIsDelegated` will be `true` in the callback. All withdrawals done using the SDK should be "delegated" while withdrawals initating from [AkashicLink](/introduction/terminology.md#akashiclink) will not by default. The extra token-amount needed to "delegate" the fee is in `internalFee.withdraw`&#x20;

Using this, to calculate the total amount spent by a user we can do (assuming callback data of the form shown above is in `txCallback`):

<pre class="language-typescript"><code class="lang-typescript"><strong>// Token transaction (USDT)
</strong><strong>if (txCallback.tokenSymbol) {
</strong><strong>    userTokenSpent = txCallback.amount + txCallback.internalFee.withdraw;
</strong><strong>    // If fee is not delegated, gas fees are paid in native coin
</strong><strong>    if (!feeIsDelegated) {
</strong><strong>        userNativeCoinSpent = txCallback.feesPaid;
</strong><strong>    }
</strong><strong>} else {
</strong>// Coin transaction (ETH, TRX)
<strong>    userNativeCoinSpent = txCallback.amount + txCallback.internalFee.withdraw 
</strong><strong>        + txCallback.feesPaid;
</strong><strong>}
</strong><strong>
</strong></code></pre>

Note that the above is pseudocode. You would probably need to take extra care of handling potential undefined/null values like `internalFee` as well as parse the numbers safely and correctly, following normal practices in your chosen programming language.

### <mark style="color:blue;">Payout (L2Transaction)</mark>

If user is sending assets to another user in the Akashic system, it will be executed in [AkashicChain](/introduction/terminology.md#akashicchain), which is our Layer 2 blockchain to reduce the gas fee and cost in Layer 1.&#x20;

```json
{
  "initiatedAt": "2024-08-19T10:03:58.649Z",
  "confirmedAt": "2024-08-19T10:03:58.649Z",
  "fromAddress": "AS3ce733d2af1ee530e0e85bd7de45c59626b28f95ac2d8e83a0685a70aac9b764", // Same as senderIdentity
  "toAddress": "AS188689e48494c8a452683587138f209d673aada204cb23393140e7f40280e0c5", // Same as receiverIdentity
  "coinSymbol": "TRX-SHASTA",
  "status": "Confirmed", // "Confirmed" or "Failed"
  "layer": "L2Transaction", // Could be "L2Transaction" here
  "amount": "10.000000",
  "internalFee": {
    "withdraw": "0.100000" // Akashic-fee, not present if Failed
  },
  "l2TxnHash": "ASe7eb1cb8193787040fcffa02a224a6ced7415ff2205343c0ab661e898e8d6eef", // AkashicChain txHash
  "receiverInfo": {
    "identity": "AS188689e48494c8a452683587138f209d673aada204cb23393140e7f40280e0c5", // Akashic Address of receiver
  },
  "receiverIdentity": "AS18...", // DEPRECATED. Same as above. Please use receiverInfo.identity instead
  "tokenSymbol": "USDT", // Only here if a token-transaction,
  "referenceId": "tx123",
  "senderInfo": {
    "identity": "AS3ce733d2af1ee530e0e85bd7de45c59626b28f95ac2d8e83a0685a70aac9b764", // Akashic Address of sender
  },
  "senderIdentity": "AS3c..." // DEPRECATED. Same as above. Please use senderInfo.identity instead
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akashicpay.com/callbacks/payout-callbacks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
