Skip to content

Quickstart

Relay your first gas-sponsored transaction in about five minutes. You will submit a 1-wei transfer on Base Sepolia, poll it to completion, and read what it cost you in USD. No testnet ETH required — Photon's relayer pays the gas.

1. Get an API key

Every request carries your key in the api-key header. Get API access and fund your prepaid balance, then export the key:

export EDITH_API_KEY="your-api-key"

2. Submit the transaction

POST /api/submit-tx queues the transaction and returns immediately with a txId — relaying happens in the background.

curl -X POST https://photon.example.com/api/submit-tx \
  -H "api-key: $EDITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49",
    "callData": "0x",
    "value": "1",
    "chainId": 84532,
    "label": "quickstart-transfer"
  }'
const res = await fetch("https://photon.example.com/api/submit-tx", {
  method: "POST",
  headers: {
    "api-key": process.env.EDITH_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: "0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49",
    callData: "0x",
    value: "1",
    chainId: 84532,
    label: "quickstart-transfer",
  }),
});
const { data } = await res.json();
console.log(data.txId);

Expected response — 201 Created:

{
  "success": true,
  "data": {
    "txId": "68fa3450539a3c9d28bbca33",
    "estimatedCostUSD": 0.0021
  },
  "timestamp": "2026-07-29T09:14:03.412Z"
}

Info

A 201 means queued, not mined. estimatedCostUSD is a pre-flight gas estimate reserved against your balance; the final costUSD comes with the result.

3. Poll until it executes

GET /api/tx?id=<txId> returns the transaction record. Poll every second or so until status is EXECUTED (or FAILED).

curl "https://photon.example.com/api/tx?id=68fa3450539a3c9d28bbca33" \
  -H "api-key: $EDITH_API_KEY"
let tx;
do {
  await new Promise((r) => setTimeout(r, 1000));
  const res = await fetch(
    "https://photon.example.com/api/tx?id=68fa3450539a3c9d28bbca33",
    { headers: { "api-key": process.env.EDITH_API_KEY! } }
  );
  ({ data: tx } = await res.json());
} while (tx.status !== "EXECUTED" && tx.status !== "FAILED");
console.log(tx.status, tx.executionTxHash);

Expected response once mined — 200 OK:

{
  "success": true,
  "data": {
    "id": "68fa3450539a3c9d28bbca33",
    "userId": "68c275846a6ba1c9a2198a8c",
    "to": "0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49",
    "callData": "0x",
    "value": "1",
    "chainId": 84532,
    "gasPrice": "1000000000",
    "maxFeePerGas": null,
    "maxPriorityFeePerGas": null,
    "gasLimit": null,
    "label": "quickstart-transfer",
    "status": "EXECUTED",
    "executionTxHash": "0x7d1a8f0f7c2f4b7e9a3d5c1e8b6a4f2d0c9e7b5a3f1d8c6e4b2a0f9d7c5e3b1a",
    "timestamp": "2026-07-29T09:14:08.921Z",
    "latency": 2500,
    "costUSD": 0.0019,
    "retries": 0,
    "isAccountCharged": true,
    "transactionType": "flash",
    "submitRegion": "default"
  },
  "timestamp": "2026-07-29T09:14:09.523Z"
}

4. Read the cost

costUSD is the actual amount debited from your prepaid balance for this transaction — here about a fifth of a cent. executionTxHash is the on-chain hash; look it up on Basescan to see the relayer paid the gas, not you.

That's the whole loop: submit intent, Photon signs and pays, you read the result.

Next steps