Cancel FRB

Cancel FRB

This endpoint allows Groove to cancel an active free round bonus assignment for a player on your platform.

Request Details (From Groove to Your Platform)

  • Method: DELETE
  • Endpoint: https://{your_domain}/frb/{version}/bonus?operator_id={operator_id}&template_id={template_id}&player_id={player_id}
  • Direction: Groove → Your Platform

Request Parameters (What You’ll Receive from Groove)

Parameter Type Mandatory Description
version String Yes The API version. Currently supports 1.0
Example: 1.0
operator_id Integer Yes Groove operator ID
Example: 11
template_id String Yes The unique assignment ID (the one your platform generated during /assign)
Example: assign_456xyz
player_id String Yes The player ID
Example: 12345678

Request Example

DELETE /frb/1.0/bonus?operator_id=11&template_id=assign_456xyz&player_id=12345678

Response Parameters (What You Must Return)

The response structure is identical to the Get FRB Status endpoint, but should reflect the actual status of the bonus.

**Critical**: Always return the ACTUAL status of the bonus, not necessarily "canceled": - If the bonus was already `completed`, return status: `"completed"` - If the bonus was already `expired`, return status: `"expired"` - If the bonus was already `canceled`, return status: `"canceled"` - Only return status: `"canceled"` if the cancellation was actually performed

Parameter Type Mandatory Description
player_id String Yes The player ID from the request
player_currency String Yes Player’s currency in ISO3 format
operator_id Integer Yes The operator ID from the request
provider_id Integer Yes Your provider ID
status String Yes The ACTUAL status of the bonus (see Available Statuses below)
template_id String Yes The assignment ID from the request
left_rounds Integer Yes Number of rounds remaining (0 if completed)
total_rounds Integer Yes Total number of rounds originally granted
expiration_date String Yes Original expiration date in ISO 8601 format
games Array No Empty array for non-active statuses
error_message String No Error description (empty string if successful)

Available Statuses

All FRB endpoints must use these exact status values:

Status Value Description
"active" The FRB is active and can be used by the player
"canceled" The FRB has been canceled by the operator
"expired" The FRB has passed its expiration date
"completed" The player has used all available rounds

Response Examples

Success Response - Bonus Canceled

{
    "player_id": "12345678",
    "player_currency": "EUR",
    "operator_id": 11,
    "provider_id": 123,
    "status": "canceled",
    "template_id": "assign_456xyz",
    "left_rounds": 10,
    "total_rounds": 50,
    "expiration_date": "2025-02-11T12:00:00Z",
    "games": [],
    "error_message": ""
}

Error Response - Bonus Not Found

{
    "player_id": "12345678",
    "player_currency": "EUR",
    "operator_id": 11,
    "provider_id": 123,
    "template_id": "assign_456xyz",
    "expiration_date": "",
    "error_message": "Bonus not found"
}

Response - Already Completed (Cannot Cancel)

{
    "player_id": "12345678",
    "player_currency": "EUR",
    "operator_id": 11,
    "provider_id": 123,
    "status": "completed",
    "template_id": "assign_456xyz",
    "left_rounds": 0,
    "total_rounds": 50,
    "expiration_date": "2025-02-11T12:00:00Z",
    "games": [],
    "error_message": ""
}
Info

**Note**: When a cancellation is requested for an already completed bonus, return HTTP 200 with status: `"completed"` to indicate the actual state. The error_message can be empty or contain an informational message.

HTTP Response Codes

Code Status Description
200 Success FRB canceled successfully
400 Bad Request Invalid parameters or bonus cannot be canceled
403 Forbidden Access denied
404 Not Found Bonus assignment not found
500 Internal Server Error Server error occurred

Implementation Example

