> For the complete documentation index, see [llms.txt](https://docs.tylt.money/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tylt.money/tylt-embedded-wallet-service/transactions.md).

# Transactions

The Wallet Transactions APIs allow merchants to enable end users to:

* Receive crypto-assets through blockchain wallet addresses
* Send crypto-assets to external blockchain addresses
* Transfer crypto-assets internally to another user within the same merchant group
* Submit Travel Rule counterparty information where required

All requests must be made from the merchant’s secure backend. API credentials must never be exposed in a browser or mobile application.

### Available APIs

| Transaction Type  | Method | Endpoint                                            | Purpose                                                 |
| ----------------- | ------ | --------------------------------------------------- | ------------------------------------------------------- |
| Receive Crypto    | `GET`  | `/whitelabel/wallet/getWalletAddress`               | Retrieve an end user’s blockchain deposit address       |
| Send Crypto       | `POST` | `/whitelabel/wallet/payout`                         | Send crypto to an external blockchain address           |
| Internal Transfer | `POST` | `/whitelabel/wallet/internalTransfer`               | Transfer crypto to another user under the same merchant |
| Travel Rule       | `POST` | `/whitelabel/compliance/travelRule/addCounterparty` | Submit beneficiary or counterparty information          |

***

## Transaction Security Requirements

Wallet transaction requests are subject to additional authentication and security controls.

### Read-Only Requests

The wallet-address endpoint requires:

* API key authentication
* HMAC-SHA256 signature
* IP whitelisting
* End-user resolution
* Approved KYC
* An active and unsuspended end-user account

### Mutating Requests

The following endpoints are mutating requests:

```http
POST /whitelabel/wallet/payout
POST /whitelabel/wallet/internalTransfer
POST /whitelabel/compliance/travelRule/addCounterparty
```

These requests require:

* API key authentication
* HMAC-SHA256 signature
* IP whitelisting
* End-user resolution
* Approved KYC
* Replay protection
* Email OTP
* Authenticator-app TOTP
* An active and unsuspended end-user account

The complete request body must be included when generating the HMAC signature.

***

## End-User Identification

Each wallet request must identify the end user using one of the following fields:

| Field            | Description                               |
| ---------------- | ----------------------------------------- |
| `endUserEmail`   | The end user’s registered email address   |
| `endUserId`      | The Tylt end-user ID                      |
| `externalUserId` | The merchant’s own unique user identifier |

The recommended identifier is `externalUserId`.

Example:

```json
{
  "externalUserId": "user-10021"
}
```

A client-supplied `merchantId` is ignored or removed by Tylt to prevent cross-merchant access.

***

## Transaction Authorization

Before submitting a payout or internal transfer, the merchant must request a transaction OTP.

### Request Transaction OTP

```http
GET /whitelabel/auth/sendTransactionOTP
```

The request must include one end-user identifier.

Example query:

```http
GET /whitelabel/auth/sendTransactionOTP?externalUserId=user-10021
```

The email OTP is sent directly to the end user’s registered email address.

The merchant’s interface must then collect:

* The email OTP
* The end user’s Authenticator-app TOTP

These values must be included in the signed transaction request:

```json
{
  "emailCode": "123456",
  "googleAuthCode": "654321"
}
```

The merchant cannot generate or replace the end user’s Authenticator code.

***

## Replay Protection

All mutating transaction requests must include:

```json
{
  "timestamp": 1700000000000,
  "nonce": "unique-random-request-id"
}
```

### Replay-Protection Fields

| Field       | Type   | Required | Description                            |
| ----------- | ------ | -------: | -------------------------------------- |
| `timestamp` | Number |      Yes | Current epoch time in milliseconds     |
| `nonce`     | String |      Yes | Unique value generated for the request |

The timestamp must be within 120 seconds of Tylt’s server time.

A nonce must not be reused within the replay-protection window.

The HMAC signature must be calculated over the complete body, including:

* End-user identifier
* Transaction fields
* `timestamp`
* `nonce`
* `emailCode`
* `googleAuthCode`

***
