Skip to Content
API ReferenceProcess Airdrop

Process Airdrop

Send MOVE tokens to a recipient address.

Endpoint

POST /api/airdrop

Authentication

Required headers:

  • Authorization: Bearer YOUR_BEARER_TOKEN
  • X-Signature: v1,t=timestamp,s=signature

Request Body

{ "address": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", "amount": "100", "uniqueHash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2" }

Parameters

FieldTypeRequiredDescription
addressstringYesRecipient wallet address (0x + exactly 64 hex characters)
amountstring/numberYesAmount in whole MOVE units (not octas)
uniqueHashstringYesSHA256 hash (64 hex characters) to prevent duplicates

Each uniqueHash can only be used once. Generate a new unique hash for each transaction.

Response

Success (200 OK)

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

Response Fields

FieldTypeDescription
successbooleanAlways true for successful requests
transactionHashstringBlockchain transaction hash for verification
recipientAddressstringEcho of the recipient address
amountstringEcho of the amount sent
timestampstringISO 8601 timestamp
uniqueHashstringEcho of the unique hash

Transaction Confirmed: When you receive a 200 OK response, the transaction has been confirmed on-chain. No need for additional verification - the transaction is finalized and irreversible.

The response time includes blockchain confirmation (~1-1.5 seconds), so you can trust that the funds have been transferred.

Error Responses

400 Bad Request

Invalid input parameters:

{ "success": false, "error": { "code": "INVALID_ADDRESS", "message": "Invalid wallet address format. Must be 0x followed by exactly 64 hex characters." } }

Common validation errors:

  • INVALID_ADDRESS - Must be 0x + exactly 64 hex characters
  • INVALID_AMOUNT - Amount must be > 0
  • DUPLICATE_HASH - This uniqueHash was already processed
  • INVALID_HASH - Must be 64-character SHA256 hex string

401 Unauthorized

Authentication failed:

{ "success": false, "error": { "code": "INVALID_TOKEN", "message": "Invalid authentication token" } }

Common authentication errors:

  • MISSING_AUTH_HEADER - Authorization header not provided
  • INVALID_TOKEN - Bearer token is invalid
  • UNAUTHORIZED - Invalid or missing signature

429 Too Many Requests

Rate limit exceeded:

{ "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Please try again later." } }

Response Headers:

  • X-RateLimit-Limit - Maximum requests allowed (600/min)
  • X-RateLimit-Remaining - Requests remaining in current window
  • X-RateLimit-Reset - Unix timestamp when the limit resets

The API uses a fixed window rate limit of 600 requests per minute per IP address. If you exceed this limit, you’ll receive a 429 response and must wait until the window resets.

503 Service Unavailable

API is temporarily paused for maintenance:

{ "success": false, "error": { "code": "AIRDROP_PAUSED", "message": "Airdrop API is currently paused. Please try again later." } }

When you receive a 503 response, the API has been intentionally paused by administrators. This is typically for maintenance or emergency situations. Implement retry logic with exponential backoff and check back periodically.

500 Internal Server Error

Service or blockchain error:

{ "success": false, "error": { "code": "INSUFFICIENT_BALANCE", "message": "Insufficient treasury balance to process this airdrop" } }

Common server errors:

  • INSUFFICIENT_BALANCE - Treasury wallet has insufficient funds
  • TRANSACTION_FAILED - Blockchain transaction failed
  • CONTRACT_ERROR - Smart contract execution error

Code Example

import crypto from 'crypto'; async function processAirdrop( apiKey: string, signingSecret: string, internalTxId: string, // Your internal transaction ID userId: string, // Your internal user ID address: string, amount: string ): Promise<string> { // Generate unique hash using YOUR internal identifiers // IMPORTANT: Customize this based on your system's IDs const uniqueHash = crypto .createHash('sha256') .update(`txn:${internalTxId}:user:${userId}:${address}:${amount}`) .digest('hex'); const requestBody = { address, amount, uniqueHash }; // Generate signature const timestamp = Math.floor(Date.now() / 1000); const bodyString = JSON.stringify(requestBody); const payload = `v1.${timestamp}.POST./api/airdrop.${bodyString}`; const signature = crypto.createHmac('sha256', signingSecret).update(payload).digest('hex'); const response = await fetch('https://YOUR_API_DOMAIN/api/airdrop', { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'X-Signature': `v1,t=${timestamp},s=${signature}`, 'Content-Type': 'application/json' }, body: bodyString }); const data = await response.json(); if (!data.success) { throw new Error(data.error.message); } return data.transactionHash; } // Usage const txHash = await processAirdrop( process.env.API_KEY!, process.env.SIGNING_SECRET!, 'order-12345', // Your internal transaction/order ID 'user-abc-789', // Your internal user ID '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', '100' ); console.log('Success! Transaction:', txHash);

Best Practices

Unique Hash Generation: Use your internal identifiers (transaction ID, user ID, campaign ID, etc.) combined with the recipient address and amount. This ensures uniqueness in your system and prevents accidental duplicates. The smart contract will reject duplicate hashes automatically.

  1. Handle errors gracefully - Check success field and handle error object
  2. Use proper signatures - All requests require HMAC-SHA256 signatures in the X-Signature header
  3. Verify transactions - Use the transaction hash to verify on the blockchain explorer
  4. Test on testnet first - Use your testnet bearer token when testing your integration

Transaction Verification

Verify your transaction using the Movement Network RPC:

// After successful airdrop const result = await processAirdrop(address, amount, uniqueHash); const txHash = result.transactionHash; // Verify via RPC const rpcUrl = 'https://mainnet.movementnetwork.xyz/v1'; // or testnet const response = await fetch(`${rpcUrl}/transactions/by_hash/${txHash}`); const tx = await response.json(); console.log('Success:', tx.success); console.log('Block:', tx.version); console.log('Timestamp:', tx.timestamp);

See Transaction Verification for complete details.

Last updated on