Swagger

Transactions

10 endpoints.

10 endpoints

Transactions

POST/transaction/submitSubmit a signed operation

Submit what the client signed for a prepared operation. One endpoint serves every rail, and exactly one of signature or signedTransaction is required. Re-sending the same payload is idempotent on both shapes.

  • UserOperation rail: the signature covers the userOperationHash, and operationId is always required with it.
  • Executor rail, including a prepare that answered rail "sponsored": the eth_signTypedData_v4 signature over the returned signingPayload, again with operationId.
  • Self-funded rail: the account signs a whole transaction, so send signedTransaction instead — those bytes are the operation's identity. operationId follows what the prepare answered: present for a swap, whose router call is checked against its quote. It is absent for a native transfer, whose operation is created here and whose id comes back in the response.
  • Authorization is EIP-7702 only and is refused with 400 on the rails that delegate nothing.
  • 404 on submit when the prepared operation is unknown or expired: verify the id, then prepare again if needed.
  • 409 when it was already submitted, and for two coded retryable conflicts: AUTHORIZATION_IN_FLIGHT, a concurrent EIP-7702 first-operation authorization for this account, and SENDER_OPERATION_IN_FLIGHT, a previous operation that has not settled yet.
  • 429 when the rate limit is exceeded; check the Retry-After response header.

Authentication: X-API-Key

Input — request body

operationId string
Operation id from prepare. Required with signature; on the self-funded rail send it for a swap and omit it for a native transfer.
signature string
Required unless signedTransaction is sent. On the UserOperation rail, a raw secp256k1 signature of the 32-byte userOperationHash (no EIP-191 prefix). On the executor rail, and on a prepare that answered rail "sponsored", the eth_signTypedData_v4 signature over signingPayload. 0x-prefixed hex, max 4096 chars.
signedTransaction string
Self-funded rail only, and mutually exclusive with signature: the account's own serialized signed EIP-1559 transaction. 0x-prefixed hex.
authorization object
EIP-7702 authorization tuple, required when the current prepare returns authorizationRequired=true, and refused on rails without delegation. All six fields are required when present: chainId (integer >= 1), address (0x-prefixed 20-byte hex), nonce (integer >= 0), yParity (0|1), r and s (0x-prefixed 32-byte hex)

Input — example request

{
  "operationId": "ugtp_operation_E6SnXDoAl9AQ",
  "signature": "0xa3087507768f541a4eaa9d46b581c351d29c3137…65 bytes"
}

Output — example response (200)

{
  "operationId": "ugtp_operation_E6SnXDoAl9AQ",
  "status": "queued",
  "userOperationHash": "0x1a4fece09e742c04398006ebdae6d03227aa7e822ba825e0c64b44fc78d12cb3",
  "networkId": "42161"
}

Output — every status this endpoint answers with

StatusWhen
200Submission result
400Invalid submit body or signed transaction. Inspect code for the rejected transaction field, chain or rail.
401Missing or invalid credentials
404Operation not found or expired — prepare it again
409An existing operation, transaction or in-flight submission conflicts with this request. Inspect code before retrying; do not assume every 409 means success.
429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
500Internal server error
502SIGNED_TRANSACTION_IDENTITY_MISMATCH or SELF_FUNDED_BROADCAST_REFUSED. Re-sending identical bytes is permitted; this does not authorize signing a new transaction.
503SELF_FUNDED_CHAIN_UNAVAILABLE or SELF_FUNDED_RECORD_UNAVAILABLE. Retry the same signed bytes with bounded backoff.
Open in Swagger
GET/transaction/:idGet operation status

Live engine status of an operation (re-polls the engine). status is the engine UserOpStatus: unknown | received | queued | submitted | confirmed | finalized | failed | dropped. finalized = execution tx reached the network's reorg-safe confirmation depth; terminal. Operations normally appear from submit onward, and a prepared-but-never-submitted operation normally returns 404. An operation may occasionally be visible with status received before submit; clients must not treat visibility as proof of submission and should continue the documented sign-and-submit flow. Returns 429 Too Many Requests if the rate limit is exceeded (check the Retry-After response header).

Authentication: X-API-Key

Input — query and path parameters

id string required
Operation id

Output — example response (200)

{
  "operationId": "ugtp_operation_E6SnXDoAl9AQ",
  "status": "finalized",
  "transactionHash": "0x5977159b21734798f90fad1e442216dccec579168c00354268085a6e1d608af0",
  "userOperationHash": "0x1a4fece09e742c04398006ebdae6d03227aa7e822ba825e0c64b44fc78d12cb3",
  "networkId": "42161",
  "replacementCount": 0,
  "reason": null
}

