Skip to main content

Guides

Put a stable ID for the person using your app in the X-End-User-ID header. PoYo stores that ID against the API key that sent it. You can block that person later without rotating or disabling the key.

Where it applies

Send the header on:
  • Unified generation: POST https://api.poyo.ai/api/generate/submit
  • Native Chat:
    • POST /v1/chat/completions
    • POST /v1/responses
    • POST /v1/messages (Claude Messages, authenticated with x-api-key)
    • POST /v1beta/models/{model}:generateContent and :streamGenerateContent

API key switch

On the API Key page, open the End users dialog for that API key. The switch is Require an end user ID. Turn on Require an end user ID in the End users dialog for that API key. Generation and chat requests must then include X-End-User-ID. If it is missing, POST /api/generate/submit and native Chat return HTTP 400 and message is The X-End-User-ID header is missing. This API key requires it on generation and chat requests. While Require an end user ID is off, requests without the header keep working. PoYo does not look up a block. A request that sends the header is still checked for a block on that ID. The first time an ID is seen, PoYo records it.

Header and ID rules

User-1 and user-1 are different IDs. Characters outside that set, or a value longer than 128 characters, return HTTP 400 with message End user ID is invalid. Use 1-128 characters: letters, numbers, and . _ : -.. An empty or whitespace-only value is treated as a missing header.

Block an end user

A block applies to this API key + this end-user ID. Other IDs on the same key still work, and the key itself stays active. On the API Key page, open the End users dialog. There you can turn Require an end user ID on or off, search recorded IDs, block an ID, and unblock it. A blocked ID returns HTTP 403 and message is end_user_blocked. The check runs when the header is present. It also runs for every submit and native Chat request when Require an end user ID is on, because those requests must include the header.

Errors

Read error.message to tell these cases apart.
The invalid-ID response uses the same JSON shape as the example. Only error.message changes. A blocked ID uses code 403 and error.type permission_error.

Submit example

Chat example

Claude Messages uses the same X-End-User-ID header next to x-api-key: