Webhook Setup
Webhooks let your agent receive real-time notifications when swaps complete or fail, instead of polling GET /swap/status. Suwappu sends an HTTP POST request to your callback URL whenever a swap event occurs.
How It Works
1. Set your callback URL -- Update your agent profile with PATCH /me
2. Test delivery -- Send a test webhook to verify your endpoint works
3. Handle events -- Process incoming webhook payloads in your application
4. Monitor -- View recent webhook events via GET /webhooks
Step 1: Set Your Callback URL
Configure the webhook endpoint in your agent profile:
-kw">curl -X PATCH https://api.suwappu.bot/v1/agent/me \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key" \
-H -str">"Content-Type: application/json" \
-d -str">'{-str">"callback_url": -str">"https://your class="hl-flag">-server.com/webhooks/suwappu"}'
#### Response
{
"hl-key">"success": true,
"hl-key">"agent": {
"hl-key">"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"hl-key">"name": "my-trading-bot",
"hl-key">"description": "Automated portfolio rebalancer",
"hl-key">"rate_limit_tier": "standard",
"hl-key">"stats": {
"hl-key">"total_requests": 14833,
"hl-key">"total_swaps": 247
},
"hl-key">"created_at": "2026-01-15T08:30:00Z",
"hl-key">"last_active_at": "2026-03-07T14:25:00Z"
}
}
To remove the webhook, set callback_url to null:
-kw">curl -X PATCH https://api.suwappu.bot/v1/agent/me \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key" \
-H -str">"Content-Type: application/json" \
-d -str">'{-str">"callback_url": null}'
Step 2: Test Webhook Delivery
Send a test event to verify your endpoint is reachable and working:
-kw">curl -X POST https://api.suwappu.bot/v1/agent/webhooks/test \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key"
This sends a test payload to your configured callback_url. Check your server logs to confirm receipt.
Step 3: Handle Webhook Events
Event Types
| Event | Description |
|---|---|
swap.completed | A swap has been confirmed on-chain |
swap.failed | A swap transaction reverted or could not be confirmed |
Webhook Payload
Suwappu sends a POST request to your callback URL with a JSON body:
{
"hl-key">"event": "swap.completed",
"hl-key">"timestamp": "2026-03-07T14:30:00Z",
"hl-key">"data": {
"hl-key">"swap_id": 4821,
"hl-key">"status": "completed",
"hl-key">"tx_hash": "0x8a3c...f29e",
"hl-key">"from_token": "ETH",
"hl-key">"to_token": "USDC",
"hl-key">"chain": "base"
}
}
Your endpoint should return a 200 status code to acknowledge receipt. If the endpoint returns a non-2xx status or times out, Suwappu will retry delivery.
Step 4: View Webhook Events
List recent webhook deliveries for your agent:
-kw">curl https://api.suwappu.bot/v1/agent/webhooks \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key"
Complete Example: curl
API_KEY=-str">"suwappu_sk_your_api_key"
BASE=-str">"https://api.suwappu.bot/v1/agent"
-str">"hl-comment"># Set callback URL
-kw">curl -X PATCH -str">"$BASE/me" \
-H -str">"Authorization: Bearer $API_KEY" \
-H -str">"Content-Type: application/json" \
-d -str">'{-str">"callback_url": -str">"https://your class="hl-flag">-server.com/webhooks/suwappu"}'
-str">"hl-comment"># Test delivery
-kw">curl -X POST -str">"$BASE/webhooks/test" \
-H -str">"Authorization: Bearer $API_KEY"
-str">"hl-comment"># View webhook events
-kw">curl -str">"$BASE/webhooks" \
-H -str">"Authorization: Bearer $API_KEY"
Complete Example: Python Flask Receiver
A minimal webhook receiver using Flask:
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route(class="hl-str">"/webhooks/suwappu", methods=[class="hl-str">"POST"])
def handle_webhook():
payload = request.get_json()
event = payload[class="hl-str">"event"]
data = payload[class="hl-str">"data"]
if event == class="hl-str">"swap.completed":
print(fclass="hl-str">"Swap {data[class="hl-str">'swap_id']} completed!")
print(fclass="hl-str">" {data[class="hl-str">'from_token']} -> {data[class="hl-str">'to_token']} on {data[class="hl-str">'chain']}")
print(fclass="hl-str">" TX: {data[class="hl-str">'tx_hash']}")
elif event == class="hl-str">"swap.failed":
print(fclass="hl-str">"Swap {data[class="hl-str">'swap_id']} failed!")
print(fclass="hl-str">" {data[class="hl-str">'from_token']} -> {data[class="hl-str">'to_token']} on {data[class="hl-str">'chain']}")
return jsonify({class="hl-str">"received": True}), 200
if __name__ == class="hl-str">"__main__":
app.run(host=class="hl-str">"0.0.0.0", port=8080)
Install dependencies:
-kw">pip install flask
Run the receiver:
python webhook_receiver.py
Complete Example: Python Setup Script
A script that configures the webhook and tests it:
import requests
API_KEY = class="hl-str">"suwappu_sk_your_api_key"
BASE_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//api.suwappu.bot/v1/agent"
headers = {class="hl-str">"Authorization": fclass="hl-str">"Bearer {API_KEY}"}
CALLBACK_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//your-server.com/webhooks/suwappu"
class=class="hl-str">"hl-comment"># Set the callback URL
response = requests.patch(
fclass="hl-str">"{BASE_URL}/me",
headers=headers,
json={class="hl-str">"callback_url": CALLBACK_URL},
)
print(fclass="hl-str">"Callback URL set: {response.json()[class="hl-str">'success']}")
class=class="hl-str">"hl-comment"># Test delivery
response = requests.post(fclass="hl-str">"{BASE_URL}/webhooks/test", headers=headers)
print(fclass="hl-str">"Test webhook sent: {response.json()}")
class=class="hl-str">"hl-comment"># View recent events
response = requests.get(fclass="hl-str">"{BASE_URL}/webhooks", headers=headers)
events = response.json()
print(fclass="hl-str">"Recent events: {events}")
Complete Example: TypeScript
const API_KEY = class="hl-str">"suwappu_sk_your_api_key";
const BASE_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//api.suwappu.bot/v1/agent";
const headers = {
Authorization: Bearer ${API_KEY},
class="hl-str">"Content-Type": class="hl-str">"application/json",
};
const CALLBACK_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//your-server.com/webhooks/suwappu";
class=class="hl-str">"hl-comment">// Set the callback URL
const patchRes = await fetch(${BASE_URL}/me, {
method: class="hl-str">"PATCH",
headers,
body: JSON.stringify({ callback_url: CALLBACK_URL }),
});
const patchData = await patchRes.json();
console.log(Callback URL set: ${patchData.success});
class=class="hl-str">"hl-comment">// Test delivery
const testRes = await fetch(${BASE_URL}/webhooks/test, {
method: class="hl-str">"POST",
headers,
});
const testData = await testRes.json();
console.log(Test webhook sent:, testData);
class=class="hl-str">"hl-comment">// View recent events
const eventsRes = await fetch(${BASE_URL}/webhooks, {
headers: { Authorization: Bearer ${API_KEY} },
});
const events = await eventsRes.json();
console.log(class="hl-str">"Recent events:", events);
Webhook Receiver in TypeScript (Node.js)
A minimal receiver using the built-in Node.js HTTP server:
import { createServer } from class="hl-str">"node:http";
const server = createServer((req, res) => {
if (req.method === class="hl-str">"POST" && req.url === class="hl-str">"/webhooks/suwappu") {
let body = class="hl-str">"";
req.on(class="hl-str">"data", (chunk) => (body += chunk));
req.on(class="hl-str">"end", () => {
const payload = JSON.parse(body);
const { event, data } = payload;
if (event === class="hl-str">"swap.completed") {
console.log(Swap ${data.swap_id} completed! TX: ${data.tx_hash});
} else if (event === class="hl-str">"swap.failed") {
console.log(Swap ${data.swap_id} failed.);
}
res.writeHead(200, { class="hl-str">"Content-Type": class="hl-str">"application/json" });
res.end(JSON.stringify({ received: true }));
});
} else {
res.writeHead(404);
res.end();
}
});
server.listen(8080, () => console.log(class="hl-str">"Webhook receiver on :8080"));
Tips
- Use HTTPS for your callback URL. Suwappu will not deliver webhooks to plain HTTP endpoints in production.
- Respond quickly. Return a
200status code as fast as possible. Process the event asynchronously if your handler involves heavy work. - Idempotency. Webhooks may be delivered more than once. Use the
swap_idto deduplicate events. - Verify the source. Check that incoming requests originate from Suwappu by validating headers or using a secret path in your callback URL.