Output — every status this endpoint answers with

StatusWhen
200Operation status
401Missing or invalid credentials
404Resource not found
429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
500Internal server error
Open in Swagger
GET/transactionList operations

List the calling project's operations, newest first, with optional account/status filters and paging. status is the last-known mirrored engine status (unknown | received | queued | submitted | confirmed | finalized | failed | dropped); call /transaction/:id for a live read. Operations normally appear after submit. An operation may occasionally be listed with status received before submit; clients must not treat listing presence as proof of submission and should continue the documented sign-and-submit flow. Returns 429 Too Many Requests if the rate limit is exceeded (check the Retry-After response header).

Authentication: X-API-Key

Input — query and path parameters

accountId string
Filter by account id
status string
Filter by status
limit number
Results per page (default 50)
offset number
Pagination offset (default 0)

Output — example response (200)

{
  "operations": [
    {
      "operationId": "ugtp_operation_E6SnXDoAl9AQ",
      "operationKind": "transfer",
      "status": "finalized",
      "networkId": "42161",
      "transactionHash": "0x5977159b21734798f90fad1e442216dccec579168c00354268085a6e1d608af0",
      "userOperationHash": "0x1a4fece09e742c04398006ebdae6d03227aa7e822ba825e0c64b44fc78d12cb3",
      "createdAt": "2026-09-02T13:56:15.463Z"
    }
  ],
  "count": 1,
  "limit": 50,
  "offset": 0
}

Output — every status this endpoint answers with

StatusWhen
200{ operations, count, limit, offset }
401Missing or invalid credentials
429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
500Internal server error
Open in Swagger
POST/transaction/transferPrepare same-chain transfer

One or more same-chain transfer legs prepared on the applicable rail — transaction batching, in the industry's terms. The gateway resolves the account from ownerAddress, legs may carry different tokens, and the RAIL is DECIDED HERE from the network and the asset — branch on the presence of rail in the response.

  • No rail field: the UserOperation rail. Sign userOperationHash and submit the signature.
  • rail "forward_request": the executor rail. Sign the EIP-712 signingPayload with eth_signTypedData_v4 and submit that.
  • rail "self_funded": the native coin, which no allowance can move. The response carries a whole transaction plus the account's on-chain nonce and a non-binding gasSuggestion, and the signed bytes go to submit as signedTransaction. There is no operationId and no ugtpFee, and a native leg must be the only leg.
  • Prepared operations expire after 30 minutes by default; self-funded swap quotes expire after 5 minutes. A self-funded native transfer receives its operationId only on submit. Prepare again if a stored preparation expires.
  • 400 when the account belongs to another network, or when the executor rail is asked to carry the native coin. 409 on a duplicate. On the self-funded rail, 409 with code=SENDER_OPERATION_IN_FLIGHT when the account already has a native transfer in flight at a different nonce. Re-preparing AT the in-flight nonce is admitted instead: that is how a stuck transfer is re-signed at a higher fee.
  • Coded 422 when the operation cannot execute: INSUFFICIENT_NATIVE_BALANCE on the self-funded rail (the engine checks the balance against the gas ceiling before the account signs), otherwise SWAP_AMOUNT_TOO_SMALL or EXECUTION_SIMULATION_REVERTED. The self-funded rail answers 400 CALL_SIMULATION_REVERTED or SELF_FUNDED_PREPARE_NOT_EXECUTABLE when the call itself cannot run.
  • Coded 503 on the self-funded rail is always retryable — it names a measurement that could not be taken.
  • 429 when the rate limit is exceeded; check the Retry-After response header.

Authentication: X-API-Key

Input — request body

ownerAddress string required
Owner EOA — the gateway resolves the account from it
networkId string required
Chain id
transfers Transfer[] required
Each: { tokenAddress, amount, recipientAddress }; amount = base-unit integer string; native sentinel 0xeee… for the chain coin
feeTokenAddress string
Fee token (omit for native-gas)

Input — example request

{
  "ownerAddress": "0x9b5fcd6f647a14ebf0f88b1c3e5a3d34b951fc6f",
  "networkId": "42161",
  "transfers": [
    {
      "tokenAddress": "0x912ce59144191c1204e64559fe8253a0e49e6548",
      "amount": "2148465421470024202",
      "recipientAddress": "0xCa9d43184Cc3179609f77D38433D363833C73c60"
    }
  ]
}

