> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Updating title-managed Achievements

> Example XSAPI code showing how to unlock a title-managed XBOX services achievement or report completion progress with XblAchievementsUpdateAchievementAsync.

This topic covers the following:

* [Before you begin](#before-you-begin)
* [Unlocking an achievement](#unlocking-an-achievement)
* [Updating completion progress for an achievement](#updating-an-achievement)
* [Troubleshooting](#troubleshooting)

## Before you begin

* Your product uses the full XBOX services feature set. New products start with limited XBOX services, and achievements and gamerscore aren't available until your product is onboarded. For more information, see [Request product onboarding to enable full XBOX services](https://docs.xbox.com/home/onboarding.md#request-product-onboarding-to-enable-full-xbox-services).
* You configured the achievement in Partner Center and published the XBOX services configuration to your development sandbox. For more information, see [Configuring title-managed Achievements in Partner Center](https://docs.xbox.com/services/xbox-services/player-data/achievements/title-managed/config/live-achievements-tm-config.md).
* Your dev kit or Windows PC uses the same development sandbox, and you sign in with a test account that has access to that sandbox. For more information, see [XBOX services sandboxes overview](https://docs.xbox.com/services/xbox-services/fundamentals/sandboxes/live-setup-sandbox.md).
* Your game initialized the Gaming Runtime and then called [XblInitialize](https://docs.xbox.com/reference/live/xsapi-c/xbox_live_global_c/functions/xblinitialize.md) with an [XblInitArgs](https://docs.xbox.com/reference/live/xsapi-c/xbox_live_global_c/structs/xblinitargs.md) structure whose `scid` member contains your Service Configuration ID (SCID). The SCID is case-sensitive. For more information, see [How to use XBOX services APIs](https://docs.xbox.com/services/xbox-services/fundamentals/xbox-services-api/live-gs-xbl-apis.md).
* You signed in a user and created an `XblContextHandle` for that user by calling [XblContextCreateHandle](https://docs.xbox.com/reference/live/xsapi-c/xbox_live_context_c/functions/xblcontextcreatehandle.md).

To reset achievements for a test account between test runs, use the [Player Data Reset tool (XblPlayerDataReset.exe)](https://docs.xbox.com/tools/tools-services/live-player-data-reset.md). To reset a player by XUID, the developer account that you sign in with by using XblDevAccount.exe needs the product-level Tools Access permission.

## Unlocking an achievement

After your achievements are configured via Partner Center and published to your development sandbox, your title can unlock them by calling the [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md) API.
For more information, see the example code in the next section.

To unlock an achievement, set `percentComplete` to 100.
If the user is online, the request is immediately sent to the XBOX services Achievements service and triggers the following user experiences.

* The user receives an Achievement Unlocked notification.
* The specified achievement appears as unlocked in the user's achievement list for the title.
* The unlocked achievement is added to the user's activity feed.

> [!NOTE]
>
> The user experience is visually the same for achievements that use either event-based Achievements or title-managed Achievements.

If the user is offline, the unlock request is queued locally on the user's device.
When it has reestablished network connectivity, the request is automatically sent to the Achievements service (no action is required from the game to trigger this), and the previous user experiences occur as described.

## Updating completion progress for an achievement

To update a user's progress toward unlocking an achievement, call [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md). Set the `percentComplete` argument to a whole number between 1-100.
For more information, see the following example code.

An achievement's progress can only increase.
If `percentComplete` is set to a number less than the achievement's last `percentComplete` value, the update is ignored.
For example, if the achievement's `percentComplete` had previously been set to 75, sending an update with a value of 25 is ignored. The achievement is still displayed as 75 percent complete.

If `percentComplete` is set to 100, the achievement is unlocked.

If `percentComplete` is set to a number greater than 100, the API behaves as if you set the number to exactly 100.

### Updating achievements for the current title

You can update achievements for the current title by calling [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md), as follows.

**Flat C API**

```cpp theme={null}
auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.
    auto result = XAsyncGetStatus(asyncBlock, false);
    if (SUCCEEDED(result))
    {
        // The achievement was updated.
    }
    else if (result == HTTP_E_STATUS_NOT_MODIFIED)
    {
        // The achievement wasn't updated.
    }
    else
    {
        // The achievement failed to update.
    }
};

HRESULT hr = XblAchievementsUpdateAchievementAsync(
    xboxLiveContext,
    xboxUserId,
    achievementId.c_str(),
    percentComplete,
    asyncBlock.get()
);
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}
```

For more information, see the following:

* [XAsyncBlock](https://docs.xbox.com/reference/system/xasync/structs/xasyncblock.md)
* [XAsyncGetStatus](https://docs.xbox.com/reference/system/xasync/functions/xasyncgetstatus.md)
* [XblAchievementsUpdateAchievementAsync](https://docs.xbox.com/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementasync.md)

### Updating achievements for a different title

You can update achievements for another `titleId` by using [XblAchievementsUpdateAchievementForTitleIdAsync](https://docs.xbox.com/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementfortitleidasync.md), as follows.

**Flat C API**

```cpp theme={null}
auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.
    auto result = XAsyncGetStatus(asyncBlock, false);
    if (SUCCEEDED(result))
    {
        // The achievement was updated.
    }
    else if (result == HTTP_E_STATUS_NOT_MODIFIED)
    {
        // The achievement wasn't updated.
    }
    else
    {
        // The achievement failed to update.
    }
};

HRESULT hr = XblAchievementsUpdateAchievementForTitleIdAsync(
    xboxLiveContext,
    xboxUserId,
    titleId,
    scid,
    achievementId.c_str(),
    percentComplete,
    asyncBlock.get()
);
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}
```

For more information, see the following:

* [XAsyncBlock](https://docs.xbox.com/reference/system/xasync/structs/xasyncblock.md)
* [XAsyncGetStatus](https://docs.xbox.com/reference/system/xasync/functions/xasyncgetstatus.md)
* [XblAchievementsUpdateAchievementForTitleIdAsync](https://docs.xbox.com/reference/live/xsapi-c/achievements_c/functions/xblachievementsupdateachievementfortitleidasync.md)

## Troubleshooting

To group a failure HRESULT into an actionable category, call [XblGetErrorCondition](https://docs.xbox.com/reference/live/xsapi-c/errors_c/functions/xblgeterrorcondition.md).

Don't retry failed updates yourself. If an update fails because of a network or authentication problem, throttling (HTTP 429), a server error (HTTP 5xx), or an unclassified error, XSAPI queues it as an offline event and sends it when the device is back online. In that case, `XAsyncGetStatus` returns the result of queuing the event, which is normally `S_OK`. If you retry, the service can receive the update twice.

The following results can reach your game:

| Result | Possible cause | What to do |
| - | - | - |
| `HTTP_E_STATUS_NOT_MODIFIED` (`XblErrorCondition::Http304NotModified`) | The achievement is already unlocked, or the new progress value isn't higher than the value that the service has recorded. | No action is required. |
| Another HTTP 4xx status, such as 400, 403, or 404 | The service rejected the request, for example because the achievement ID isn't configured for your title or sandbox. | Check the achievement ID and your title's configuration. Retrying the same request fails the same way. |
| `E_INVALIDARG` | The context, achievement ID, or async block is null. | Check the arguments. Pass a `percentComplete` value from 1 to 100. |
| `E_XBL_NOT_INITIALIZED` | XSAPI isn't initialized. | Call `XblInitialize` before you update achievements. |

[Return to the top of this topic.](#top)


## Related topics

- [Title-managed Achievements example code (contents)](https://docs.xbox.com/services/xbox-services/player-data/achievements/title-managed/how-to/live-achievements-howto-nav.md)
- [Stats and achievements](https://docs.xbox.com/build/steam-porting-guide/features/stats-and-achievements.md)
- [Player Data](https://docs.xbox.com/services/xbox-services/player-data/achievements/title-managed/how-to/index.md)
- [Unreal development for PC: get started (earlier versions)](https://docs.xbox.com/build/gdk-and-engines/unreal/unreal-legacy.md)
- [Event-based vs. title-managed Achievements](https://docs.xbox.com/services/xbox-services/player-data/achievements/live-achievements-eb-vs-tm.md)