app.delete('/frb/:version/bonus', (req, res) => {
    const { operator_id, template_id, player_id } = req.query;
    const { version } = req.params;
    
    // Validate parameters
    if (!operator_id || !template_id || !player_id) {
        return res.status(400).json({
            player_id: player_id || "",
            player_currency: "",
            operator_id: parseInt(operator_id) || 0,
            provider_id: 123,
            template_id: template_id || "",
            expiration_date: "",
            error_message: "Missing required parameters"
        });
    }
    
    // Look up the bonus assignment
    const assignment = getAssignment(template_id, player_id);
    
    if (!assignment) {
        return res.status(404).json({
            player_id: player_id,
            player_currency: "EUR",
            operator_id: parseInt(operator_id),
            provider_id: 123,
            template_id: template_id,
            expiration_date: "",
            error_message: "Bonus not found"
        });
    }
    
    // Check current status and respond accordingly
    if (assignment.status === 'completed') {
        // Return the actual status (completed) - cannot cancel
        return res.json({
            player_id: player_id,
            player_currency: assignment.player_currency,
            operator_id: parseInt(operator_id),
            provider_id: 123,
            status: "completed",  // Return ACTUAL status
            template_id: template_id,
            left_rounds: 0,
            total_rounds: assignment.total_rounds,
            expiration_date: assignment.expiration_date,
            games: [],
            error_message: ""
        });
    }
    
    if (assignment.status === 'expired') {
        // Return the actual status (expired) - can still mark as canceled for records
        return res.json({
            player_id: player_id,
            player_currency: assignment.player_currency,
            operator_id: parseInt(operator_id),
            provider_id: 123,
            status: "expired",  // Return ACTUAL status
            template_id: template_id,
            left_rounds: assignment.left_rounds,
            total_rounds: assignment.total_rounds,
            expiration_date: assignment.expiration_date,
            games: [],
            error_message: ""
        });
    }
    
    if (assignment.status === 'canceled') {
        // Already canceled - return current status
        return res.json({
            player_id: player_id,
            player_currency: assignment.player_currency,
            operator_id: parseInt(operator_id),
            provider_id: 123,
            status: "canceled",  // Already canceled
            template_id: template_id,
            left_rounds: assignment.left_rounds,
            total_rounds: assignment.total_rounds,
            expiration_date: assignment.expiration_date,
            games: [],
            error_message: ""
        });
    }
    
    // Cancel the bonus
    cancelAssignment(template_id, player_id);
    
    // Return success response
    res.json({
        player_id: player_id,
        player_currency: assignment.player_currency,
        operator_id: parseInt(operator_id),
        provider_id: 123,
        status: "canceled",
        template_id: template_id,
        left_rounds: assignment.left_rounds,
        total_rounds: assignment.total_rounds,
        expiration_date: assignment.expiration_date,
        games: [],
        error_message: ""
    });
});

Important Notes

  1. Template ID: The template_id in the request is the unique assignment ID your platform generated during the /assign request
  2. Status Response Rules:
    • ALWAYS return the ACTUAL status of the bonus, not the requested action
    • If bonus is completed, return status: "completed" (not "canceled")
    • If bonus is expired, return status: "expired" (not "canceled")
    • If bonus is already canceled, return status: "canceled"
    • Only return "canceled" if you actually performed the cancellation
  3. HTTP Response Codes:
    • Return HTTP 200 even when returning completed or expired status
    • Use HTTP 404 only when the bonus doesn’t exist
  4. Player Protection: Ensure no active game rounds are using the bonus before cancellation
  5. Audit Trail: Keep records of cancellation attempts, even unsuccessful ones
  6. Immediate Effect: Successful cancellations should take effect immediately

Business Rules

  1. Active Games: If a player is currently in a game round using this bonus, handle appropriately:

    • Option 1: Prevent cancellation until round completes
    • Option 2: Allow cancellation but let current round complete
    • Document your approach for Groove
  2. Refunds: Cancellation does not imply refund - it only stops future usage

  3. Notification: Consider notifying the player that their bonus has been canceled

Best Practices

  1. Transaction Safety: Use database transactions to ensure atomic updates
  2. Concurrent Access: Handle race conditions if player is actively using the bonus
  3. Audit Logging: Log all cancellation requests with timestamp and reason
  4. Status Consistency: Ensure status is consistently updated across all systems
  5. Error Messages: Provide clear error messages for different failure scenarios