Files
PolymarketDocumentation/docs/developers/builders/relayer-client.md
T
2026-02-14 12:59:26 +01:00

918 lines
28 KiB
Markdown

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Relayer Client
> Use Polymarket's Polygon relayer to execute gasless transactions for your users
## Overview
The Relayer Client routes onchain transactions through Polymarket's infrastructure, providing gasless transactions for your users. Builder authentication is required to access the relayer.
<CardGroup cols={3}>
<Card title="Gasless Transactions" icon="gas-pump">
Polymarket pays all gas fees
</Card>
<Card title="Wallet Deployment" icon="wallet">
Deploy Safe or Proxy wallets
</Card>
<Card title="CTF Operations" icon="arrows-split-up-and-left">
Split, merge, and redeem positions
</Card>
</CardGroup>
***
## Builder API Credentials
Each builder receives API credentials from their [Builder Profile](/developers/builders/builder-profile):
| Credential | Description |
| ------------ | ------------------------------------ |
| `key` | Your builder API key identifier |
| `secret` | Secret key for signing requests |
| `passphrase` | Additional authentication passphrase |
<Warning>
**Security Notice**: Your Builder API keys must be kept secure. Never expose them in client-side code.
</Warning>
***
## Installation
<CodeGroup>
```bash TypeScript theme={null}
npm install @polymarket/builder-relayer-client
```
```bash Python theme={null}
pip install py-builder-relayer-client
```
</CodeGroup>
***
## Relayer Endpoint
All relayer requests are sent to Polymarket's relayer service on Polygon:
```
https://relayer-v2.polymarket.com/
```
***
## Signing Methods
<Tabs>
<Tab title="Remote Signing (Recommended)">
Remote signing keeps your credentials secure on a server you control.
**How it works:**
1. Client sends request details to your signing server
2. Your server generates the HMAC signature
3. Client attaches headers and sends to relayer
### Server Implementation
Your signing server receives request details and returns the authentication headers:
<CodeGroup>
```typescript TypeScript theme={null}
import {
buildHmacSignature,
BuilderApiKeyCreds
} from "@polymarket/builder-signing-sdk";
const BUILDER_CREDENTIALS: BuilderApiKeyCreds = {
key: process.env.POLY_BUILDER_API_KEY!,
secret: process.env.POLY_BUILDER_SECRET!,
passphrase: process.env.POLY_BUILDER_PASSPHRASE!,
};
// POST /sign - receives { method, path, body } from the client SDK
export async function handleSignRequest(request) {
const { method, path, body } = await request.json();
const timestamp = Date.now().toString();
const signature = buildHmacSignature(
BUILDER_CREDENTIALS.secret,
parseInt(timestamp),
method,
path,
body
);
return {
POLY_BUILDER_SIGNATURE: signature,
POLY_BUILDER_TIMESTAMP: timestamp,
POLY_BUILDER_API_KEY: BUILDER_CREDENTIALS.key,
POLY_BUILDER_PASSPHRASE: BUILDER_CREDENTIALS.passphrase,
};
}
```
```python Python theme={null}
import os
import time
from py_builder_signing_sdk.signing.hmac import build_hmac_signature
from py_builder_signing_sdk import BuilderApiKeyCreds
BUILDER_CREDENTIALS = BuilderApiKeyCreds(
key=os.environ["POLY_BUILDER_API_KEY"],
secret=os.environ["POLY_BUILDER_SECRET"],
passphrase=os.environ["POLY_BUILDER_PASSPHRASE"],
)
# POST /sign - receives { method, path, body } from the client SDK
def handle_sign_request(method: str, path: str, body: str):
timestamp = str(int(time.time()))
signature = build_hmac_signature(
BUILDER_CREDENTIALS.secret,
timestamp,
method,
path,
body
)
return {
"POLY_BUILDER_SIGNATURE": signature,
"POLY_BUILDER_TIMESTAMP": timestamp,
"POLY_BUILDER_API_KEY": BUILDER_CREDENTIALS.key,
"POLY_BUILDER_PASSPHRASE": BUILDER_CREDENTIALS.passphrase,
}
```
</CodeGroup>
<Warning>
Never commit credentials to version control. Use environment variables or a secrets manager.
</Warning>
### Client Configuration
Point your client to your signing server:
<CodeGroup>
```typescript TypeScript theme={null}
import { createWalletClient, http, Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";
import { RelayClient } from "@polymarket/builder-relayer-client";
import { BuilderConfig } from "@polymarket/builder-signing-sdk";
// Create wallet
const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
const wallet = createWalletClient({
account,
chain: polygon,
transport: http(process.env.RPC_URL)
});
// Configure remote signing
const builderConfig = new BuilderConfig({
remoteBuilderConfig: {
url: "https://your-server.com/sign"
}
});
const RELAYER_URL = "https://relayer-v2.polymarket.com/";
const CHAIN_ID = 137;
const client = new RelayClient(
RELAYER_URL,
CHAIN_ID,
wallet,
builderConfig
);
```
```python Python theme={null}
import os
from py_builder_relayer_client.client import RelayClient
from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig
private_key = os.getenv("PRIVATE_KEY")
# Configure remote signing
builder_config = BuilderConfig(
remote_builder_config=RemoteBuilderConfig(
url="https://your-server.com/sign"
)
)
client = RelayClient(
"https://relayer-v2.polymarket.com",
137,
private_key,
builder_config
)
```
</CodeGroup>
</Tab>
<Tab title="Local Signing">
Sign locally when your backend handles all transactions.
**How it works:**
1. Your system creates transactions on behalf of users
2. Your system uses Builder API credentials locally to add headers
3. Complete signed request is sent directly to the relayer
<CodeGroup>
```typescript TypeScript theme={null}
import { createWalletClient, http, Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";
import { RelayClient } from "@polymarket/builder-relayer-client";
import { BuilderConfig } from "@polymarket/builder-signing-sdk";
// Create wallet
const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
const wallet = createWalletClient({
account,
chain: polygon,
transport: http(process.env.RPC_URL)
});
// Configure local signing
const builderConfig = new BuilderConfig({
localBuilderCreds: {
key: process.env.POLY_BUILDER_API_KEY!,
secret: process.env.POLY_BUILDER_SECRET!,
passphrase: process.env.POLY_BUILDER_PASSPHRASE!
}
});
const RELAYER_URL = "https://relayer-v2.polymarket.com/";
const CHAIN_ID = 137;
const client = new RelayClient(
RELAYER_URL,
CHAIN_ID,
wallet,
builderConfig
);
```
```python Python theme={null}
import os
from py_builder_relayer_client.client import RelayClient
from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds
private_key = os.getenv("PRIVATE_KEY")
# Configure local signing
builder_config = BuilderConfig(
local_builder_creds=BuilderApiKeyCreds(
key=os.getenv("POLY_BUILDER_API_KEY"),
secret=os.getenv("POLY_BUILDER_SECRET"),
passphrase=os.getenv("POLY_BUILDER_PASSPHRASE"),
)
)
client = RelayClient(
"https://relayer-v2.polymarket.com",
137,
private_key,
builder_config
)
```
</CodeGroup>
<Warning>
Never commit credentials to version control. Use environment variables or a secrets manager.
</Warning>
</Tab>
</Tabs>
***
## Authentication Headers
The SDK automatically generates and attaches these headers to each request:
| Header | Description |
| ------------------------- | ------------------------------------ |
| `POLY_BUILDER_API_KEY` | Your builder API key |
| `POLY_BUILDER_TIMESTAMP` | Unix timestamp of signature creation |
| `POLY_BUILDER_PASSPHRASE` | Your builder passphrase |
| `POLY_BUILDER_SIGNATURE` | HMAC signature of the request |
<Info>
With **local signing**, the SDK constructs and attaches these headers automatically. With **remote signing**, your server must return these headers (see Server Implementation above), and the SDK attaches them to the request.
</Info>
***
## Wallet Types
Choose your wallet type before using the relayer:
<Tabs>
<Tab title="Safe Wallets">
Gnosis Safe-based proxy wallets that require explicit deployment before use.
* **Best for:** Most builder integrations
* **Deployment:** Call `client.deploy()` before first transaction
* **Gas fees:** Paid by Polymarket
<CodeGroup>
```typescript TypeScript theme={null}
const client = new RelayClient(
"https://relayer-v2.polymarket.com",
137,
eoaSigner,
builderConfig,
RelayerTxType.SAFE // Default
);
// Deploy before first use
const response = await client.deploy();
const result = await response.wait();
console.log("Safe Address:", result?.proxyAddress);
```
```python Python theme={null}
from py_builder_relayer_client.client import RelayClient, RelayerTxType
client = RelayClient(
"https://relayer-v2.polymarket.com",
137,
private_key,
builder_config,
RelayerTxType.SAFE # Default
)
# Deploy before first use
response = client.deploy()
result = response.wait()
print(f"Safe Address: {result.proxy_address}")
```
</CodeGroup>
</Tab>
<Tab title="Proxy Wallets">
Custom Polymarket proxy wallets that auto-deploy on first transaction.
* **Used for:** Magic Link users from Polymarket.com
* **Deployment:** Automatic on first transaction
* **Gas fees:** Paid by Polymarket
<CodeGroup>
```typescript TypeScript theme={null}
const client = new RelayClient(
"https://relayer-v2.polymarket.com",
137,
eoaSigner,
builderConfig,
RelayerTxType.PROXY
);
// No deploy() needed - auto-deploys on first tx
await client.execute([transaction], "First transaction");
```
```python Python theme={null}
from py_builder_relayer_client.client import RelayClient, RelayerTxType
client = RelayClient(
"https://relayer-v2.polymarket.com",
137,
private_key,
builder_config,
RelayerTxType.PROXY
)
# No deploy() needed - auto-deploys on first tx
client.execute([transaction], "First transaction")
```
</CodeGroup>
</Tab>
</Tabs>
<Accordion title="Wallet Comparison Table">
| Feature | Safe Wallets | Proxy Wallets |
| ----------------- | :-----------------: | :---------------------: |
| Deployment | Explicit `deploy()` | Auto-deploy on first tx |
| Gas Fees | Polymarket pays | Polymarket pays |
| ERC20 Approvals | ✅ | ✅ |
| CTF Operations | ✅ | ✅ |
| Send Transactions | ✅ | ✅ |
</Accordion>
***
## Usage
### Deploy a Wallet
For Safe wallets, deploy before executing transactions:
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.deploy();
const result = await response.wait();
if (result) {
console.log("Safe deployed successfully!");
console.log("Transaction Hash:", result.transactionHash);
console.log("Safe Address:", result.proxyAddress);
}
```
```python Python theme={null}
response = client.deploy()
result = response.wait()
if result:
print("Safe deployed successfully!")
print(f"Transaction Hash: {result.transaction_hash}")
print(f"Safe Address: {result.proxy_address}")
```
</CodeGroup>
### Execute Transactions
The `execute` method sends transactions through the relayer. Pass an array of transactions to batch multiple operations in a single call.
<CodeGroup>
```typescript TypeScript theme={null}
interface Transaction {
to: string; // Target contract or wallet address
data: string; // Encoded function call (use "0x" for simple transfers)
value: string; // Amount of MATIC to send (usually "0")
}
const response = await client.execute(transactions, "Description");
const result = await response.wait();
if (result) {
console.log("Transaction confirmed:", result.transactionHash);
}
```
```python Python theme={null}
# Transaction dict format:
# { "to": str, "data": str, "value": str }
response = client.execute(transactions, "Description")
result = response.wait()
if result:
print(f"Transaction confirmed: {result.transaction_hash}")
```
</CodeGroup>
### Transaction Examples
<Tabs>
<Tab title="Transfer">
Transfer tokens to any address (e.g., withdrawals):
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData, parseUnits } from "viem";
const transferTx = {
to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDCe
data: encodeFunctionData({
abi: [{
name: "transfer",
type: "function",
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" }
],
outputs: [{ type: "bool" }]
}],
functionName: "transfer",
args: [
"0xRecipientAddressHere",
parseUnits("100", 6) // 100 USDCe (6 decimals)
]
}),
value: "0"
};
const response = await client.execute([transferTx], "Transfer USDCe");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
USDC_E = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
transfer_tx = {
"to": USDC_E,
"data": Web3().eth.contract(
address=USDC_E,
abi=[{"name": "transfer", "type": "function", "inputs": [{"name": "to", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]}]
).encode_abi(abi_element_identifier="transfer", args=["0xRecipientAddressHere", 100 * 10**6]),
"value": "0"
}
response = client.execute([transfer_tx], "Transfer USDCe")
response.wait()
```
</CodeGroup>
</Tab>
<Tab title="Approve">
Set token allowances to enable trading:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData, maxUint256 } from "viem";
const approveTx = {
to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDCe
data: encodeFunctionData({
abi: [{
name: "approve",
type: "function",
inputs: [
{ name: "spender", type: "address" },
{ name: "amount", type: "uint256" }
],
outputs: [{ type: "bool" }]
}],
functionName: "approve",
args: [
"0x4d97dcd97ec945f40cf65f87097ace5ea0476045", // CTF
maxUint256
]
}),
value: "0"
};
const response = await client.execute([approveTx], "Approve USDCe for CTF");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
USDC_E = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045"
MAX_UINT256 = 2**256 - 1
approve_tx = {
"to": USDC_E,
"data": Web3().eth.contract(
address=USDC_E,
abi=[{"name": "approve", "type": "function", "inputs": [{"name": "spender", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]}]
).encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
"value": "0"
}
response = client.execute([approve_tx], "Approve USDCe for CTF")
response.wait()
```
</CodeGroup>
</Tab>
<Tab title="Redeem Positions">
Redeem winning conditional tokens after market resolution:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData } from "viem";
const redeemTx = {
to: ctfAddress,
data: encodeFunctionData({
abi: [{
name: "redeemPositions",
type: "function",
inputs: [
{ name: "collateralToken", type: "address" },
{ name: "parentCollectionId", type: "bytes32" },
{ name: "conditionId", type: "bytes32" },
{ name: "indexSets", type: "uint256[]" }
],
outputs: []
}],
functionName: "redeemPositions",
args: [collateralToken, parentCollectionId, conditionId, indexSets]
}),
value: "0"
};
const response = await client.execute([redeemTx], "Redeem positions");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045"
redeem_tx = {
"to": CTF,
"data": Web3().eth.contract(
address=CTF,
abi=[{"name": "redeemPositions", "type": "function", "inputs": [{"name": "collateralToken", "type": "address"}, {"name": "parentCollectionId", "type": "bytes32"}, {"name": "conditionId", "type": "bytes32"}, {"name": "indexSets", "type": "uint256[]"}], "outputs": []}]
).encode_abi(abi_element_identifier="redeemPositions", args=[collateral_token, parent_collection_id, condition_id, index_sets]),
"value": "0"
}
response = client.execute([redeem_tx], "Redeem positions")
response.wait()
```
</CodeGroup>
</Tab>
<Tab title="Split Positions">
Split collateral tokens into conditional outcome tokens:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData } from "viem";
const splitTx = {
to: ctfAddress,
data: encodeFunctionData({
abi: [{
name: "splitPosition",
type: "function",
inputs: [
{ name: "collateralToken", type: "address" },
{ name: "parentCollectionId", type: "bytes32" },
{ name: "conditionId", type: "bytes32" },
{ name: "partition", type: "uint256[]" },
{ name: "amount", type: "uint256" }
],
outputs: []
}],
functionName: "splitPosition",
args: [collateralToken, parentCollectionId, conditionId, partition, amount]
}),
value: "0"
};
const response = await client.execute([splitTx], "Split positions");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045"
split_tx = {
"to": CTF,
"data": Web3().eth.contract(
address=CTF,
abi=[{"name": "splitPosition", "type": "function", "inputs": [{"name": "collateralToken", "type": "address"}, {"name": "parentCollectionId", "type": "bytes32"}, {"name": "conditionId", "type": "bytes32"}, {"name": "partition", "type": "uint256[]"}, {"name": "amount", "type": "uint256"}], "outputs": []}]
).encode_abi(abi_element_identifier="splitPosition", args=[collateral_token, parent_collection_id, condition_id, partition, amount]),
"value": "0"
}
response = client.execute([split_tx], "Split positions")
response.wait()
```
</CodeGroup>
</Tab>
<Tab title="Merge Positions">
Merge conditional tokens back into collateral:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData } from "viem";
const mergeTx = {
to: ctfAddress,
data: encodeFunctionData({
abi: [{
name: "mergePositions",
type: "function",
inputs: [
{ name: "collateralToken", type: "address" },
{ name: "parentCollectionId", type: "bytes32" },
{ name: "conditionId", type: "bytes32" },
{ name: "partition", type: "uint256[]" },
{ name: "amount", type: "uint256" }
],
outputs: []
}],
functionName: "mergePositions",
args: [collateralToken, parentCollectionId, conditionId, partition, amount]
}),
value: "0"
};
const response = await client.execute([mergeTx], "Merge positions");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045"
merge_tx = {
"to": CTF,
"data": Web3().eth.contract(
address=CTF,
abi=[{"name": "mergePositions", "type": "function", "inputs": [{"name": "collateralToken", "type": "address"}, {"name": "parentCollectionId", "type": "bytes32"}, {"name": "conditionId", "type": "bytes32"}, {"name": "partition", "type": "uint256[]"}, {"name": "amount", "type": "uint256"}], "outputs": []}]
).encode_abi(abi_element_identifier="mergePositions", args=[collateral_token, parent_collection_id, condition_id, partition, amount]),
"value": "0"
}
response = client.execute([merge_tx], "Merge positions")
response.wait()
```
</CodeGroup>
</Tab>
<Tab title="Batch Transactions">
Execute multiple transactions atomically in a single call:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData, parseUnits, maxUint256 } from "viem";
const erc20Abi = [
{
name: "approve",
type: "function",
inputs: [
{ name: "spender", type: "address" },
{ name: "amount", type: "uint256" }
],
outputs: [{ type: "bool" }]
},
{
name: "transfer",
type: "function",
inputs: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" }
],
outputs: [{ type: "bool" }]
}
] as const;
// Approve CTF to spend USDCe
const approveTx = {
to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
data: encodeFunctionData({
abi: erc20Abi,
functionName: "approve",
args: ["0x4d97dcd97ec945f40cf65f87097ace5ea0476045", maxUint256]
}),
value: "0"
};
// Transfer some USDCe to another wallet
const transferTx = {
to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
data: encodeFunctionData({
abi: erc20Abi,
functionName: "transfer",
args: ["0xRecipientAddressHere", parseUnits("50", 6)]
}),
value: "0"
};
// Both transactions execute in one call
const response = await client.execute(
[approveTx, transferTx],
"Approve and transfer"
);
await response.wait();
```
```python Python theme={null}
from web3 import Web3
USDC_E = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045"
MAX_UINT256 = 2**256 - 1
erc20_abi = [
{"name": "approve", "type": "function", "inputs": [{"name": "spender", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]},
{"name": "transfer", "type": "function", "inputs": [{"name": "to", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]}
]
contract = Web3().eth.contract(address=USDC_E, abi=erc20_abi)
# Approve CTF to spend USDCe
approve_tx = {
"to": USDC_E,
"data": contract.encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
"value": "0"
}
# Transfer some USDCe to another wallet
transfer_tx = {
"to": USDC_E,
"data": contract.encode_abi(abi_element_identifier="transfer", args=["0xRecipientAddressHere", 50 * 10**6]),
"value": "0"
}
# Both transactions execute in one call
response = client.execute([approve_tx, transfer_tx], "Approve and transfer")
response.wait()
```
</CodeGroup>
<Info>
Batching reduces latency and ensures all transactions succeed or fail together.
</Info>
</Tab>
</Tabs>
***
## Reference
### Contracts & Approvals
| Contract | Address | USDCe | Outcome Tokens |
| --------------------- | -------------------------------------------- | :---: | :------------: |
| USDCe | `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` | — | — |
| CTF | `0x4d97dcd97ec945f40cf65f87097ace5ea0476045` | ✅ | — |
| CTF Exchange | `0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E` | ✅ | ✅ |
| Neg Risk CTF Exchange | `0xC5d563A36AE78145C45a50134d48A1215220f80a` | ✅ | ✅ |
| Neg Risk Adapter | `0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296` | — | ✅ |
### Transaction States
| State | Description |
| ----------------- | -------------------------------------------- |
| `STATE_NEW` | Transaction received by relayer |
| `STATE_EXECUTED` | Transaction executed onchain |
| `STATE_MINED` | Transaction included in a block |
| `STATE_CONFIRMED` | Transaction confirmed (final ✅) |
| `STATE_FAILED` | Transaction failed (terminal ❌) |
| `STATE_INVALID` | Transaction rejected as invalid (terminal ❌) |
### TypeScript Types
<Accordion title="View Type Definitions">
```typescript theme={null}
// Transaction type used in all examples
interface Transaction {
to: string;
data: string;
value: string;
}
// Wallet type selector
enum RelayerTxType {
SAFE = "SAFE",
PROXY = "PROXY"
}
// Transaction states
enum RelayerTransactionState {
STATE_NEW = "STATE_NEW",
STATE_EXECUTED = "STATE_EXECUTED",
STATE_MINED = "STATE_MINED",
STATE_CONFIRMED = "STATE_CONFIRMED",
STATE_FAILED = "STATE_FAILED",
STATE_INVALID = "STATE_INVALID"
}
// Response from relayer
interface RelayerTransaction {
transactionID: string;
transactionHash: string;
from: string;
to: string;
proxyAddress: string;
data: string;
state: string;
type: string;
metadata: string;
createdAt: Date;
updatedAt: Date;
}
```
</Accordion>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Order Attribution" icon="tag" href="/developers/builders/order-attribution">
Attribute orders to your builder account
</Card>
<Card title="Example Apps" icon="code" href="/developers/builders/examples">
Complete integration examples
</Card>
</CardGroup>