curl --request POST \
--url https://api.citadel.example/api/v1/events/{name} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"network": "mainnet",
"inputs": {
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF",
"amount": "50000000",
"asset": "USDT",
"user": "user-4211"
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
network: 'mainnet',
inputs: {
to: 'TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF',
amount: '50000000',
asset: 'USDT',
user: 'user-4211'
}
})
};
fetch('https://api.citadel.example/api/v1/events/{name}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.citadel.example/api/v1/events/{name}"
payload = {
"network": "mainnet",
"inputs": {
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF",
"amount": "50000000",
"asset": "USDT",
"user": "user-4211"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.citadel.example/api/v1/events/{name}"
payload := strings.NewReader("{\n \"network\": \"mainnet\",\n \"inputs\": {\n \"to\": \"TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF\",\n \"amount\": \"50000000\",\n \"asset\": \"USDT\",\n \"user\": \"user-4211\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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))
}{
"event": "<string>",
"network": "mainnet",
"runs": [
{
"run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow": "<string>",
"status": "running"
}
]
}Start workflows by event
Sends your own named event (payout, refund, …) on one network with the inputs your
workflow declared. Every active workflow of that network listening on the name starts a
run; a workflow on another network never hears it. The platform does the rest —
screening, choosing a wallet, moving funds — the way the workflow is drawn.
network is required: there is no default network. Inputs are type-checked at the
door on that network: a wallet must be yours there, an asset supported there.
Idempotent per (event, idempotency key, workflow): a retry with the same inputs returns
the runs it started and starts nothing twice. The key reused with other inputs, or on
another network, is refused with 409 idempotency_conflict, and nothing starts.
Needs the events.write scope. A key limited to vaults is refused with
403 vault_limited: workflows choose their own wallets.
curl --request POST \
--url https://api.citadel.example/api/v1/events/{name} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"network": "mainnet",
"inputs": {
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF",
"amount": "50000000",
"asset": "USDT",
"user": "user-4211"
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
network: 'mainnet',
inputs: {
to: 'TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF',
amount: '50000000',
asset: 'USDT',
user: 'user-4211'
}
})
};
fetch('https://api.citadel.example/api/v1/events/{name}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.citadel.example/api/v1/events/{name}"
payload = {
"network": "mainnet",
"inputs": {
"to": "TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF",
"amount": "50000000",
"asset": "USDT",
"user": "user-4211"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.citadel.example/api/v1/events/{name}"
payload := strings.NewReader("{\n \"network\": \"mainnet\",\n \"inputs\": {\n \"to\": \"TC6A9sQD2tCSaR1wcBXZtrvGkFyoLgRHHF\",\n \"amount\": \"50000000\",\n \"asset\": \"USDT\",\n \"user\": \"user-4211\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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))
}{
"event": "<string>",
"network": "mainnet",
"runs": [
{
"run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"workflow": "<string>",
"status": "running"
}
]
}Authorizations
An API key minted in the console (ctd_…). Authenticates; never authorizes funds. A key
carries scopes (read, wallets.write, transactions.write, events.write,
webhooks.write, policy.write) and may be limited to vaults, to IP addresses, and in
lifetime — see Authentication.
Headers
Makes a retry safe. The same key with the same body returns the first result; with a
different body (on /events/{name}: other inputs or another network),
409 idempotency_conflict. Also accepted as idempotency_key in the body. Without one,
POST /transactions answers with an idempotency_key of its own, intent:<uuid>.
255Path Parameters
^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$Body
Response
Runs started.