Skip to content

feat: Add RefundByEntitlementIds endpoint (POST /game/refund/v1)#435

Open
Copilot wants to merge 3 commits intodevfrom
copilot/add-refund-endpoint
Open

feat: Add RefundByEntitlementIds endpoint (POST /game/refund/v1)#435
Copilot wants to merge 3 commits intodevfrom
copilot/add-refund-endpoint

Conversation

Copy link
Contributor

Copilot AI commented Mar 6, 2026

  • Add LootLockerRefundInventoryEventAction enum (removed, skipped) for LootLockerRefundPlayerInventoryEvent.action
  • Add LootLockerRefundNonReversibleRewardKind enum (progression_points, progression_reset) for LootLockerRefundNonReversibleReward.kind
  • Add LootLockerRefundWarningType enum (non_reversible_rewards, insufficient_funds, already_refunded, refund_failed) for LootLockerRefundWarningDetail.type
  • Change action, kind, and type properties from string to their respective enum types
  • Update XML doc comments to match new enum-typed properties
Original prompt

Summary

Implement the refund endpoint for the Unity SDK as described in lootlocker/index#1395.

The tracking issue is https://github.com/lootlocker/index/issues/1395. Per the lifecycle instructions: as soon as the PR is opened, post a comment on the tracking issue with the PR link, and update the tracking issue's project status to In Review.

API Specification

Endpoint: POST /game/refund/v1

Request body:

{
  "entitlement_ids": ["<ULID>", ...]
}

Response (200):

{
  "player_inventory_events": [
    {
      "asset_id": 123,
      "name": "Item Name",
      "action": "removed" | "skipped"
    }
  ],
  "currency_refunded": [
    {
      "currency_id": "<ULID>",
      "currency_code": "gold",
      "amount": "500"
    }
  ],
  "currency_clawback": [
    {
      "currency_id": "<ULID>",
      "currency_code": "gold",
      "amount": "500"
    }
  ],
  "warnings": [
    {
      "entitlement_id": "<ULID>",
      "details": [
        {
          "type": "non_reversible_rewards" | "insufficient_funds" | "already_refunded" | "refund_failed",
          "message": "Human-readable explanation",
          "rewards": [
            {
              "kind": "progression_points" | "progression_reset",
              "id": "<ULID>",
              "name": "Progression name",
              "amount": "100"
            }
          ]
        }
      ]
    }
  ]
}

What needs to be implemented

1. Runtime/Client/LootLockerEndPoints.cs

Add a new endpoint under the // Purchase section (after the existing purchase endpoints):

public static EndPointClass refundByEntitlementIds = new EndPointClass("refund/v1", LootLockerHTTPMethod.POST);

2. Runtime/Game/Requests/PurchaseRequest.cs

Following the existing patterns in this file:

In namespace LootLocker.Requests, add:

// --- Request DTO ---
/// <summary>
/// Request to refund one or more entitlements by their IDs.
/// </summary>
public class LootLockerRefundByEntitlementIdsRequest
{
    /// <summary>
    /// The IDs of the entitlements to refund
    /// </summary>
    public string[] entitlement_ids { get; set; }
}

// --- Response DTOs ---
/// <summary>
/// Represents the action taken on a player inventory item during a refund.
/// </summary>
public class LootLockerRefundPlayerInventoryEvent
{
    /// <summary>
    /// The legacy numeric asset ID
    /// </summary>
    public ulong asset_id { get; set; }
    /// <summary>
    /// Display name of the asset
    /// </summary>
    public string name { get; set; }
    /// <summary>
    /// "removed" if taken back from inventory, "skipped" if it could not be removed (e.g. already consumed)
    /// </summary>
    public string action { get; set; }
}

/// <summary>
/// Represents a currency entry (amount credited or debited) as part of a refund
/// </summary>
public class LootLockerRefundCurrencyEntry
{
    /// <summary>
    /// The ULID of the currency
    /// </summary>
    public string currency_id { get; set; }
    /// <summary>
    /// Short code identifying the currency (e.g. "gold", "gems")
    /// </summary>
    public string currency_code { get; set; }
    /// <summary>
    /// The amount credited or debited, as a string to support arbitrary precision
    /// </summary>
    public string amount { get; set; }
}

/// <summary>
/// Represents a non-reversible reward that was granted alongside an entitlement and could not be clawed back
/// </summary>
public class LootLockerRefundNonReversibleReward
{
    /// <summary>
    /// "progression_points": points were added to a progression. "progression_reset": a progression was reset to its initial state.
    /// </summary>
    public string kind { get; set; }
    /// <summary>
    /// The ULID of the progression that was affected
    /// </summary>
    public string id { get; set; }
    /// <summary>
    /// Display name of the progression
    /// </summary>
    public string name { get; set; }
    /// <summary>
    /// The number of points that were granted and cannot be reversed. Only present for kind "progression_points".
    /// </summary>
    public string amount { get; set; }
}

/// <summary>
/// Represents a single warning detail for a refund
/// </summary>
public class LootLockerRefundWarningDetail
{
    /// <summary>
    /// The warning category:
    /// "non_reversible_rewards": rewards granted that cannot be automatically clawed back.
    /// "insufficient_funds": the player does not have enough currency balance to cover the clawback.
    /// "already_refunded": the entitlement was already refunded before this request.
    /// "refund_failed": the entitlement could not be refunded due to an unexpected error.
    /// </summary>
    public string type { get; set; }
    /// <summary>
    /// Human-readable explanation of the warning
    /// </summary>
    public string message { get; set; }
    /// <summary>
    /// The specific rewards ...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. [Learn more about Advanced Security.](https://gh.io/cca-advanced-security)

Co-authored-by: kirre-bylund <4068377+kirre-bylund@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement refund endpoint for Unity SDK feat: Add RefundByEntitlementIds endpoint Mar 6, 2026
Copilot AI changed the title feat: Add RefundByEntitlementIds endpoint feat: Add RefundByEntitlementIds endpoint (POST /game/refund/v1) Mar 6, 2026
Copy link
Contributor

@kirre-bylund kirre-bylund left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot review complete, please adress.

Co-authored-by: kirre-bylund <4068377+kirre-bylund@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 6, 2026

@copilot review complete, please adress.

All three string fields converted to enums in commit 4318242:

  • actionLootLockerRefundInventoryEventAction (removed, skipped)
  • kindLootLockerRefundNonReversibleRewardKind (progression_points, progression_reset)
  • typeLootLockerRefundWarningType (non_reversible_rewards, insufficient_funds, already_refunded, refund_failed)

@kirre-bylund kirre-bylund marked this pull request as ready for review March 6, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants