Signing the X-Expires-At header

Use your wallet's private key to sign a message containing the expiry time in epoch milliseconds. We will use this signature to authenticate the signer to the API.


Choose a time up to 1 minute in the future that will determine when the signature expires. Convert this time into epoch milliseconds and cast to a string. Sign the string " " concatenated with the chosen time with your wallet's private key. Set the x-expires-at and x-signature headers when sending the request.


There is no way to invalidate a signature that has been compromised. Set an expiry that is no more than 60 seconds in the future. Please generate an API Key if you need a mechanism that does not expire.


const { ethers } = require('ethers');

const { ADDRESS, MNEMONIC } = process.env;
const wallet = ethers.Wallet.fromMnemonic(MNEMONIC);

async function generateAuthHeaders(expireInMs) {
    const expiresAt = ( + expireInMs).toString();
    const signature = await wallet.signMessage(` ${expiresAt}`);
  return {
    'x-expires-at': expiresAt,
    'x-signature': signature,

(async function() {
  const url = `${ADDRESS}`;
  // Signature expires 10 seconds from now
  const headers = await generateAuthHeaders(10 * 1000);
  const res = await fetch(url, {
    method: 'GET',


Status CodeError CodeErrorSolution
403804x-expires-at is not an integerSend expires at as an epoch timestamp in milliseconds.
403805x-expires-at must be in the futureSend an expires at that is at least ten seconds in the future.
403806x-expires-at is greater than 60 secs in futureSend an expires at that is less than sixty seconds in the future.