curl --request GET \
--url https://api.arcus.xyz/v1/affiliate/info \
--header 'X-API-Key: <api-key>' \
--header 'X-Signature: <api-key>' \
--header 'X-Timestamp: <api-key>'import requests
url = "https://api.arcus.xyz/v1/affiliate/info"
headers = {
"X-API-Key": "<api-key>",
"X-Timestamp": "<api-key>",
"X-Signature": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-API-Key': '<api-key>',
'X-Timestamp': '<api-key>',
'X-Signature': '<api-key>'
}
};
fetch('https://api.arcus.xyz/v1/affiliate/info', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcus.xyz/v1/affiliate/info",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>",
"X-Signature: <api-key>",
"X-Timestamp: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.arcus.xyz/v1/affiliate/info"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("X-Timestamp", "<api-key>")
req.Header.Add("X-Signature", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.arcus.xyz/v1/affiliate/info")
.header("X-API-Key", "<api-key>")
.header("X-Timestamp", "<api-key>")
.header("X-Signature", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcus.xyz/v1/affiliate/info")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
request["X-Timestamp"] = '<api-key>'
request["X-Signature"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"address": "<string>",
"code": "<string>",
"kickbackBps": 123,
"tier": 123,
"totalCommission": 123,
"pendingCommission": 123,
"volume30d": 123,
"totalReferredVolume30d": 123,
"totalReferredVolumeAllTime": 123,
"commission30d": 123,
"tradingFeeTier": {
"level": 123,
"makerFeePpm": 123,
"takerFeePpm": 123
}
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "rate limited",
"reason": "account_empty",
"retryAfterMs": 850,
"clientId": "my-order-42"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}Get affiliate info
Returns the caller’s own affiliate information including code, tier, commission totals, and referee count.
curl --request GET \
--url https://api.arcus.xyz/v1/affiliate/info \
--header 'X-API-Key: <api-key>' \
--header 'X-Signature: <api-key>' \
--header 'X-Timestamp: <api-key>'import requests
url = "https://api.arcus.xyz/v1/affiliate/info"
headers = {
"X-API-Key": "<api-key>",
"X-Timestamp": "<api-key>",
"X-Signature": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-API-Key': '<api-key>',
'X-Timestamp': '<api-key>',
'X-Signature': '<api-key>'
}
};
fetch('https://api.arcus.xyz/v1/affiliate/info', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcus.xyz/v1/affiliate/info",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>",
"X-Signature: <api-key>",
"X-Timestamp: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.arcus.xyz/v1/affiliate/info"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("X-Timestamp", "<api-key>")
req.Header.Add("X-Signature", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.arcus.xyz/v1/affiliate/info")
.header("X-API-Key", "<api-key>")
.header("X-Timestamp", "<api-key>")
.header("X-Signature", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcus.xyz/v1/affiliate/info")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
request["X-Timestamp"] = '<api-key>'
request["X-Signature"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"address": "<string>",
"code": "<string>",
"kickbackBps": 123,
"tier": 123,
"totalCommission": 123,
"pendingCommission": 123,
"volume30d": 123,
"totalReferredVolume30d": 123,
"totalReferredVolumeAllTime": 123,
"commission30d": 123,
"tradingFeeTier": {
"level": 123,
"makerFeePpm": 123,
"takerFeePpm": 123
}
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "rate limited",
"reason": "account_empty",
"retryAfterMs": 850,
"clientId": "my-order-42"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}{
"error": "Invalid request body",
"code": "GEO_RESTRICTED",
"errorSource": "Order",
"errorType": "Tick",
"rejectionReason": "POST_ONLY_WOULD_CROSS"
}address must be the API key’s master Ethereum address; reading another wallet’s affiliate info is 403. The Ed25519 request signature is required because X-API-Key alone proves nothing (API keys are Ed25519 public keys, listable by anyone via GET /v1/apiKeys). With no request body the signing message is timestamp + action (action info — the path segment verbatim, casing included).Authorizations
Hex-encoded Ed25519 public key (64 chars). The public key IS the API key — register it via POST /createApiKey. Required on every authenticated request, both read-only and signed.
Unix time in nanoseconds as a decimal string (e.g. "1713825891591000000"). Millisecond or second epochs are rejected with 401 Unauthorized. Must be within ±30,000 ms of server wall-clock, or the request is rejected with 401 Unauthorized. Required on all mutating / credential-creating endpoints. This same value must appear as the ct field in the ordersign typed canonical payload (single-order endpoints) or in each element's ct field (batch endpoints).
Lowercase hex-encoded Ed25519 signature (128 chars).
Single-order endpoints (placeOrder, cancelOrder, modifyOrder, and other non-batch mutating routes) sign over the ordersign typed canonical payload — a compact, key-sorted JSON object built from parsed request fields using engine-native integer values:
placeOrder: {"ad":"0x…","ai":N,[,"c":"…"],"ct":N,"g":N,"m":N,"op":1,"p":N,"q":N,"r":0|1,"s":N,"t":N,"v":1} cancelOrder: {"ad":"0x…","ai":N,[,"c":"…"],"ct":N,[,"id":"…"],"m":N,"op":2,"v":1} modifyOrder: {"ad":"0x…","ai":N,[,"c":"…"],"ct":N,"g":N,[,"id":"…"],"m":N,"op":3,"p":N,"q":N,"r":0|1,"s":N,"t":N,"v":1} (exactly one of id / c)
ct must equal the X-Timestamp header value. Keys in brackets are conditional (omitted when empty). op values: 1=place, 2=cancel, 3=modify. See the ordersign package for field definitions and reference signing code.
Other signed routes (e.g. createApiKey) still use the legacy scheme: signing_message = X-Timestamp + ACTION + canonicalJSON(body), where ACTION is the camelCase final path segment.
Batch endpoints (batchPlaceOrders, batchCancelOrders, batchModifyOrders) do NOT use this header. They authenticate with per-element typed ordersign signatures embedded in the request body (see the global auth description and the per-field signature descriptions on OrderRequest / CancelOrderRequest / ModifyOrderRequest).
Read endpoints are authenticated by ?address= (and optionally X-API-Key) only — no signature is required, except for the signed affiliate reads (see the Referral tag), which require the full header triple; with no body their signing message is X-Timestamp + ACTION. canonicalJSON(body) is the JSON body with object keys sorted lexicographically at every level and no whitespace; the server canonicalizes the received body before verifying, so only the bytes signed over must be canonical. Required on all mutating / credential-creating endpoints.
Query Parameters
Ethereum address of the affiliate. Must match the API key's master address.
20-byte EVM address as hex: optional 0x or 0X prefix and exactly 40 hexadecimal digits. API responses normalize to lowercase a–f after 0x.
^(0x|0X)?[0-9a-fA-F]{40}$Response
Affiliate info.
Lower-case 0x-prefixed 20-byte affiliate address.
Active referral code, or empty string if revoked / never created.
Affiliate's current kickback rate in basis points (0-5000). 0 means no kickback.
Current affiliate/account tier level used for referral commission rates. Use tradingFeeTier for the corresponding maker/taker fee BPS details.
Lifetime commission earned, in quote quantums (1e9 = $1).
Commission earned since the last claim cutoff, in quote quantums. Decreases to 0 when a ClaimProcessed event covers the full outstanding balance.
Notional fill volume over the trailing 30 days, in quote quantums. null/0 if the rollup is temporarily unavailable; the endpoint degrades gracefully rather than failing /info.
Combined trailing-30-day notional fill volume of all of this affiliate's direct (T1) referees, in quote quantums (1e9 = $1). Read from the hourly volume rollup. 0 if the rollup is temporarily unavailable; the endpoint degrades gracefully.
Combined all-time notional fill volume of all of this affiliate's current direct (T1) referees, in quote quantums (1e9 = $1). Same definition as totalReferredVolume30d but with no time window: the lifetime fills of whoever is a T1 referee right now. Read from the per-address all-time volume rollup. Trails live fills by the rollup's refresh lag. 0 if the rollup is temporarily unavailable; the endpoint degrades gracefully.
Commission earned over the trailing 30 days, in quote quantums. Computed as the lifetime commission snapshot minus the running commission total as of the window start (boundary subtraction). 0 if the rollup is temporarily unavailable; the endpoint degrades gracefully.
The user's current trading fee tier (level + maker/taker BPS). Omitted when the store has not yet recorded a tier for this address (new accounts before the first AccountFeeTierUpdate).
Show child attributes
Show child attributes
Was this page helpful?