This is what the platform stores after a user links their stablecoin app. It is an opaque reference that Swype resolves internally during payout execution.
{
"destination_id": "dst_9f3a21",
"status": "linked",
"created_at": "2026-01-06T15:12:03Z"
}destination_id does not contain chain, asset, or address details.
The platform stores destination_id and maps it to its own platform_user_id.
This is the instruction the platform sends to initiate a payout: pay this linked destination this amount in USD.
{
"destination_id": "dst_9f3a21",
"amount": {
"value": 1250.00,
"currency": "USD"
},
"reference": "creator_payout_2026_01_06"
}This is intentionally high-level: no chains, tokens, gas, or addresses.
Use an Idempotency-Key header to prevent duplicate payouts on retries.
This is the payout object returned by Swype after creation and updated over time as execution progresses.
{
"payout_id": "po_83k2l1",
"destination_id": "dst_9f3a21",
"amount": {
"value": 1250.00,
"currency": "USD"
},
"status": "submitted",
"created_at": "2026-01-06T15:14:22Z"
}Optional fields Swype may include as execution progresses:
{
"provider": {
"name": "bridge",
"provider_payout_id": "prov_72a9d2"
},
"tx_hash": "0xabc123..."
}
The regulated execution partner is the sender of record.
tx_hash is included when available, and serves as verifiable proof of execution.
Webhooks notify the platform when a payout moves through its lifecycle. Platforms should verify signatures before trusting events.
{
"id": "evt_1a2b3c",
"type": "payout.processing",
"created_at": "2026-01-06T15:15:10Z",
"data": {
"payout_id": "po_83k2l1",
"destination_id": "dst_9f3a21",
"status": "processing"
}
}
After a user completes the hosted linking flow, the platform exchanges the completed link session for a single opaque destination_id.
This identifier represents the user’s linked payout destination and is what the platform stores and uses for all future payouts. The platform never receives addresses, chains, or asset details.
import fetch from "node-fetch";
async function exchangeLinkSession(linkSessionId) {
const response = await fetch(
`https://api.swype.com/v1/link_sessions/${linkSessionId}/exchange`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SWYPE_API_KEY}`,
"Content-Type": "application/json"
}
}
);
const result = await response.json();
return {
destination_id: result.destination_id,
status: result.status
};
}platform_user_id → destination_id
Then, to initiate a payout, the platform submits a platform-level instruction such as: pay this destination this amount in USD.
import fetch from "node-fetch";
import { v4 as uuidv4 } from "uuid";
async function createPayout(destinationId, amountUsd) {
const idempotencyKey = uuidv4();
const response = await fetch("https://api.swype.com/v1/payouts", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SWYPE_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey
},
body: JSON.stringify({
destination_id: destinationId,
amount: {
value: amountUsd,
currency: "USD"
},
reference: "creator_payout_2026_01_06"
})
});
return response.json();
}Swype resolves destination + chooses route (asset/network/partner)
Execution partner executes transfer (sender of record)
Swype tracks state + emits lifecycle webhooks
Swype sends webhooks to notify the platform of payout status changes
(e.g. payout.processing, payout.completed, payout.failed). The platform verifies the webhook signature before trusting the event.
function verifySignature(payload, signature, secret) {
if (!signature) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
if (signature.length !== expected.length) return false;
return crypto.timingSafeEqual(
Buffer.from(signature, "utf8"),
Buffer.from(expected, "utf8")
);
}
app.post("/webhooks/swype", (req, res) => {
const signatureHeader = req.headers["swype-signature"];
const signature = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;
const payload = req.body;
if (!verifySignature(payload, signature, process.env.SWYPE_WEBHOOK_SECRET)) {
return res.status(400).send("Invalid signature");
}
const event = JSON.parse(payload.toString("utf8"));
switch (event.type) {
case "payout.processing":
break;
case "payout.completed":
break;
case "payout.failed":
break;
}
res.status(200).send("OK");
});