curl --request POST \
--url https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim \
--header 'Content-Type: application/json' \
--header 'X-Monaco-Signature: <api-key>' \
--data '
{
"token": "0x0000000000000000000000000000000000000002",
"amount": "1000000"
}
'import requests
url = "https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim"
payload = {
"token": "0x0000000000000000000000000000000000000002",
"amount": "1000000"
}
headers = {
"X-Monaco-Signature": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Monaco-Signature': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({token: '0x0000000000000000000000000000000000000002', amount: '1000000'})
};
fetch('https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim', 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://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'token' => '0x0000000000000000000000000000000000000002',
'amount' => '1000000'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Monaco-Signature: <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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim"
payload := strings.NewReader("{\n \"token\": \"0x0000000000000000000000000000000000000002\",\n \"amount\": \"1000000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Monaco-Signature", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim")
.header("X-Monaco-Signature", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"token\": \"0x0000000000000000000000000000000000000002\",\n \"amount\": \"1000000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Monaco-Signature"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"token\": \"0x0000000000000000000000000000000000000002\",\n \"amount\": \"1000000\"\n}"
response = http.request(request)
puts response.read_body{
"payoutBalance": "0",
"tradingBalance": "1000000"
}Claim accrued BuilderCodes payout balance
Claim accrued BuilderCodes payout balance.
Move accrued BuilderCodes payout balance from your reserved payout bucket into a trading balance under the authenticated application, making it withdrawable through the ordinary withdrawal flow. Ledger-only (one shared vault + one backend ledger) — no on-chain transaction and no gas.
The bucket is resolved from the AUTHENTICATED caller’s own wallet address, never from the request body, so a caller can only ever claim their own accrued balance. A wallet that has never been an enrolled frontend’s payout address simply has an empty bucket. A wallet that USED to be a payout address keeps whatever it accrued back then and can still claim it — payout-address changes are not retroactive, so current enrollment is deliberately not required.
The payout wallet may be an EOA or a smart-contract wallet. An EOA answers
Monaco’s signature challenge directly. A contract wallet — a multisig such
as a Safe — holds no private key and cannot, so it authenticates by EIP-1271
contract signature instead: Monaco asks the wallet contract whether it
accepts the challenge. That path is deliberately narrow. It is offered only
to a wallet that holds a BuilderCodes payout bucket, only while the
contract_wallet_auth_enabled flag is on, and only where the deployment has
a chain RPC endpoint configured. While any of those is not met, login is
EOA-only and a contract payout wallet can neither call this endpoint nor
withdraw afterwards, so its accrued share stays unclaimable.
Delegated-agent sessions are refused: a delegated grant conveys only order-management authority, and this claim converts reserved balance into a tradeable one. No program switch gates the claim: a balance already credited stays claimable whether or not the revenue share is on.
Transport contracts differ, and this comment is emitted into the generated gRPC SDK where HTTP statuses do not exist. An insufficient payout balance is HTTP 409 on REST and FAILED_PRECONDITION on gRPC; a refused caller (delegated session) is HTTP 403 on REST and PERMISSION_DENIED on gRPC.
A claim can also fail as HTTP 503 / UNAVAILABLE when the matching engine is unreachable, restarting, or slow to answer. Treat that as an UNKNOWN outcome, NOT a rejection. The request is admitted to the sequencer before its reply is sent, so a claim that timed out in transit may still commit, and there is no idempotency key — a blind retry can claim a SECOND time. Do NOT retry automatically, and do not settle it with a balance read: an admitted claim can still be sitting in the sequencer queue when the balance is read, so an unchanged balance does not prove the claim will not commit. Treat the claim as PENDING rather than failed, re-check once the engine is healthy again, and reconcile before issuing another claim.
Not every 503 is ambiguous, and the safe ones are tagged. TWO outcomes are
refused BEFORE the claim can be admitted to the sequencer, so they left no
durable-log or state footprint and definitely committed nothing. One is a
deliberate maintenance block, where REST carries
"error": "OPERATIONS_BLOCKED" and gRPC tags the status with
x-maintenance-blocked: true. The other is a sequencer admission rejection
when the engine is saturated, where REST carries "code": "OVERLOADED" and
gRPC carries the same code in the status’ error details. Both are safe to
retry with backoff, and an overload positively wants one. Only an UNTAGGED
availability failure — matching-engine transport, timeout and fail-closed
paths — carries the unknown outcome.
A claim spends the per-user movement budget withdrawals and collateral
transfers share. Over budget it is refused with HTTP 429 /
RESOURCE_EXHAUSTED before it reaches the sequencer, so it committed
nothing and is safe to retry after the interval in details.retryAfter.
curl --request POST \
--url https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim \
--header 'Content-Type: application/json' \
--header 'X-Monaco-Signature: <api-key>' \
--data '
{
"token": "0x0000000000000000000000000000000000000002",
"amount": "1000000"
}
'import requests
url = "https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim"
payload = {
"token": "0x0000000000000000000000000000000000000002",
"amount": "1000000"
}
headers = {
"X-Monaco-Signature": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Monaco-Signature': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({token: '0x0000000000000000000000000000000000000002', amount: '1000000'})
};
fetch('https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim', 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://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'token' => '0x0000000000000000000000000000000000000002',
'amount' => '1000000'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Monaco-Signature: <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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim"
payload := strings.NewReader("{\n \"token\": \"0x0000000000000000000000000000000000000002\",\n \"amount\": \"1000000\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Monaco-Signature", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim")
.header("X-Monaco-Signature", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"token\": \"0x0000000000000000000000000000000000000002\",\n \"amount\": \"1000000\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://staging.apimonaco.xyz/api/v1/buildercodes/rewards/claim")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Monaco-Signature"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"token\": \"0x0000000000000000000000000000000000000002\",\n \"amount\": \"1000000\"\n}"
response = http.request(request)
puts response.read_body{
"payoutBalance": "0",
"tradingBalance": "1000000"
}Authorizations
Ed25519 session-key request signing. Every authenticated request carries three headers: X-Monaco-PublicKey (64-char lowercase-hex session public key), X-Monaco-Timestamp (Unix milliseconds, within 30s of server time), and X-Monaco-Signature (hex ed25519 signature). The signature is over METHOD\npath?query\ntimestamp_ms\nSHA256_hex(body), where the body hash is the SHA-256 of the empty byte string when there is no body. Obtain the session keypair from POST /api/v1/auth/challenge followed by POST /api/v1/auth/verify.
Body
Payout token contract address (0x-prefixed) to claim. BuilderCodes shares accrue in the quote token of the traded pair.
"0x0000000000000000000000000000000000000002"
Amount to claim, in RAW atomic units of the token. Must be positive and no greater than the accrued payout balance.
"1000000"
Was this page helpful?

