TriportRPC

POST /v1/admin/referrals/payouts/{id}/failed — Mark payout as failed

POSThttps://api.triport.io/v1/admin/referrals/payouts/4f2c9b1e-7a3d-4c0b-9e21-3f8a6d5c1b22/failed

Operator action that transitions a referral payout into the terminal `failed` state, optionally recording a reason.

— (operator/admin token)

This is an operator-only endpoint for the referral payout lifecycle. A payout moves through requestedprocessingsent (or failed / cancelled). When an out-of-band transfer cannot be completed, an operator calls this endpoint to mark the payout as failed so the user's balance and reporting reflect the real state.

The transition is only valid from an actionable state. If the payout has already reached a terminal status (e.g. it was previously marked sent), the request is rejected with 409 payout_not_actionable rather than silently overwriting it.

An optional free-text reason may be supplied to annotate why the payout failed. On success the endpoint returns { "ok": true }.

This endpoint requires the X-Admin-Token header. It is not part of the session-cookie–authenticated user referral surface — it sits under /v1/admin/referrals/* alongside the other operator controls.

Parameters

Path parameters

idUUIDrequired
The payout ID to mark as failed. Must be a valid UUID, otherwise 400 invalid_payout_id.
Request bodyobject
reasonstringoptional
Optional free-text note describing why the payout failed. Omit or send {} if not needed. Body is capped at 4 KiB.

Response

Response fields

FieldTypeDescription
okbooleanAlways true when the payout was transitioned to failed.

Errors

All errors use the shared envelope { "error": "<tag>" }. See errors.md for the full envelope.

CodeTagWhen it happens
400invalid_payout_idThe {id} path segment is not a valid UUID.
400invalid_jsonThe request body could not be decoded (malformed JSON or larger than 4 KiB).
401admin_token_unsetThe operator token is not configured on the server.
401admin_token_invalidThe X-Admin-Token header is missing or does not match.
404payout_not_foundNo payout exists with the given ID.
404not_foundThe path is missing the action segment (e.g. /payouts/{id} with no /failed).
405method_not_allowedA method other than POST was used.
409payout_not_actionableThe payout is in a terminal/non-actionable state and cannot be marked failed.
500internalUnexpected server-side error.

Examples

JavaScript (fetch)

const res = await fetch(
  `https://api.triport.io/v1/admin/referrals/payouts/${payoutId}/failed`,
  {
    method: "POST",
    headers: {
      "X-Admin-Token": process.env.TRIPORT_ADMIN_TOKEN,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ reason: "destination wallet rejected the transfer" }),
  }
);


if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`mark-failed failed: ${error}`);
}
const { ok } = await res.json(); // ok === true

TypeScript SDK (@triport/sdk)

import { TriportAdmin } from "@triport/sdk";


const admin = new TriportAdmin({ adminToken: process.env.TRIPORT_ADMIN_TOKEN! });


await admin.referrals.payouts.markFailed(payoutId, {
  reason: "destination wallet rejected the transfer",
});

Python (triport-sdk)

import os
from triport import TriportAdmin


admin = TriportAdmin(admin_token=os.environ["TRIPORT_ADMIN_TOKEN"])


admin.referrals.payouts.mark_failed(
    payout_id,
    reason="destination wallet rejected the transfer",
)

Notes

  • Idempotency: the transition is guarded — a payout that has already been resolved (for example marked sent) returns 409 payout_not_actionable, so repeated calls will not flip a settled payout.
  • Related endpoints:
  • The reason is stored as an annotation only; it does not affect the resulting status, which is always failed on success.