Output — example response (201)

{
  "operationId": "ugtp_operation_E6SnXDoAl9AQ",
  "userOperation": {
    "sender": "0x9b5fcd6f647a14ebf0f88b1c3e5a3d34b951fc6f",
    "nonce": "0x2",
    "initCode": "0x",
    "callData": "0xb61d27f6000000000000000000000000912ce59144191c…228 bytes",
    "accountGasLimits": "0x000000000000000000000000000084b800000000000000000000000000014393",
    "preVerificationGas": "0xc208",
    "gasFees": "0x00000000000000000000000000000000000000000000000000000000016eafe0",
    "paymasterAndData": "0x49f26881b5ea4d3f3d451c7faa4bca1b4aebcd97…214 bytes",
    "signature": "0x"
  },
  "userOperationHash": "0x1a4fece09e742c04398006ebdae6d03227aa7e822ba825e0c64b44fc78d12cb3",
  "ugtpFee": {
    "tokenAmount": "622595557466841530",
    "feeToken": "0x912ce59144191c1204e64559fe8253a0e49e6548"
  },
  "accountType": "eoa_7702",
  "authorizationRequired": false
}

Output — every status this endpoint answers with

StatusWhen
201Prepared operation
400Invalid input, an unsupported network, or a self-funded call that cannot execute. Inspect the response code and reason.
401Missing or invalid credentials
404The referenced accountId does not exist.
409A duplicate user operation (same UserOp hash already materialized), or code=SENDER_OPERATION_IN_FLIGHT on the self-funded rail — the account has a native transfer in flight at a nonce other than the one this prepare would hand out
422Blocked by a security verdict, insufficient native balance, or deterministic execution failure. Inspect security or the error code before signing.
429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
500An unclassified failure, carrying code=TRANSFER_PREPARE_FAILED.
503SELF_FUNDED_ESTIMATE_UNAVAILABLE: the operation could not be measured. Retry preparation with bounded backoff.
Open in Swagger
GET/transaction/historyAccount transaction history

The account's own operations — sends, swaps, and cross-chain operations — newest first, each with its asset movements and the fee it actually collected. Scoped to the one account resolved from networkId plus address, and to the calling project. A pure database read: it does not re-poll the engine, fetch receipts, or query bridges, so an address with no activity simply returns an empty list. Returns 429 Too Many Requests if the rate limit is exceeded (check the Retry-After response header).

Authentication: X-API-Key

Input — query and path parameters

networkId string required
Chain id
address string required
Account address
limit number
Results per page
offset number
Pagination offset

Output — example response (200)

{
  "operations": [],
  "count": 0,
  "limit": 25,
  "offset": 0
}

Output — every status this endpoint answers with

StatusWhen
200{ operations, count, limit, offset }
400Invalid request body or query parameters
401Missing or invalid credentials
429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
500Internal server error
Open in Swagger
POST/transaction/allowance-setupRead what to sign for an allowance

Executor rail only. Answers what this token needs before it can move without native coin: kind "permit" returns EIP-712 typed data when the token implements EIP-2612, and kind "approve" names the token, spender, and amount when it does not. Read-only — it signs nothing and sends nothing. Call it after a prepare is refused with code EXECUTOR_ALLOWANCE_MISSING, then relay the signature through /transaction/setup-permit for a permit or /transaction/setup-approval for an approve. Neither the spender nor the amount is ever accepted from the caller. Returns 404 if privateTokenSymbol names no active private token. Returns 429 Too Many Requests if the rate limit is exceeded (check the Retry-After response header).

  • Granting an allowance creates no operation: it is not returned by GET /transaction, does not appear in GET /transaction/history, and has no operationId to poll. What comes back is the on-chain transaction hash, and the allowance itself is the state to check.
  • This read decides nothing on its own — it reports what the token supports. The spender is never a caller-supplied address: for a private deposit it is resolved from privateTokenSymbol, and otherwise it is the executor.

Authentication: X-API-Key

Input — request body

networkId string required
Chain id
ownerAddress string required
The account whose allowance it is
tokenAddress string required
The ERC-20 to be granted
privateTokenSymbol string
Selects a private token's own contract as the spender, which a private deposit needs; resolved from the symbol, never from a caller-supplied address

Input — example request

