Skip to content

Handle refusals

When Sotirea refuses a request, it says exactly why: code is the kind of refusal, fields.rule names what refused it, and message explains it in words you can show a person. Your code should decide on the rule, never on the words, which can change.

  • rate_limited (429), unavailable (503) and internal (500) are about the moment, not the request. Send the same request again after a short wait, with the same Idempotency-Key for a payment.
  • Everything else needs something to change first: the request, the key, an approval, or your organisation’s rules. Sending it again unchanged is refused again.
  • No answer at all, from a timeout or a dropped connection, is not a refusal. For a payment, send it again with the same Idempotency-Key: if it was made, you get it back.

The payout example retries the first kind and returns the rest.

// explain turns a refusal into what your team should do about it.
func explain(err error) string {
var refusal *sotirea.Error
if !errors.As(err, &refusal) {
return "no answer from Sotirea: send it again with the same payout id"
}
switch refusal.Rule() {
case "new_destination", "allowlist":
return "approve this address in the console before paying it"
case "destination_waiting":
return "this address was just approved: " + refusal.Message
case "insufficient_balance":
return "the vault cannot cover it: " + refusal.Message
case "insufficient_gas":
return "top up the network fees for Base, then pay with a new payout id"
case "sanctioned_address", "blocked_destination":
return "never pay this address"
case "idempotency_key":
return "this payout id was already used for a different payment"
}
// Any other refusal: its message is written to be shown to a person.
return fmt.Sprintf("%s (request %s)", refusal.Message, refusal.RequestID)
}

Every rule the API can answer with is on errors and refusals, with what it means and what to do. A rule you do not handle still has a message written for a person: show it, and log the request_id, which Sotirea can trace if you ask about it.