Drops

Drops reward viewers with in-game items for watching streams of your game, like Twitch Drops. You run a campaign for your game; viewers who watch live streams of it earn its drops, claim them on Xive, and your game grants the reward when your app reads their entitlements.

Drops cost nothing and pay nothing, for you or for viewers. A campaign only goes live once Xive has reviewed it.

Campaigns

Campaigns belong to an organization, not to a person, and each is tied to one of the organization's active applications: that app reads the campaign's entitlements. Owners and admins create and manage campaigns; developers can see them. A personal app can't run Drops.

FieldNotes
application_idRequired. One of the organization's active applications.
categoryRequired. The game: a stream category's slug or id (see category search).
nameRequired. 2 to 80 characters.
descriptionOptional. Up to 1,000 characters.
image_urlOptional. An https:// image on one of the allowed image hosts.
account_link_urlOptional. An https:// page where viewers connect their game account. See Linking game accounts.
starts_at, ends_atRequired. ISO 8601 date and time; without a zone it's read as UTC. A campaign runs for at least an hour and up to 90 days.
channelsOptional. Up to 100 Xive usernames (or profile ids). Only these channels earn. Leave it empty to let any channel streaming the game earn.

The name, description and every drop's name go through Xive's content filter, the same one that checks stream titles.

Review and going live

  1. Draft. A new campaign is a draft that only your organization can see. Add its drops, and upload codes for any code drop.
  2. Submit for review. A campaign needs at least one drop, every code drop needs unused codes, its application must be active, and it must end more than an hour from now.
  3. Xive reviews it. A Xive administrator approves or rejects it. A rejected campaign comes back with a note; edit it and submit it again.
  4. Scheduled, then live. An approved campaign is live from starts_at to ends_at.
  5. Ended. It ends at ends_at, or earlier if you end it. Ending early stops earning at once; drops already earned stay claimable for their claim window.

Only a draft or a rejected campaign can be edited or deleted, and its drops changed. While it waits for review it can't be changed: withdraw it (it becomes a draft again), edit it, and submit it again. Once approved, the only changes are topping up codes and ending it. Xive can also end a campaign; see Claiming.

How viewers earn

A viewer earns a drop's minutes by watching. A minute counts when all of these are true:

  • The viewer is signed in to Xive.
  • The stream is live (not a replay or a clip).
  • The stream's current category is the campaign's game. If the creator switches category, earning stops until they switch back.
  • The channel is eligible: it's on the campaign's channel list, or the list is empty. A creator can turn Drops off for their channel in their Studio, and then nobody earns there.
  • It's inside the campaign's window, and the campaign is approved.