{
  "networkId": "43114",
  "ownerAddress": "0x0a1758ad202a2059e8c2970b562597ca45d863c4",
  "tokenAddress": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"
}

Output — example response (200)

{
  "kind": "permit",
  "primaryType": "Permit",
  "domain": {},
  "types": {},
  "message": {},
  "deadline": 1780000000
}

Output — every status this endpoint answers with

StatusWhen
200What the account must sign
400Invalid request body or query parameters
401Missing or invalid credentials
429Rate limit exceeded — retry after the number of seconds in the `Retry-After` response header
500Internal server error
Open in Swagger
POST/transaction/setup-permitRelay an EIP-2612 permit

Relays an EIP-2612 permit for the executor rail, allowing the account to grant token allowance without native gas. The amount is never accepted from the caller — it is always the maximum — and neither is a spender address. Returns 409 with code PERMIT_ALREADY_GRANTED when this account already permitted the spender, which makes the call safely idempotent from the caller's side.

Authentication: X-API-Key

Input — request body

networkId string required
Chain id
ownerAddress string required
The account granting the allowance
tokenAddress string required
The ERC-20 being permitted
deadline number required
Unix timestamp from the typed data that was signed
signature string required
The account's signature over the permit typed data
privateTokenSymbol string
Selects a private token's own contract as the spender instead of the executor

Input — example request

{
  "networkId": "43114",
  "ownerAddress": "0x0a1758ad202a2059e8c2970b562597ca45d863c4",
  "tokenAddress": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
  "deadline": 1780000000,
  "signature": "0x..."
}

Output — example response (200)

{
  "transactionHash": "0x...the approve transaction UGTP broadcast",
  "status": "confirmed",
  "allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
}

Output — every status this endpoint answers with

StatusWhen
200Permit relayed
400Invalid request body or query parameters
401Missing or invalid credentials
409code=PERMIT_ALREADY_GRANTED — this account already permitted the executor.
Open in Swagger
POST/transaction/setup-approvalBroadcast the account's own approve

For executor-rail tokens without EIP-2612, the account signs an approve transaction and UGTP broadcasts it. Prefer /transaction/setup-permit when the token supports permit.

  • Whether any native coin accompanies it is read from chain state and never configured: an account that can already cover its own gas is sent none, and one that falls short is topped up by the difference only.
  • This is one-TIME setup and tightly bounded — a per-account, per-token lifetime allowance plus a per-project hourly limit, both reported as 429 once spent. Build it as a step a user passes through once per token, never as something to repeat.
  • Deliberately minimal: the sender, token, spender, and amount are all read out of the signed bytes, and the sender is recovered from the signature, so a body naming any of them is refused.
  • Coded 400 when the bytes are not an acceptable approve. 403 with APPROVAL_SENDER_BLOCKED when this account previously spent a funded allowance on something else.
  • 409 when chain state advises against it: APPROVAL_ALREADY_GRANTED when the allowance is already in place, APPROVAL_TX_NONCE_STALE or APPROVAL_TX_NONCE_IN_FLIGHT when the signed nonce cannot mine.
  • 502, 503, and 504 each name a step that did not complete and whether a retry is safe.

Authentication: X-API-Key

Input — request body

networkId string required
Chain id
rawTransaction string required
The account's own serialized signed approve transaction, 0x-prefixed hex

Input — example request

{
  "networkId": "43114",
  "rawTransaction": "0x02f8..."
}

Output — example response (200)

{
  "fundingTransactionHash": "0xaaa...",
  "approvalTransactionHash": "0xbbb...",
  "approvalStatus": "confirmed",
  "allowance": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
}

Output — every status this endpoint answers with

StatusWhen
200Gas funded and the approval broadcast
400Invalid approval transaction, unsupported token or spender, incorrect amount, or a failed simulation. Inspect the returned approval error code.
401Missing or invalid credentials
403code=APPROVAL_SENDER_BLOCKED — this account previously spent funded gas on a different transaction and is permanently ineligible for funded approvals.
409APPROVAL_ALREADY_GRANTED, APPROVAL_TX_NONCE_STALE, APPROVAL_TX_NONCE_IN_FLIGHT or APPROVAL_FUNDING_IN_PROGRESS. Check allowance and pending transactions before retrying.
429Approval funding limit reached. A lifetime allowance does not reset after backoff; inspect the reported limit before retrying.
502APPROVAL_FUNDING_FAILED: retry. APPROVAL_FUNDED_BUT_NOT_BROADCAST: gas was funded; broadcast the same signed approval through the account wallet or RPC. APPROVAL_MINED_WITHOUT_ALLOWANCE: inspect the receipt and allowance.
503Approval setup is temporarily unavailable or a required chain read failed. Retry with bounded backoff and the same signed approval.
504code=APPROVAL_FUNDING_NOT_CONFIRMED — the funding transfer has not confirmed yet; a retry resumes it without funding again.
Open in Swagger
GET/transaction/listAdmin transaction list

