> ## 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 a user's Presence via XSAPI C

> Flat C sample using XblPresenceSetPresenceAsync to update an XBOX services user's online Presence status and advertise current in-game activity.

This topic provides example code for setting a user's online Presence status. XBOX services Rich Presence provides features for advertising a player's current activity to other players.

For more information, see [Rich Presence overview](https://docs.xbox.com/services/xbox-services/community/presence/live-presence-overview.md).

## Updating a user's online Presence status

This example code sets a user's online Presence status.

The following example uses the 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 XAsyncBlock*.
    HRESULT hr = XAsyncGetStatus(asyncBlock, false);
    if (FAILED(hr))
    {
        // Log the failure. To choose how to handle it, call XblGetErrorCondition(hr).
    }
};

HRESULT hr = XblPresenceSetPresenceAsync(xboxLiveContext, true, nullptr, 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)
* [XblPresenceSetPresenceAsync](https://docs.xbox.com/reference/live/xsapi-c/presence_c/functions/xblpresencesetpresenceasync.md)

## Updating Rich Presence status

The following example sets the `playingMap` Rich Presence string for the user. In this example, `playingMap` is configured as a static string that has no tokens. `xboxLiveContext` is the `XblContextHandle` for the user, and `queue` is your game's task queue, or `nullptr` to use the process default task queue.

```cpp theme={null}
#include <memory>
#include <string.h>
#include <xsapi-c/services_c.h>

HRESULT SetRichPresence(XblContextHandle xboxLiveContext, XTaskQueueHandle queue)
{
    // Get the SCID that you passed to XblInitialize.
    const char* scid = nullptr;
    HRESULT hr = XblGetScid(&scid);
    if (FAILED(hr))
    {
        return hr;
    }

    XblPresenceRichPresenceIds ids{};
    if (strcpy_s(ids.scid, sizeof(ids.scid), scid) != 0)
    {
        return E_INVALIDARG;
    }
    ids.presenceId = "playingMap";

    // Use a new XAsyncBlock for each call.
    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 XAsyncBlock*.
        HRESULT result = XAsyncGetStatus(asyncBlock, false);
        if (FAILED(result))
        {
            // Log every failure. To choose how to handle it, call XblGetErrorCondition(result).
            // For XblErrorCondition::Http429TooManyRequests, don't retry right away.
        }
    };

    hr = XblPresenceSetPresenceAsync(xboxLiveContext, true, &ids, asyncBlock.get());
    if (SUCCEEDED(hr))
    {
        // The callback now owns the XAsyncBlock.
        asyncBlock.release();
    }
    return hr;
}
```

If the configured presence string requires explicit replacement strings, set `presenceTokenIds` to their configured string IDs in placeholder order, and set `presenceTokenIdsCount` to the array length.

If the `scid` or `presenceId` member is empty, the request includes only the active or inactive state and doesn't include a Rich Presence string.

For more information, see the following:

* [XblGetErrorCondition](https://docs.xbox.com/reference/live/xsapi-c/errors_c/functions/xblgeterrorcondition.md)
* [XblGetScid](https://docs.xbox.com/reference/live/xsapi-c/xbox_live_global_c/functions/xblgetscid.md)
* [XblPresenceRichPresenceIds](https://docs.xbox.com/reference/live/xsapi-c/presence_c/structs/xblpresencerichpresenceids.md)
* [XblPresenceSetPresenceAsync](https://docs.xbox.com/reference/live/xsapi-c/presence_c/functions/xblpresencesetpresenceasync.md)

## Rate limits and certification

The Presence service allows each user and title 3 writes in 15 seconds and 30 writes in 300 seconds. Update Rich Presence when the player's activity changes, and combine rapid changes into a single update. If you also refresh Rich Presence periodically, keep the combined rate within both limits.

If a call fails with `HTTP_E_STATUS_429_TOO_MANY_REQUESTS` (`XblErrorCondition::Http429TooManyRequests`), don't retry in a loop. The service response includes a Retry-After header, and XSAPI honors it.

Certification test [XR-132](https://docs.xbox.com/publishing/certification/xr/xr-132.md) fails a title whose request rate is at or above 10 times the sustain limit, which is 300 Presence writes in 300 seconds. This threshold isn't a safe operating allowance. For more information, see [Fine-grained rate limiting](https://docs.xbox.com/services/xbox-services/develop/best-practices/live-fine-grained-rate-limiting.md).


## Related topics

- [Rich Presence example code (contents)](https://docs.xbox.com/services/xbox-services/community/presence/how-to/live-presence-howto-nav.md)
- [Rich Presence overview](https://docs.xbox.com/services/xbox-services/community/presence/live-presence-overview.md)
- [How to](https://docs.xbox.com/services/xbox-services/community/presence/how-to/index.md)
- [How to use XBOX services APIs](https://docs.xbox.com/services/xbox-services/fundamentals/xbox-services-api/live-gs-xbl-apis.md)
- [XblPresenceSetPresenceAsync](https://docs.xbox.com/reference/live/xsapi-c/presence_c/functions/xblpresencesetpresenceasync.md)
