Skip to Content
Quickstart

Quickstart

1. Get Your Credentials

Contact the Movement team to receive:

  • Bearer Token - For authentication
  • Signing Secret - For request signatures
  • API Endpoint - Your API URL (https://YOUR_API_DOMAIN)

Important: Testnet and mainnet use different bearer tokens and signing secrets. Request separate credentials for each environment.

2. Make Your First Request

All requests require a bearer token. Airdrop requests also require a request signature. Here’s a complete example:

# Note: You'll need to generate the X-Signature header (see step 4) # The network (mainnet/testnet) is determined by your bearer token curl -X POST https://YOUR_API_DOMAIN/api/airdrop \ -H "Authorization: Bearer YOUR_BEARER_TOKEN" \ -H "X-Signature: v1,t=1700000000,s=abc123..." \ -H "Content-Type: application/json" \ -d '{ "address": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", "amount": "10", "uniqueHash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2" }'

Expected Response

{ "success": true, "transactionHash": "0xabc123def456...", "recipientAddress": "0x1234567890abcdef...", "amount": "10", "timestamp": "2025-11-18T12:00:00Z", "uniqueHash": "a1b2c3d4..." }

3. Generate Unique Hashes

Each transaction needs a unique SHA256 hash (64 hex characters). The hash should be generated from your internal identifiers to ensure uniqueness.

Important: The example below is just one approach. You should use your own internal identifiers (user ID, transaction ID, order ID, campaign ID, etc.) combined with the recipient address and amount to create a hash that’s unique to your system.

import crypto from 'crypto'; // Example: Using internal transaction ID function generateUniqueHash( internalTxId: string, // Your internal transaction/order ID userId: string, // Your internal user ID address: string, amount: string ): string { // Combine your internal identifiers with transaction details const data = `${internalTxId}:${userId}:${address}:${amount}`; return crypto.createHash('sha256').update(data).digest('hex'); } // Usage const hash = generateUniqueHash( 'order-12345', // Your order ID 'user-abc-789', // Your user ID '0x1234...', // Recipient address '10' // Amount ); console.log(hash); // 64 character hex string

Never reuse a uniqueHash! Each airdrop must have a unique hash, or it will be rejected by the smart contract as a duplicate.

4. Generate Request Signatures (Required)

All requests must include an HMAC-SHA256 signature:

import crypto from 'crypto'; function generateSignature( signingSecret: string, method: string, path: string, body: object ): string { const timestamp = Math.floor(Date.now() / 1000); const bodyString = JSON.stringify(body); const payload = `v1.${timestamp}.${method}.${path}.${bodyString}`; const signature = crypto .createHmac('sha256', signingSecret) .update(payload) .digest('hex'); return `v1,t=${timestamp},s=${signature}`; } const headers = { 'Authorization': `Bearer ${bearerToken}`, 'X-Signature': generateSignature(signingSecret, 'POST', '/api/airdrop', requestBody), 'Content-Type': 'application/json' };

See Authentication for details.

5. Verify Transaction

Once you receive a transaction hash, query the Movement Network RPC to get transaction details:

RPC Endpoint

Testnet: GET https://testnet.movementnetwork.xyz/v1/transactions/by_hash/{txHash}

Mainnet: GET https://mainnet.movementnetwork.xyz/v1/transactions/by_hash/{txHash}

Code Example

async function verifyTransaction(txHash: string, network: 'mainnet' | 'testnet'): Promise<any> { const rpcUrl = network === 'testnet' ? 'https://testnet.movementnetwork.xyz/v1' : 'https://mainnet.movementnetwork.xyz/v1'; const response = await fetch(`${rpcUrl}/transactions/by_hash/${txHash}`); if (!response.ok) { throw new Error(`Transaction not found: ${response.statusText}`); } const transaction = await response.json(); return transaction; } // Usage - verify mainnet transaction const txHash = '0xabc123...'; // From airdrop response const txDetails = await verifyTransaction(txHash, 'mainnet'); console.log('Transaction Status:', txDetails.success); console.log('Block Height:', txDetails.version); console.log('Timestamp:', txDetails.timestamp);

Response Example

{ "version": "12345678", "hash": "0xabc123...", "state_change_hash": "0x...", "event_root_hash": "0x...", "gas_used": "4", "success": true, "vm_status": "Executed successfully", "accumulator_root_hash": "0x...", "changes": [...], "sender": "0x...", "sequence_number": "0", "max_gas_amount": "200000", "gas_unit_price": "100", "timestamp": "1700000000000000" }

Transaction Confirmation: A transaction is considered final when success: true and it’s included in a block (has a version number).

Visual Explorer: You can also view transactions in the Movement Explorer:

  • Testnet: https://explorer.movementnetwork.xyz/txn/{txHash}?network=bardock+testnet
  • Mainnet: https://explorer.movementnetwork.xyz/txn/{txHash}?network=mainnet

Common Errors

401 Unauthorized

Cause: Invalid or missing bearer token

Solution: Check your Authorization: Bearer YOUR_BEARER_TOKEN header

400 Invalid Address

Cause: Address format is incorrect

Solution: Must be 0x followed by exactly 64 hex characters (66 total).

400 Duplicate Hash

Cause: This hash was already used

Solution: Generate a new unique hash

401 Invalid Signature

Cause: Missing or invalid request signature

Solution: Ensure X-Signature header is correctly generated

429 Rate Limit Exceeded

Cause: Too many requests from your IP address

Solution: Wait 60 seconds before retrying. Rate limit is 600 requests per minute (1 per second) per IP

Next Steps

Last updated on