Skip to main content

HTTP Client Integration

Airnode exposes a standard HTTP API. You call an endpoint, receive signed data, and optionally submit it on-chain yourself.

Making a request

Send a POST request to /endpoints/{endpointId} with parameters in the JSON body. Include an API key header if the endpoint requires authentication.

curl -X POST http://airnode.example.com/endpoints/0x... \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-key" \
-d '{"parameters":{"ids":"bitcoin","vs_currencies":"usd"}}'

Response format

The response format depends on whether the endpoint has encoding configured.

Encoded response

When the endpoint defines encoding (type, path, times), the response contains ABI-encoded data as a hex string. This is the format you submit to on-chain contracts.

{
"airnode": "0x...",
"endpointId": "0x...",
"timestamp": 1700000000,
"data": "0x...",
"signature": "0x..."
}

Raw response

When the endpoint has no encoding, the response contains the upstream API's JSON output directly. The signature covers the hash of the JSON data.

{
"airnode": "0x...",
"endpointId": "0x...",
"timestamp": 1700000000,
"rawData": { "bitcoin": { "usd": 67432 } },
"signature": "0x..."
}

Signature format

Every response is signed by the airnode's private key using EIP-191 personal sign:

messageHash = keccak256(encodePacked(endpointId, timestamp, data))
signature = EIP-191 personal sign over messageHash

The signature proves the airnode endorsed this data at this timestamp for this endpoint. Anyone can verify it without trusting the transport layer.

Verifying signatures off-chain

Use viem (or any EIP-191 library) to recover the signer and confirm it matches the expected airnode address.

import { recoverAddress, hashMessage, keccak256, encodePacked } from 'viem';

const messageHash = keccak256(encodePacked(['bytes32', 'uint256', 'bytes'], [endpointId, BigInt(timestamp), data]));

const recovered = await recoverAddress({
hash: hashMessage({ raw: messageHash }),
signature,
});

// recovered === airnode address

If the recovered address does not match the airnode address you expect, the data has been tampered with or was signed by a different key.

Authentication

Endpoints support three auth methods: free (no credentials), apiKey (via X-Api-Key header), and x402 (pay-per-request). Endpoints with auth.type: 'apiKey' require an X-Api-Key header. Endpoints with auth.type: 'free' accept unauthenticated requests.

# Free endpoint -- no auth header needed
curl -X POST http://airnode.example.com/endpoints/0x... \
-H "Content-Type: application/json" \
-d '{"parameters":{"id":"1"}}'

# API key endpoint
curl -X POST http://airnode.example.com/endpoints/0x... \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-key" \
-d '{"parameters":{"id":"1"}}'

Async requests

For endpoints with mode: async, the initial response is a 202 with a poll URL:

{
"requestId": "0x...",
"status": "pending",
"pollUrl": "/requests/0x..."
}

Poll until complete:

curl http://airnode.example.com/requests/0x...
# → { "requestId": "0x...", "status": "complete", "data": "0x...", "signature": "0x...", ... }

Status transitions: pendingprocessingcomplete | failed.

SSE streaming

For endpoints with mode: stream, the response is a Server-Sent Event:

curl -X POST -N http://airnode.example.com/endpoints/0x... \
-H "Content-Type: application/json" \
-d '{"parameters":{"ids":"bitcoin"}}'
data: {"done":true,"airnode":"0x...","endpointId":"0x...","timestamp":1700000000,"data":"0x...","signature":"0x..."}

The full pipeline runs (including plugins), and the signed result is delivered as a single SSE event.

x402 payment

For endpoints with x402 auth, the first request returns 402 with payment details:

{
"paymentId": "0x...",
"amount": "1000000",
"token": "0xA0b8...",
"network": 8453,
"recipient": "0x...",
"expiresAt": 1700001000
}

After paying on-chain, retry with the transaction hash:

curl -X POST http://airnode.example.com/endpoints/0x... \
-H "Content-Type: application/json" \
-H "X-Payment-Proof: 0x<txHash>" \
-d '{"parameters":{"ids":"bitcoin"}}'

Error responses

StatusMeaning
400Missing or invalid parameters
401Missing or invalid API key
402Payment required (x402 — includes payment details)
404Unknown endpoint ID
413Request body too large (> 64KB)
415Content-Type must be application/json
429Rate limit exceeded
502Upstream API error or internal processing failure

Health check

curl http://airnode.example.com/health

Returns the airnode address and version. Use this to verify the server is running and to discover the airnode address for signature verification.