Only real watch time counts. Watch time is credited on the viewer's presence heartbeat, at most the time that actually passed: opening several tabs or several streams never earns faster, and a long gap restarts the clock rather than counting the gap. A creator doesn't earn on their own stream. The same minutes count toward every drop of the campaign at once, as on Twitch. Changes (a stream going live, a category switch, a creator's switch, a new campaign) take about a minute to show up.

Drops

A campaign has up to 10 drops. Each one is a reward earned by watching for a number of minutes.

FieldNotes
nameRequired. Up to 80 characters.
image_urlOptional. Same image hosts as the campaign.
minutes_requiredRequired. 1 to 600 minutes of watching.
claim_window_daysOptional. How many days after the campaign ends the drop can still be claimed: 0 to 30, default 14.
reward_typeentitlement (the default): your game grants the reward when it reads the entitlement. code: the viewer also gets one of your uploaded codes.

Claiming

Viewers see their progress and claim earned drops in their Drops inventory at thexive.com/drops. Claiming creates an entitlement with fulfillment_status CLAIMED, which your app reads and marks FULFILLED once your game has granted it. Claiming twice gives the same entitlement back.

An earned drop can be claimed until the campaign's end (its ends_at, or when it was ended early) plus the drop's claim window. A campaign ended by Xive stops claims at once.

Linking game accounts

Your game needs to know which of its players is which Xive user. Use Sign in with Xive (OAuth) on a page of your own, and set it as the campaign's account_link_url: the viewer's inventory shows Connect your game account linking there.

  1. The player signs in with Xive on your page. Your app gets a user token.
  2. Read the Xive user id from the token: user_id from GET /api/oauth2/validate, or id from GET /api/apps/users. Store it against the player's game account.
  3. Match that id to the user_id of the entitlements you read.

With that user's token, the entitlements API returns only that user's entitlements — handy for granting rewards the moment a player links their account.

The entitlements API

Twitch's Drops entitlements shapes, on the bot API. Call it with any of your app's credentials: a xive_sa_ secret, an app access token, or a user token. It's app-level — no channel and no scope — but your app only ever sees the entitlements of your own organization's campaigns, from any of the organization's apps. A personal app sees nothing. A user token only sees that user's entitlements, whatever user_id says.

Get entitlements

GET /api/apps/drops/entitlements, oldest first.

ParameterNotes
idEntitlement ids, up to 100: repeat it (?id=a&id=b) or comma-separate it.
user_idA Xive user id.
campaign_idOne of your campaigns.
game_idA category id.
fulfillment_statusCLAIMED or FULFILLED.
firstPage size, 1 to 1,000. Default 20.
afterThe pagination.cursor from the previous page.
curl "https://api.thexive.com/api/apps/drops/entitlements?fulfillment_status=CLAIMED&first=100" \
  -H "Authorization: Bearer $XIVE_APP_SECRET"
{
  "success": true,
  "data": [
    {
      "id": "8d3e5c1a-2b4f-4c6d-9e8f-0a1b2c3d4e5f",
      "benefit_id": "5f0c9a7e-1d2b-4e3f-8a9b-c0d1e2f3a4b5",
      "drop_id": "5f0c9a7e-1d2b-4e3f-8a9b-c0d1e2f3a4b5",
      "campaign_id": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "timestamp": "2026-10-12T18:04:11.532Z",
      "user_id": "1f9a3b6c-7d8e-4f0a-9b1c-2d3e4f5a6b7c",
      "game_id": "512",
      "fulfillment_status": "CLAIMED",
      "last_updated": "2026-10-12T18:04:11.532Z"
    }
  ],
  "pagination": { "cursor": "MjAyNi0xMC0xMlQxODowNDoxMS41MzI0MTJafDhkM2U1YzFh…" }
}

benefit_id is Twitch's name for the drop; drop_id is the same id. timestamp is when the viewer claimed it. When pagination is empty ({}) there are no more pages; otherwise pass its cursor as after.

Update entitlements

PATCH /api/apps/drops/entitlements with up to 100 entitlement_ids and the fulfillment_status to set (FULFILLED once granted, or CLAIMED to undo).

curl -X PATCH https://api.thexive.com/api/apps/drops/entitlements \
  -H "Authorization: Bearer $XIVE_APP_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"entitlement_ids": ["8d3e5c1a-2b4f-4c6d-9e8f-0a1b2c3d4e5f"], "fulfillment_status": "FULFILLED"}'
{
  "success": true,
  "data": [
    { "status": "SUCCESS", "ids": ["8d3e5c1a-2b4f-4c6d-9e8f-0a1b2c3d4e5f"] }
  ]
}

The ids come back grouped by result; only groups with ids are listed:

StatusMeaning
SUCCESSUpdated (or already had that status).
INVALID_IDNot an entitlement id.
NOT_FOUNDNo such entitlement.
UNAUTHORIZEDNot one of your organization's, or not the token's user.
UPDATE_FAILEDSomething failed on Xive's side. Try those ids again.

Before Drops is switched on, both answer 503 with "code": "drops_unavailable".

Codes

A code drop hands each viewer who claims it one of the codes you upload — a key for your store, a redeemable item code. Upload them from the campaign's page in the Console: paste them one per line, or upload a .txt or .csv file (its first column).

  • Up to 10,000 codes per upload and 100,000 per drop. Duplicates are skipped.
  • Each code is given once, to one viewer, when they claim. The viewer sees it in their inventory.
  • You can top up codes while the campaign is live, until it ends. You can also remove the unused ones; codes already given stay with their viewers.
  • If a drop runs out of codes, claiming still creates the entitlement, without a code. Your game must grant those rewards itself: read the entitlements and fulfil them.

No EventSub: poll

There is no EventSub event for Drops, as on Twitch. Poll GET /api/apps/drops/entitlements?fulfillment_status=CLAIMED, grant what you find, then mark it FULFILLED. Every few minutes is plenty; when a player links their account or opens your game, check that user right away.

Limits

WhatLimit
Open campaigns per organization (drafts, in review, and approved ones that haven't ended)20
Drops per campaign10
Channels on a campaign's list100
Campaign window1 hour to 90 days
Minutes per drop1 to 600
Claim window0 to 30 days after the campaign ends (default 14)
Codes10,000 per upload, 100,000 per drop
Entitlements per page / per update1,000 / 100
Entitlements API callsYour app's normal request budget

In the Console

Open your organization in the Console and choose Drops campaigns. The organization's Drops page lists its campaigns with their status, and owners and admins create new ones there. Each campaign's page shows its status and what happens next, its drops with their stats (viewers progressing, earned, claimed, fulfilled, codes left), and, for owners and admins, the forms to edit, add drops, upload codes, submit, withdraw, end and delete.

The Console uses these routes with your Xive sign-in, not an application secret. A campaign of an organization you don't belong to answers 404; a developer trying to change one gets 403 with "code": "role_forbidden".

RouteWhat it does
GET /api/developer/orgs/{id}/dropsThe organization's campaigns, its applications and your permissions.
POST /api/developer/orgs/{id}/dropsThe campaign fields. Creates a draft.
GET /api/developer/drops/{campaignId}The campaign, its drops and their stats.
PATCH /api/developer/drops/{campaignId}Any of the campaign fields. Draft or rejected only.
DELETE /api/developer/drops/{campaignId}Draft or rejected only.
POST /api/developer/drops/{campaignId}/submitDraft or rejected → in review.
POST /api/developer/drops/{campaignId}/withdrawIn review → draft.
POST /api/developer/drops/{campaignId}/endEnds an approved campaign now.
POST /api/developer/drops/{campaignId}/dropsThe drop fields. Adds a drop.
PATCH /api/developer/drops/{campaignId}/drops/{dropId}Any of the drop fields.
DELETE /api/developer/drops/{campaignId}/drops/{dropId}Removes a drop and its codes.
POST /api/developer/drops/{campaignId}/drops/{dropId}/codes{"codes": "one per line"} or a list. Answers added and duplicates.
DELETE /api/developer/drops/{campaignId}/drops/{dropId}/codesRemoves the drop's unused codes.

Before Drops is switched on, the list answers "available": false and the other routes 503 with "code": "drops_unavailable".