# transactions_encode

## Overview

Encode a transaction into BCS (Binary Canonical Serialization) bytes ready for signing. This endpoint is the bridge between transaction construction and offline signing workflows. It takes a complete transaction object (without signature) and returns the canonical byte representation that must be signed to produce a valid signed transaction.

## Endpoint

`POST /v1/transactions/encode_submission`

## Request Parameters

- `sender` (`string, required`): Request Body: 0x-prefixed account address of the signer
- `sequence_number` (`string, required`): Request Body: Next sequence number for the sender account
- `max_gas_amount` (`string, required`): Request Body: Maximum gas units the sender is willing to pay
- `gas_unit_price` (`string, required`): Request Body: Price per gas unit in octas
- `expiration_timestamp_secs` (`string, required`): Request Body: Unix timestamp after which the transaction expires
- `payload` (`object, required`): Request Body: Transaction payload (entry_function_payload, script_payload, etc.)

## Request Example

```json
{
  "sender": "0x1a2b3c...",
  "sequence_number": "42",
  "max_gas_amount": "2000",
  "gas_unit_price": "100",
  "expiration_timestamp_secs": "1700000120",
  "payload": {
    "type": "entry_function_payload",
    "function": "0x1::aptos_account::transfer",
    "arguments": ["0x2a3b4c...", "1000000"]
  }
}
```

## Response Fields

- `result` (`OBJECT, required`): ### Success Response (200) Returns the BCS-encoded transaction bytes as a hex string: ```json "0xb5e97db07fa0bd0e5598aa3643a9bc6f6693bddc1a9fec9e674a461eaa00b193..." ``` These bytes represent the signing message. Sign them with the sender's private key to produce a valid signature. ### Error Responses | Status | Error Code | Description | | -- | -- | -- | | 400 | invalid_input | Invalid transaction format or missing required fields | | 400 | invalid_payload | Payload doesn't conform to entry function or script requirements | | 400 | function_not_found | The specified Move function does not exist on-chain | | 400 | type_error | Type arguments don't match the function signature |

## Successful Response

```json
"0xb5e97db07fa0bd0e5598aa3643a9bc6f6693bddc1a9fec9e674a461eaa00b193..."
```

## Error Responses

### Error 1

- Code: `invalid_input`
- Description: Invalid transaction format or missing required fields

### Error 2

- Code: `invalid_payload`
- Description: Payload doesn't conform to entry function or script requirements

### Error 3

- Code: `function_not_found`
- Description: The specified Move function does not exist on-chain

### Error 4

- Code: `type_error`
- Description: Type arguments don't match the function signature

## Code Examples

cURL
Python
TypeScript
Rust

```bash
curl -s -X POST "https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1/transactions/encode_submission" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": "0x1a2b3c...",
    "sequence_number": "42",
    "max_gas_amount": "2000",
    "gas_unit_price": "100",
    "expiration_timestamp_secs": "1700000120",
    "payload": {
      "type": "entry_function_payload",
      "function": "0x1::aptos_account::transfer",
      "arguments": ["0x2a3b4c...", "1000000"]
    }
  }'
```

```python
from aptos_sdk.client import RestClient
from aptos_sdk.account import Account

client = RestClient("https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1")
account = Account.load_key("your_private_key_hex")

# Step 1: Build transaction object
raw_txn = {
    "sender": str(account.address()),
    "sequence_number": str(client.account_sequence_number(account.address())),
    "max_gas_amount": "2000",
    "gas_unit_price": "100",
    "expiration_timestamp_secs": str(int(time.time()) + 120),
    "payload": {
        "type": "entry_function_payload",
        "function": "0x1::aptos_account::transfer",
        "arguments": ["0x2a3b4c...", "1000000"]
    }
}

# Step 2: Encode for signing
encoded = client.encode_submission(raw_txn)

# Step 3: Sign the encoded bytes
to_sign = bytes.fromhex(encoded[2:])  # Remove 0x prefix
signature = account.sign(to_sign)

# Step 4: Submit with signature
raw_txn["signature"] = {
    "type": "ed25519_signature",
    "public_key": str(account.public_key()),
    "signature": str(signature)
}
result = client.submit_transaction(raw_txn)
```

```typescript
import { Aptos, AptosConfig, Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";

const config = new AptosConfig({
  fullnode: "https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1"
});
const aptos = new Aptos(config);

// The TypeScript SDK handles encoding internally
// For manual encoding via REST:
const response = await fetch(
  "https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1/transactions/encode_submission",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      sender: "0x1a2b3c...",
      sequence_number: "42",
      max_gas_amount: "2000",
      gas_unit_price: "100",
      expiration_timestamp_secs: String(Math.floor(Date.now() / 1000) + 120),
      payload: {
        type: "entry_function_payload",
        function: "0x1::aptos_account::transfer",
        arguments: ["0x2a3b4c...", "1000000"]
      }
    })
  }
);
const encodedHex = await response.json();
// Sign encodedHex with your signing mechanism
```

