Prepare an integrator fee claim
curl --request POST \
--url https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim \
--header 'Content-Type: application/json' \
--data '
{
"chainId": "<string>",
"recipient": "<string>",
"amountUsd": 123
}
'import requests
url = "https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim"
payload = {
"chainId": "<string>",
"recipient": "<string>",
"amountUsd": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({chainId: '<string>', recipient: '<string>', amountUsd: 123})
};
fetch('https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/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://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/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([
'chainId' => '<string>',
'recipient' => '<string>',
'amountUsd' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim"
payload := strings.NewReader("{\n \"chainId\": \"<string>\",\n \"recipient\": \"<string>\",\n \"amountUsd\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
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://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim")
.header("Content-Type", "application/json")
.body("{\n \"chainId\": \"<string>\",\n \"recipient\": \"<string>\",\n \"amountUsd\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainId\": \"<string>\",\n \"recipient\": \"<string>\",\n \"amountUsd\": 123\n}"
response = http.request(request)
puts response.read_body{
"data": {
"claimId": "<string>",
"message": "<string>",
"signatureKind": "eip191",
"amountUsd": 123,
"networkFeeUsd": 123,
"receive": {
"amount": "<string>",
"amountRaw": "<string>",
"token": {
"chainId": "<string>",
"address": "<string>",
"symbol": "<string>",
"decimals": 123
}
},
"recipient": "<string>",
"expiresAt": "<string>"
}
}{
"message": "<string>"
}Bridge Integrator Fee Claim
[Alpha Preview] Prepare a claim on an integrator fee balance: priced payout plus the message the fee wallet signs.
POST
/
2
/
bridge
/
integrator-fees
/
{address}
/
claim
Prepare an integrator fee claim
curl --request POST \
--url https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim \
--header 'Content-Type: application/json' \
--data '
{
"chainId": "<string>",
"recipient": "<string>",
"amountUsd": 123
}
'import requests
url = "https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim"
payload = {
"chainId": "<string>",
"recipient": "<string>",
"amountUsd": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({chainId: '<string>', recipient: '<string>', amountUsd: 123})
};
fetch('https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/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://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/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([
'chainId' => '<string>',
'recipient' => '<string>',
'amountUsd' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim"
payload := strings.NewReader("{\n \"chainId\": \"<string>\",\n \"recipient\": \"<string>\",\n \"amountUsd\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
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://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim")
.header("Content-Type", "application/json")
.body("{\n \"chainId\": \"<string>\",\n \"recipient\": \"<string>\",\n \"amountUsd\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://demo-api.mobula.io/api/2/bridge/integrator-fees/{address}/claim")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"chainId\": \"<string>\",\n \"recipient\": \"<string>\",\n \"amountUsd\": 123\n}"
response = http.request(request)
puts response.read_body{
"data": {
"claimId": "<string>",
"message": "<string>",
"signatureKind": "eip191",
"amountUsd": 123,
"networkFeeUsd": 123,
"receive": {
"amount": "<string>",
"amountRaw": "<string>",
"token": {
"chainId": "<string>",
"address": "<string>",
"symbol": "<string>",
"decimals": 123
}
},
"recipient": "<string>",
"expiresAt": "<string>"
}
}{
"message": "<string>"
}Alpha Preview — Endpoints and response shape may change without notice.
POST /api/2/bridge/integrator-fees/{address}/claim prices a USDC payout from
the fee wallet’s balance
and returns the message to sign. Nothing is reserved yet: the balance is only
debited when you submit
the signature.
Path parameter
| Name | Notes |
|---|---|
address | The fee wallet whose balance is claimed. It is also the signer. |
Request body
| Field | Required | Notes |
|---|---|---|
chainId | yes | Where the USDC is paid: an EVM bridge chain (e.g. evm:8453, evm:42161) or solana:solana. Not HyperLiquid. |
recipient | no | Who receives the USDC, in that chain’s address format. Defaults to the fee wallet itself, so set it when claiming an EVM balance on Solana or the other way round. |
amountUsd | no | USD taken from the balance. Defaults to the whole available balance. |
{ "chainId": "evm:8453", "amountUsd": 120.5 }
Response
{
"data": {
"claimId": "6f1c2a9e-4b7d-4c1e-9a53-2d8f0e7b1c44",
"message": "Mobula Bridge: claim integrator fees\nWallet: 0xyourfeewallet\nAmount: 120.500000 USD\nNetwork fee: 0.004100 USD\nReceive: 120.4959 USDC on evm:8453\nRecipient: 0xYourFeeWallet\nClaim: 6f1c2a9e-4b7d-4c1e-9a53-2d8f0e7b1c44\nExpires: 2026-10-21T09:12:03.000Z",
"signatureKind": "eip191",
"amountUsd": 120.5,
"networkFeeUsd": 0.0041,
"receive": {
"amount": "120.4959",
"amountRaw": "120495900",
"token": {
"chainId": "evm:8453",
"address": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"symbol": "USDC",
"decimals": 6
}
},
"recipient": "0xYourFeeWallet",
"expiresAt": "2026-10-21T09:12:03.000Z"
}
}
networkFeeUsd— what the payout transaction costs onchainId, at live gas (plus the USDC account rent on Solana when the recipient has none). It is deducted from what is sent: you receiveamountUsd − networkFeeUsd.receive— the exact USDC amount sent, human and raw.expiresAt— the claim can be signed and submitted for 24 hours, enough for a multisig to gather its signatures.
Signing
Signmessage exactly as returned, with the fee wallet:
- EVM wallet (
signatureKind: "eip191") —personal_sign, e.g.walletClient.signMessage({ account, message })in viem. Submit the0x…hex. - Safe or other contract wallet — sign
messageas an off-chain message (EIP-1271) and submit the combined signature once enough owners have signed. It is checked withisValidSignatureonchainId, or on Base (evm:8453) when the payout is on Solana, so the Safe must be deployed on that chain. - Solana wallet (
signatureKind: "ed25519") —signMessageover the UTF-8 bytes ofmessage. Submit the 64-byte signature base58-encoded.
// Solana wallet adapter
const sig = await wallet.signMessage(new TextEncoder().encode(prepared.message));
const signature = bs58.encode(sig);
Errors
Errors return HTTP400 with a message:
| Case | message |
|---|---|
| Unsupported payout chain | Claims pay USDC on EVM bridge chains and solana:solana, not … |
| Wrong recipient format | recipient must be a … address on … |
amountUsd above the balance | Balance is $…, below $… |
| Less than $1 left after the network fee | A claim must pay out at least $1 after the $… network fee on … |
| No live gas price on the chain | No gas price available on … right now — retry shortly |
Path Parameters
The fee wallet whose balance is claimed. It is also the signer.
Body
application/json
Response
The priced claim and the message to sign.
Show child attributes
Show child attributes