Control plane. Paginated transaction list across every project the session user can access, or one project when projectId is given, with filter-scoped revenue totals. Platform staff see all; a client is scoped to its own project memberships.

  • Each row carries its prepare-time security verdict (safe | unsafe | unavailable) when one was recorded.
  • Each row's fee object carries collectedUsdMicros, the collected amount valued in USD micros at the row's snapshotted price. netProfitUsdMicros is the collected fee minus relayer gas, both at execution-time prices. netProfitFeeRaw is that same margin in the fee token's base units, nullable and possibly negative.
  • Routing-fee valuation precedence: the quote-time value when the quote carried one. Else a confirmation-time snapshot, when the fee was collected in the paymaster fee token or the native coin. Else, for legacy rows only, a 1:1 conversion when the fee rode a trusted stable fee token. Else null.
  • A private-token row also carries productFee — our fee on that operation, always in the public underlying — with usdMicros stored at write time; legacy rows fall back to a 1:1 conversion for a $1-pegged stablecoin, else null.
  • Totals aggregate over every operation matching the current filter, not just the returned page: collectedUsdMicros, netProfitUsdMicros, lifiFeeUsdMicros, privateFeeUsdMicros, and earnedUsdMicros as their sum.
  • Totals.tokens is a per-network, per-asset breakdown of earned revenue, sorted by earnedUsdMicros descending. The same symbol on two networks stays two separate entries.
  • The totals block is viewer-scoped: platform staff receive the platform figures plus projectEarnedUsdMicros, while a client receives only its own earnings.
  • Each row's fee and productFee are viewer-scoped the same way: populated for platform staff, always null for a client.
  • Each row's projectEarnings lists what the project earned on that operation from its own markup, one entry per token, for every viewer. usdMicros stays null until settlement prices it.
  • totals.projectEarnings splits the priced markups per leg, as transferUsdMicros and privateUsdMicros.
  • A client's "all my projects" scope covers its active projects only; an archived project's operations drop out.

Authentication: Bearer JWT (project member)

Input — query and path parameters

projectId string
Optional project id filter
limit number
Results per page (default 25, max 100)
offset number
Pagination offset
status string
Status bucket: pending (unknown/received/queued/submitted), confirmed, finalized, failed, or dropped. A raw engine status is also accepted and matched exactly.
networkId string
Exact chain id, or comma-separated chain ids
kind string
Filter by operation kind: transfer | swap | cross_chain_transfer | cross_chain_swap | call | private_deposit | private_transfer | private_withdraw | private_register
transactionHash string
Partial execution tx hash
userOperationHash string
Partial user operation hash
from ISO datetime
Created-at lower bound
to ISO datetime
Created-at upper bound
includeTestnets string
Boolean-as-string, default false. Testnet networks are excluded from results unless true; an explicit networkId filter takes precedence.

Output — example response (200)

