> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agg.market/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> To integrate AGG, start with Quickstart: REST (https://docs.agg.market/quickstart/rest), then Order lifecycle & statuses (https://docs.agg.market/concepts/order-lifecycle).
> Track every trade until it reaches a terminal status. Before retrying a failed or timed-out call, read Errors, retries & idempotency (https://docs.agg.market/concepts/errors).
> The API reference is generated from https://docs.agg.market/openapi/openapi.json.

# Referrals

> Who pays a referral fee, and how to sign an app-paid payout after the fill is already terminal.

A referral pays `referrer` from the same trade. On a sell it applies only when you set a sell rate. Rates and the parameter table live on [Fees](/concepts/fees). Signature payload types live on [Self-custody signing](/recipes/self-custody-signing).

Send referral fields from your backend with `x-app-api-key`, alongside `x-app-id` and the
user's access token. The API key does not replace the user's session. Never expose it in
browser code.

## Who pays

`referralPayer` is `"user"` (default) or `"app"`.

A user-paid referral is reserved from `maxSpend` and collected the same way as the app fee: on the amount actually filled. `feeBreakdown.appFee` is the maximum if the buy fills in full. `feeBreakdown.referralFee` is the user-paid referral.

An app-paid referral is not a user cost. A partial fill pays the quoted referral amount. A failed fill pays nothing. You pay it from `referralPayerAddress`.

Per-venue rates go in `referrerFeeBipsByVenue`. Hyperliquid charges 1 USDC to activate a referrer with no HyperCore account. On a self-custody Hyperliquid buy with a user-paid referral, `referralActivationSponsorAddress` names a wallet of yours that pays it instead, and its signature is listed with `purpose: "hl_activation_sponsor"`. See [Fees](/concepts/fees#where-a-referral-cannot-be-paid).

## Poll past terminal

An app-paid payout can appear in `pendingSignatures` with `purpose: "referral_payout"` after
the trade is already terminal, including for managed trades. When you requested an app-paid
referral, continue polling for that payout after a successful fill. Read each request's
`expiresAt`; an unanswered request expires without undoing the trade.

<CodeGroup>
  ```ts SDK theme={null}
  let payout;
  const deadline = Date.now() + 15 * 60 * 1000;
  while (!payout && Date.now() < deadline) {
    const status = await client.getExecutionStatus({ quoteId });
    payout = status.pendingSignatures?.find(
      (item) => item.purpose === "referral_payout" &&
        item.signerAddress.toLowerCase() === payerAddress.toLowerCase(),
    );
    if (status.terminal && ["failed", "cancelled", "expired"].includes(status.overallState)) break;
    if (!payout) await new Promise((resolve) => setTimeout(resolve, status.pollAfterMs ?? 3000));
  }
  ```

  ```bash cURL theme={null}
  curl -s -H "x-app-id: $APP_ID" -H "Authorization: Bearer $ACCESS_TOKEN" \
    "$API/execution/status?quoteId=$QUOTE_ID"
  ```
</CodeGroup>

Full shape on [Get execution status](/api-reference/trading/get-execution-status).

Submit the signature on [Submit signatures for a pending self-custody fill](/api-reference/trading/submit-signatures-for-a-pending-self-custody-fill). How to sign `payload` is [Self-custody signing](/recipes/self-custody-signing). On an EVM chain the request `type` is `transaction` and you send `{ stepId, txHash }` after broadcasting. On HyperCore (`1337`) the type is `eip712` and you send `{ stepId, signature }`. Solana payouts are refused.

```ts theme={null}
// payerSigner uses the signing-reference implementation with your payer wallet.
// For transactions it switches chains and converts the decimal value to bigint.
if (payout && Date.parse(payout.expiresAt) > Date.now()) {
  const signed = await payerSigner(payout);
  await client.submitFillSignatures(quoteId, [
    typeof signed === "string"
      ? { stepId: payout.stepId, signature: signed }
      : { stepId: payout.stepId, txHash: signed.txHash },
  ]);
}
```

In self-custody the same `pendingSignatures` list also holds the trader's requests. Skip a request whose `signerAddress` is not the wallet you hold.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.