```rust
use aptos_sdk::rest_client::Client;
use serde_json::json;

let client = Client::new("https://api-aptos-mainnet.n.dwellir.com/YOUR_API_KEY/v1".parse()?);

let txn = json!({
    "sender": "0x1a2b3c...",
    "sequence_number": "42",
    "max_gas_amount": "2000",
    "gas_unit_price": "100",
    "expiration_timestamp_secs": "1700000120",
    "payload": {
        "type": "entry_function_payload",
        "function": "0x1::aptos_account::transfer",
        "arguments": ["0x2a3b4c...", "1000000"]
    }
});

let encoded = client.encode_submission(&txn).await?;
// Sign the encoded bytes with your key management system
```

## Encoding Workflow

The complete encode-sign-submit workflow:

```
1. GET /v1/accounts/{address}          → sequence_number
2. GET /v1/estimate_gas_price          → gas_unit_price
3. Build transaction JSON              → raw transaction object
4. POST /v1/transactions/encode_submission → BCS-encoded bytes
5. Sign encoded bytes (offline)        → signature
6. POST /v1/transactions               → submit signed transaction
7. GET /v1/transactions/by_hash/{hash} → confirm execution
```

This separation enables secure signing workflows where the signing key never touches a networked machine.

## Use Cases

1. **Offline Signing**: Encode transactions on an online machine, transfer encoded bytes to an air-gapped signing device, then return signatures for submission. This is the gold standard for securing high-value operations.

2. **Hardware Wallet Integration**: Send encoded transaction bytes to hardware wallets (Ledger, Trezor) for signing, maintaining security while using blockchain APIs for transaction construction.

3. **Multi-Step Approval Workflows**: Separate transaction construction, review, approval, and signing into distinct steps for organizational governance. Each step can be handled by different systems or personnel.

4. **Cross-Platform Signing**: Encode on a server (web API) and sign on a different platform (mobile app, desktop wallet) without requiring the full Aptos SDK on both sides.

5. **Transaction Inspection**: Encode transactions to verify their exact on-chain representation before signing. Compare encoded bytes against expected values for audit and verification.

6. **Custodial Architectures**: In custodial wallet systems, the hot system builds and encodes transactions while the cold signing system only handles encoded bytes and produces signatures.

## Best Practices

**Complete Transaction Fields**: Include all required fields: sender, sequence\_number, max\_gas\_amount, gas\_unit\_price, expiration\_timestamp\_secs, and payload. Missing fields cause encoding failures.

**Sequence Number Management**: Fetch the latest sequence number from `GET /v1/accounts/{address}` immediately before encoding to avoid conflicts with concurrent transactions.

**Expiration Timestamps**: Set `expiration_timestamp_secs` to current time + 60-120 seconds. Factor in the time needed for the signing round trip when using offline signing -- add extra time for hardware wallet interactions.

**Chain ID Verification**: The encoding implicitly uses the node's chain ID. Ensure you are encoding against the correct network (mainnet vs testnet) to prevent cross-network issues.

**Byte Handling**: The returned hex string is 0x-prefixed. Remove the `0x` prefix before converting to byte arrays for signing. Most signing libraries expect raw bytes, not hex strings.

**Encoding Validation**: After encoding, optionally decode the bytes client-side to verify correctness before sending to signing devices. This catches errors before they reach expensive hardware signing steps.

## Security Considerations

Encoding itself does not involve cryptographic keys or sensitive data. However, the encoded bytes represent a transaction ready for signing -- treat them as sensitive in the following ways:

- **Verify before signing**: Always display or log the human-readable transaction details alongside encoded bytes so signers can verify what they are approving.
- **Secure transport**: When transmitting encoded bytes to signing devices, use authenticated channels to prevent man-in-the-middle modification.
- **Tamper detection**: Any modification to the encoded bytes produces a different signature that will be rejected by the network, providing built-in tamper evidence.

## Performance Considerations

Encoding is a fast, computational operation that validates the transaction against on-chain state (verifying the function exists, types match, etc.) but does not execute it. Response times are typically 20-50ms, dominated by network latency rather than encoding overhead.

Encoded transaction sizes vary:

- Simple transfers: 100-200 bytes
- Smart contract calls: 300-1,000 bytes
- Complex multi-agent transactions: 1-5KB

These sizes are negligible for modern networks but matter for hardware wallet display limitations and QR code encoding use cases.

## Related Endpoints

- `/v1/transactions` - Submit the signed transaction
- `/v1/transactions/simulate` - Simulate before encoding and signing
- `/v1/accounts/{address}` - Get current sequence number
- `/v1/estimate_gas_price` - Get gas price for transaction building
- `/v1/transactions/by_hash/{hash}` - Check submitted transaction status
