https://xcatcher.top/api/v1/mcp/healthAuthorization: Bearer xc_live_...Public endpoint, no auth required.
BASE="https://xcatcher.top" curl -sS "$BASE/mcp/health" echo
Quotes expire quickly. Pay immediately after receiving the quote.
BASE="https://xcatcher.top"
POINTS=1
curl -sS "$BASE/api/v1/x402/quote?points=$POINTS" | tee quote.json
echo
QUOTE_ID=$(jq -r '.quote_id' quote.json)
USDC_MINT=$(jq -r '.accepts.solana.asset' quote.json)
PAY_TO=$(jq -r '.accepts.solana.payTo' quote.json)
AMOUNT_ATOMIC=$(jq -r '.accepts.solana.maxAmountRequired' quote.json)
echo "QUOTE_ID=$QUOTE_ID"
echo "USDC_MINT=$USDC_MINT"
echo "PAY_TO=$PAY_TO"
echo "AMOUNT_ATOMIC=$AMOUNT_ATOMIC"
echo "USDC_AMOUNT=$(python3 - <<'PY'
import json
q=json.load(open("quote.json"))
amt=int(q["accepts"]["solana"]["maxAmountRequired"])
print(amt/1_000_000)
PY
)"
echo
Send USDC (SPL) to PAY_TO for at least AMOUNT_ATOMIC (USDC has 6 decimals). Record the Solana tx signature.
# Send SPL USDC to PAY_TO for >= AMOUNT_ATOMIC # Then set: SOL_SIG="YOUR_SOLANA_TX_SIGNATURE"
Base64 encode once (no double encoding). Output must be single line.
SOL_SIG="YOUR_SOLANA_TX_SIGNATURE"
PAYMENT_SIGNATURE_B64=$(jq -nc --arg sig "$SOL_SIG" \
'{"x402Version":1,"scheme":"exact","network":"solana:mainnet","payload":{"signature":$sig}}' \
| base64 | tr -d '\n')
echo "PAYMENT_SIGNATURE_B64=$PAYMENT_SIGNATURE_B64"
echo
This returns an api_key. Export it as XCATCHER_API_KEY.
BASE="https://xcatcher.top"
curl -sS -X POST "$BASE/api/v1/x402/buy_points" \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: $PAYMENT_SIGNATURE_B64" \
-d "$(jq -nc --arg q "$QUOTE_ID" '{quote_id:$q}')" \
| tee buy.json
echo
API_KEY=$(jq -r '.api_key' buy.json)
echo "API_KEY=$API_KEY"
export XCATCHER_API_KEY="$API_KEY"
echo "XCATCHER_API_KEY exported."
echo
Always verify the key works before creating tasks.
BASE="https://xcatcher.top" curl -sS "$BASE/api/v1/me" \ -H "Authorization: Bearer $XCATCHER_API_KEY" \ | jq . echo # If you get 402: # - Most common causes: quote expired or payment proof invalid. # - Fix: redo steps 1 → 4 with a NEW quote and NEW payment.
Rules: users are X usernames without '@'; always provide idempotency_key.
BASE="https://xcatcher.top"
MODE="normal" # normal|deep
IDEM="test-idem-001"
USERS_JSON='["user1","user2"]'
echo "ESTIMATED_COST_POINTS=$(python3 - <<'PY'
import json, os
users=json.loads(os.environ.get("USERS_JSON","[]"))
mode=os.environ.get("MODE","normal")
per=1 if mode=="normal" else 10
print(len(users)*per)
PY
)"
echo
curl -sS -X POST "$BASE/api/v1/tasks" \
-H "Authorization: Bearer $XCATCHER_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg mode "$MODE" --arg idem "$IDEM" --argjson users "$USERS_JSON" \
'{mode:$mode, users:$users, idempotency_key:$idem}')" \
| tee task.json | jq .
echo
TASK_ID=$(jq -r '.task_id' task.json)
echo "TASK_ID=$TASK_ID"
echo
Stop when download_url or result_path is present.
BASE="https://xcatcher.top"
while true; do
J=$(curl -sS "$BASE/api/v1/tasks/$TASK_ID" -H "Authorization: Bearer $XCATCHER_API_KEY")
echo "$J" | jq '{task_id,status,status_code,updated_time,error_message,result_path,download_url}'
HAS=$(echo "$J" | jq -r '(.download_url // .result_path // "") | length')
if [ "$HAS" -gt 0 ]; then
echo "DONE"
break
fi
sleep 5
done
echo
Download requires the same Bearer token; results are not public.
BASE="https://xcatcher.top"
curl -sS -L -o "task_${TASK_ID}.xlsx" \
-H "Authorization: Bearer $XCATCHER_API_KEY" \
"$BASE/api/v1/tasks/$TASK_ID/download"
echo "Saved: task_${TASK_ID}.xlsx"
echo
Header value is base64(UTF-8 JSON).
{
"x402Version": 1,
"scheme": "exact",
"network": "solana:mainnet",
"payload": {
"signature": "YOUR_SOLANA_TX_SIGNATURE"
}
}
For planning only: