Starship Rewards API

Get Payout API

Retrieve detailed information about a specific payout including status and beneficiary details

Get Payout API

Retrieve detailed information about a specific payout, including its current status and beneficiary details.

Endpoint

GET /api/v1/payouts/:id

Authentication: Bearer token required

Request Headers

Authorization: Bearer <access_token>

Path Parameters

ParameterTypeDescription
idstringPayout ID (e.g., pyt_xyz789abc)

Response

Success Response

Status Code: 200 OK

{
  "id": "pyt_xyz789abc",
  "reference_id": "PAY_2024_001",
  "status": "completed",
  "amount": 100.00,
  "currency": "USD",
  "fees": 1.50,
  "total_amount": 101.50,
  "beneficiary": {
    "email": "john.doe@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "country": "US",
    "phone": "+1234567890"
  },
  "description": "Q1 2024 Bonus Payment",
  "created_at": "2024-01-15T10:30:00Z",
  "queued_at": "2024-01-15T10:30:01Z",
  "submitted_at": "2024-01-15T10:31:00Z",
  "completed_at": "2024-01-15T10:35:00Z",
  "failed_at": null,
  "cancelled_at": null
}

Response Fields

FieldTypeDescription
idstringUnique payout identifier
reference_idstringClient reference
statusstringCurrent payout status
amountnumberPayout amount to beneficiary
currencystringCurrency code
feesnumberFees charged
total_amountnumberTotal deducted from wallet
beneficiaryobjectBeneficiary information
failure_codestringError code if failed (nullable)
failure_reasonstringError description if failed (nullable)
descriptionstringPayout description (nullable)
created_atstringCreation timestamp
queued_atstringWhen queued (nullable)
submitted_atstringWhen submitted to provider (nullable)
completed_atstringWhen completed (nullable)
failed_atstringWhen failed (nullable)
cancelled_atstringWhen cancelled (nullable)

Failed Payout Response

When a payout has failed, additional failure information is included:

{
  "id": "pyt_failed123",
  "reference_id": "PAY_2024_FAIL",
  "status": "failed",
  "amount": 100.00,
  "currency": "USD",
  "fees": 1.50,
  "total_amount": 101.50,
  "failure_code": "INVALID_ACCOUNT",
  "failure_reason": "The beneficiary account number is invalid or closed",
  "beneficiary": {
    "email": "john.doe@example.com",
    "first_name": "John",
    "last_name": "Doe"
  },
  "created_at": "2024-01-15T10:30:00Z",
  "failed_at": "2024-01-15T10:32:00Z"
}

Common Failure Codes

CodeDescription
INVALID_ACCOUNTBeneficiary account is invalid or closed
INSUFFICIENT_FUNDSProvider or wallet insufficient funds
COMPLIANCE_HOLDTransaction held for compliance review
BENEFICIARY_REJECTEDBeneficiary rejected the payment
PROVIDER_ERRORPayment provider system error
EXPIREDPayout expired before completion
LIMIT_EXCEEDEDTransaction limit exceeded

Error Responses

400 Bad Request - Missing ID

{
  "error": "BadRequest",
  "message": "Payout ID is required"
}

404 Not Found

{
  "error": "NotFound",
  "message": "Payout not found"
}

401 Unauthorized

{
  "error": "UnauthorizedAccess",
  "message": "Authentication required"
}

Examples

Basic Request

curl -X GET "{{host}}/api/v1/payouts/pyt_xyz789abc" \
  -H "Authorization: Bearer your_access_token"
<?php
function getPayout($accessToken, $payoutId) {
    $url = "{{host}}/api/v1/payouts/$payoutId";

    $options = [
        'http' => [
            'header' => "Authorization: Bearer $accessToken",
            'method' => 'GET'
        ]
    ];

    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);

    if ($result === false) {
        throw new Exception('Failed to get payout');
    }

    return json_decode($result, true);
}

// Usage
$payout = getPayout('your_access_token', 'pyt_xyz789abc');

echo "Payout ID: " . $payout['id'] . "\n";
echo "Status: " . $payout['status'] . "\n";
echo "Amount: " . $payout['amount'] . " " . $payout['currency'] . "\n";

if ($payout['status'] === 'failed') {
    echo "Failure: " . $payout['failure_reason'] . "\n";
}
?>

Poll for Status Updates

async function waitForPayoutCompletion(payoutId, maxWaitMs = 300000) {
    const startTime = Date.now();
    const pollInterval = 5000; // 5 seconds

    while (Date.now() - startTime < maxWaitMs) {
        const response = await fetch(`/api/v1/payouts/${payoutId}`, {
            headers: {
                'Authorization': `Bearer ${getAccessToken()}`
            }
        });

        const payout = await response.json();

        // Check for terminal states
        if (['completed', 'failed', 'cancelled', 'expired'].includes(payout.status)) {
            return payout;
        }

        // Log current status
        console.log(`Payout ${payoutId} status: ${payout.status}`);

        // Wait before next poll
        await new Promise(resolve => setTimeout(resolve, pollInterval));
    }

    throw new Error(`Timeout waiting for payout ${payoutId}`);
}

