Welcome to Across

Move money across all major chains.

What is Across?

Across is a crosschain interoperability protocol that provides the fastest, cheapest, and most secure way to move assets across blockchains. With ~2 second fills on mainnet and support for 23+ chains, Across powers crosschain swaps, bridges, and embedded actions through a unified API flow.

Staging. Latest Across API runs in a staging environment today. This is exclusive documentation to share a preview on the API spec and integration flow.

API key required. Get your API key and Integrator ID to authenticate your requests.

Across API Quickstart

Four calls, start to finish.

Discover what can move

GET /v1/capabilities answers what can move between two chains right now.

1-discover.ts
const res = await fetch(
  "https://api.staging.across.to/v1/capabilities" +
    "?originChainId=42161&destinationChainId=8453&include=tokens",
  { headers: { Authorization: "Bearer YOUR_API_KEY" } },
);

const capabilities = await res.json();

The response from this API call will tell you details about supported deposit/funding methods available on this route, along with various other details.

Price the transfer

POST /v1/quotes prices one exact transfer and returns the payload to sign. amountType decides which side carries the amount: exact_input (the default) uses origin.amount; exact_output and min_output use destination.amount and must name amountType explicitly.

2-price.ts
const res = await fetch("https://api.staging.across.to/v1/quotes", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    origin: {
      token: { chainId: 42161, address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
      amount: "1000000", // 1 USDC, 6 decimals
      depositor: "0xYourWalletAddress",
    },
    destination: {
      token: { chainId: 8453, address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" },
      recipient: "0xYourWalletAddress",
    },
    amountType: "exact_input",
    fundingMethods: ["permit2"],
  }),
});

const quote = await res.json();
// quote.quoteId, quote.expiresAt, quote.nextActions

Request bodies are strict — a misspelled field is an error, not a silently ignored one.

Execute the quote

The quote returns nextActions: an ordered list of what has to happen before the transfer can proceed. Dispatch on kindapproval, sign, transaction or deposit_address. A permit2 quote gives you a sign action; sign its typedData verbatim, because that exact payload is what the server verifies.

Carried over from step 2: quoteId, and the sign action itself — you need both its id (to key the signatures map) and its typedData (to sign).

3-execute.ts
const quoteId = quote.quoteId;
const signAction = quote.nextActions.find((a) => a.kind === "sign");

const signatures = {
  [signAction.id]: await walletClient.signTypedData(signAction.typedData),
};

const res = await fetch(
  `https://api.staging.across.to/v1/quotes/${quoteId}/executions`,
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ authorization: { signatures } }),
  },
);

const execution = await res.json();
// execution.transferId, execution.executionId, execution.acceptedAt

A 2xx means the transfer was accepted, but it still needs to be filled and can be tracked in the next step.

Track it to a settled outcome

Carried over from step 3: transferId — the same value as the quoteId you priced with.

4-track.ts
const orderId = execution.transferId;

const res = await fetch(`https://api.staging.across.to/v1/transfers/${orderId}`);

const transfer = await res.json();
console.log(transfer.status);
// { state, reason, description, isTerminal, finalized }

Poll until status.isTerminal, then slow to 1–5 minutes until status.finalized.

What's Next

On this page