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.

Signing

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 "api.arcade.xyz: " 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.

Example

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

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

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

(async function() {
  const url = `https://api-v2.arcade.xyz/api/v2/accounts/${ADDRESS}`;
  // Signature expires 10 seconds from now
  const headers = await generateAuthHeaders(10 * 1000);
  
  const res = await fetch(url, {
    method: 'GET',
    headers,
  });
  
  console.log(res);
})();

Errors

Status CodeError CodeErrorSolution
401401Unauthorized
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.