// Usage
try {
    const payout = await waitForPayoutCompletion('pyt_xyz789abc');

    if (payout.status === 'completed') {
        console.log('Payout completed successfully!');
    } else if (payout.status === 'failed') {
        console.log(`Payout failed: ${payout.failure_reason}`);
    }
} catch (error) {
    console.error('Error:', error.message);
}

Track Payout Timeline

function displayPayoutTimeline(payout) {
    console.log(`Payout ${payout.id} Timeline:`);
    console.log('─'.repeat(50));

    const milestones = [
        { label: 'Created', time: payout.created_at },
        { label: 'Queued', time: payout.queued_at },
        { label: 'Submitted', time: payout.submitted_at },
        { label: 'Completed', time: payout.completed_at },
        { label: 'Failed', time: payout.failed_at },
        { label: 'Cancelled', time: payout.cancelled_at }
    ];

    milestones.forEach(({ label, time }) => {
        if (time) {
            const date = new Date(time);
            console.log(`  ${label}: ${date.toLocaleString()}`);
        }
    });

    console.log('─'.repeat(50));
    console.log(`Current Status: ${payout.status}`);
}

// Usage
const payout = await getPayout('pyt_xyz789abc');
displayPayoutTimeline(payout);

Handle Different Statuses

<?php
function handlePayoutStatus($payout) {
    switch ($payout['status']) {
        case 'created':
        case 'queued':
            return [
                'action' => 'wait',
                'message' => 'Payout is being processed'
            ];

        case 'processing':
            return [
                'action' => 'wait',
                'message' => 'Payout submitted to payment provider'
            ];

        case 'settling':
            return [
                'action' => 'wait',
                'message' => 'Funds are being settled to beneficiary'
            ];

        case 'action_required':
            return [
                'action' => 'review',
                'message' => 'Additional action required - check event details'
            ];

        case 'completed':
            return [
                'action' => 'done',
                'message' => 'Payout delivered successfully',
                'completed_at' => $payout['completed_at']
            ];

        case 'failed':
            return [
                'action' => 'retry_or_refund',
                'message' => $payout['failure_reason'],
                'code' => $payout['failure_code']
            ];

        case 'cancelled':
            return [
                'action' => 'none',
                'message' => 'Payout was cancelled',
                'cancelled_at' => $payout['cancelled_at']
            ];

        case 'expired':
            return [
                'action' => 'recreate',
                'message' => 'Payout expired - create a new one'
            ];

        default:
            return [
                'action' => 'unknown',
                'message' => 'Unknown status: ' . $payout['status']
            ];
    }
}
?>

Use Cases

Display Payout Status to End User

function getStatusDisplay(payout) {
    const statusConfig = {
        created: { icon: '⏳', text: 'Processing', color: 'blue' },
        queued: { icon: '⏳', text: 'Processing', color: 'blue' },
        processing: { icon: '🔄', text: 'In Progress', color: 'blue' },
        settling: { icon: '🔄', text: 'Settling', color: 'blue' },
        action_required: { icon: '⚠️', text: 'Action Required', color: 'yellow' },
        completed: { icon: '✅', text: 'Completed', color: 'green' },
        failed: { icon: '❌', text: 'Failed', color: 'red' },
        cancelled: { icon: '🚫', text: 'Cancelled', color: 'gray' },
        expired: { icon: '⏰', text: 'Expired', color: 'gray' }
    };

    return statusConfig[payout.status] || { icon: '❓', text: 'Unknown', color: 'gray' };
}

Audit Trail for Compliance

function generateAuditReport(payout) {
    return {
        payout_id: payout.id,
        reference_id: payout.reference_id,
        amount: `${payout.amount} ${payout.currency}`,
        fees: payout.fees,
        total_deducted: payout.total_amount,
        beneficiary: {
            name: `${payout.beneficiary.first_name} ${payout.beneficiary.last_name}`,
            email: payout.beneficiary.email,
            country: payout.beneficiary.country
        },
        timestamps: {
            created: payout.created_at,
            queued: payout.queued_at,
            submitted: payout.submitted_at,
            completed: payout.completed_at,
            failed: payout.failed_at,
            cancelled: payout.cancelled_at
        },
        final_status: payout.status,
        failure_info: payout.failure_code ? {
            code: payout.failure_code,
            reason: payout.failure_reason
        } : null,
        total_processing_time: calculateProcessingTime(payout)
    };
}

function calculateProcessingTime(payout) {
    const start = new Date(payout.created_at);
    const end = new Date(
        payout.completed_at ||
        payout.failed_at ||
        payout.cancelled_at ||
        new Date()
    );
    return `${Math.round((end - start) / 1000)} seconds`;
}

Best Practices

  1. Store payout IDs - Always save the payout ID returned from creation for later retrieval
  2. Poll responsibly - Use reasonable intervals (5-10 seconds) when polling for status
  3. Handle all statuses - Implement handling for every possible status
  4. Log timestamps - Store timestamp history for audit and debugging purposes
  5. Parse failure codes - Use failure codes for automated retry decisions