{
  "transactions": [
    {
      "id": "ugtp_operation_E6SnXDoAl9AQ",
      "operationKind": "transfer",
      "status": "finalized",
      "networkId": "42161",
      "transactionHash": "0x5977159b21734798f90fad1e442216dccec579168c00354268085a6e1d608af0",
      "userOperationHash": "0x1a4fece09e742c04398006ebdae6d03227aa7e822ba825e0c64b44fc78d12cb3",
      "fee": {
        "symbol": "ARB",
        "collectedFeeRaw": "564385946233880654",
        "collectedUsdMicros": "62782",
        "netProfitUsdMicros": "50548",
        "netProfitFeeRaw": "454406689249794025",
        "lifiFeeAssetId": null,
        "lifiFeeAssetSymbol": null,
        "lifiFeeAssetDecimals": null,
        "lifiFeeTokenRaw": null,
        "lifiFeeUsdMicros": null
      },
      "productFee": null,
      "security": {
        "verdict": "safe"
      },
      "createdAt": "2026-09-02T13:56:15.463Z"
    },
    {
      "id": "ugtp_operation_wdxo2cOMXBIQ",
      "operationKind": "cross_chain_swap",
      "status": "finalized",
      "networkId": "42161",
      "transactionHash": "0x1125e6fa15ea46293efa3bf06e98958b16b140d4c3f2556f13e4c1b319920a4c",
      "userOperationHash": "0x9f165e8e0f3957722ad6520328ce00333c29f7d26ca50401bf7a5da8540c08c8",
      "fee": {
        "symbol": "USDC",
        "collectedFeeRaw": "72738",
        "collectedUsdMicros": "72726",
        "netProfitUsdMicros": "54191",
        "netProfitFeeRaw": "54200",
        "lifiFeeAssetId": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
        "lifiFeeAssetSymbol": "USDC",
        "lifiFeeAssetDecimals": 6,
        "lifiFeeTokenRaw": "500",
        "lifiFeeUsdMicros": "499"
      },
      "productFee": null,
      "security": {
        "verdict": "safe"
      },
      "createdAt": "2026-09-04T09:34:06.000Z"
    },
    {
      "id": "ugtp_operation_BJL0njW5DcGh",
      "operationKind": "private_withdraw",
      "status": "finalized",
      "networkId": "43114",
      "transactionHash": "0x5d0827600d4bf987ec907143c2479f1d84e49e92d26bd967411a21cb03246506",
      "userOperationHash": "0x141d4abead5569196b9c3165e040dab50a6a91940a1da44b779a76c5cc01307d",
      "fee": {
        "symbol": "USDT",
        "collectedFeeRaw": "54441",
        "collectedUsdMicros": "54430",
        "netProfitUsdMicros": "49987",
        "netProfitFeeRaw": "49997",
        "lifiFeeAssetId": null,
        "lifiFeeAssetSymbol": null,
        "lifiFeeAssetDecimals": null,
        "lifiFeeTokenRaw": null,
        "lifiFeeUsdMicros": null
      },
      "productFee": {
        "kind": "bps",
        "amountRaw": "500",
        "symbol": "USDT",
        "decimals": 6,
        "usdMicros": "500"
      },
      "security": {
        "verdict": "safe"
      },
      "createdAt": "2026-09-04T08:46:59.706Z"
    }
  ],
  "total": 3,
  "limit": 25,
  "offset": 0,
  "totals": {
    "collectedUsdMicros": "110000",
    "netProfitUsdMicros": "81000",
    "lifiFeeUsdMicros": "1000000",
    "privateFeeUsdMicros": "5000",
    "earnedUsdMicros": "1086000",
    "tokens": [
      {
        "networkId": "137",
        "assetId": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
        "symbol": "USDT",
        "decimals": 6,
        "earnedTokenRaw": "1023000",
        "earnedUsdMicros": "1023000"
      },
      {
        "networkId": "42161",
        "assetId": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
        "symbol": "USDC",
        "decimals": 6,
        "earnedTokenRaw": "63000",
        "earnedUsdMicros": "63000"
      }
    ]
  }
}

Output — every status this endpoint answers with

StatusWhen
200Transactions
400Invalid request body or query parameters
401Missing or invalid credentials
Open in Swagger
GET/transaction/seriesTransactions-over-time series (admin chart)

Control plane. Per-bucket new operation counts over the requested window, zero-filled and UTC-aligned, split by network. Omitting bucket picks a granularity from the window length. Platform staff see all operations; a client is scoped to its project memberships.

Authentication: Bearer JWT

Input — query and path parameters

period string required
day | week | month | custom
bucket string
day | week | month (default derived from window length)
from string
Window start (required when period=custom)
to string
Window end (defaults to now)
projectId string
Filter to one project
includeTestnets string
Boolean-as-string, default false. Testnet networks are excluded unless true; an explicit networkId filter takes precedence.

Output — example response (200)

{
  "period": "month",
  "from": "2026-06-10T00:00:00.000Z",
  "to": "2026-07-10T00:00:00.000Z",
  "bucket": "day",
  "networks": [
    {
      "networkId": "137",
      "name": "Polygon PoS"
    }
  ],
  "series": [
    {
      "bucket": "2026-06-10T00:00:00.000Z",
      "total": 4,
      "byNetwork": {
        "137": 4
      }
    }
  ],
  "total": 4
}

Output — every status this endpoint answers with

StatusWhen
200{ period, from, to, bucket, networks[{networkId,name}], series[{bucket,total,byNetwork}], total }
400Invalid request body or query parameters
401Missing or invalid credentials
Open in Swagger