MyStars FaaS Recipients API
Resolve a recipient and check delivery eligibility before ordering.
Resolve a recipient and check delivery eligibility before ordering.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/mystars-recipients-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
openapi: 3.2.0
info:
title: MyStars FaaS — Fulfilment Recipients API
version: 1.12.0
summary: Buy Telegram Stars & Premium for any @username, paid in GRAM (ex TON) or USDT (TON).
description: 'MyStars FaaS is a public B2B API for buying and reselling **Telegram Stars** and **Telegram Premium**, delivered to any Telegram `@username` and paid in **GRAM (ex TON)** or **USDT (TON)**.
Quote a price, check the recipient, create an order, then pay the returned on-chain address. MyStars holds the payment, fulfils delivery through Fragment, and notifies you with a signed webhook when the order is delivered or reversed.
## Getting an API key
Keys are issued inside our Telegram bot — no dashboard, no signup form. Open [@my_stars_tg_bot](https://t.me/my_stars_tg_bot), tap **API access**, and copy your secret. Send it in the `X-Api-Key` header on every request.
## Typed SDKs
Skip raw HTTP with an official client: `npm install @mystars-tg/faas-sdk` (TypeScript) or `pip install mystars-faas` (Python). Each wraps every call with retries, idempotency, typed errors, and on-chain payment builders.
## Documentation
Full guides — quick start, rate limits, idempotency, webhooks, and reversal rules — live at the [developer portal](https://mystars.tg/docs).
'
contact:
name: MyStars API support
url: https://t.me/Mystars_support_bot
license:
name: Proprietary
url: https://mystars.tg/terms
servers:
- url: https://api.mystars.tg
description: Production
security:
- ApiKeyAuth: []
tags:
- name: Recipients
description: Resolve a recipient and check delivery eligibility before ordering.
paths:
/v1/recipients/check:
post:
tags:
- Recipients
operationId: checkRecipient
summary: Check a recipient
description: 'Resolve a `@username` and check whether they can receive the requested
item, before you create an order. Read-only and fail-open — a transient
oracle hiccup resolves to `eligible: true` rather than blocking you.
**Why `type` is required.** The check runs against the very product you
intend to order, so it must know which one. Pass `type: stars` to resolve a
**Stars** recipient, or `type: premium` to resolve a **Premium-gift**
recipient (the Premium path also takes `months` — 3, 6 or 12). Always check
with the same `type` you''ll use in `POST /v1/orders`: a Stars check does not
prove a Premium gift will be accepted, and vice-versa.
> ⚠️ **A recipient who already has an active Premium subscription cannot be
> gifted Premium.** Telegram blocks gifting a Premium subscription to anyone
> whose subscription is still active (for example, an annual plan that has
> not expired yet) — this is **Telegram''s restriction, not ours**. The check
> surfaces it as `eligible: false` with `reason: "already_subscribed"` and
> Telegram''s verbatim wording in `telegram_message`. The same recipient also
> makes `POST /v1/orders` fail with `422 recipient_ineligible`: no order is
> created and you are not charged. Pre-flighting Premium recipients here is
> the cheapest way to tell your user *before* they pay.
**Rate limit:** this endpoint carries a tighter per-tenant cap of 60
requests/min (in addition to the standard per-tenant budget), because each
call performs a live upstream lookup. If you exceed this,
you receive a `429` and should back off for the remainder of the minute.
'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RecipientCheckRequest'
x-codeSamples:
- lang: shell
label: cURL
source: "curl -X POST https://api.mystars.tg/v1/recipients/check \\\n -H \"X-Api-Key: $MYSTARS_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"type\":\"stars\",\"recipient\":{\"username\":\"durov\"}}'\n"
- lang: typescript
label: TypeScript SDK
source: "import { MyStarsClient } from \"@mystars-tg/faas-sdk\";\n\nconst client = MyStarsClient.production(process.env.MYSTARS_API_KEY!);\n\nconst check = await client.checkRecipient({\n type: \"stars\",\n recipient: { username: \"durov\" },\n});\nif (!check.eligible) throw new Error(check.reason ?? \"ineligible\");\n"
- lang: python
label: Python SDK
source: "import os\n\nfrom mystars_faas import MyStarsClient\n\nclient = MyStarsClient.production(os.environ[\"MYSTARS_API_KEY\"])\n\ncheck = client.check_recipient(\"durov\", type=\"stars\")\nif not check.eligible:\n raise SystemExit(check.telegram_message)\n"
- lang: python
label: Python (HTTP)
source: "import requests\n\nresp = requests.post(\n \"https://api.mystars.tg/v1/recipients/check\",\n headers={\"X-Api-Key\": MYSTARS_API_KEY},\n json={\"type\": \"stars\", \"recipient\": {\"username\": \"durov\"}},\n)\nresp.raise_for_status()\nprint(resp.json())\n"
responses:
'200':
description: Resolution + eligibility result.
content:
application/json:
schema:
$ref: '#/components/schemas/RecipientCheckResult'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/RateLimited'
components:
responses:
BadRequest:
description: Malformed request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
RateLimited:
description: 'A rate limit was reached — the per-minute request budget, the tighter
pricing/recipient-check probe cap (60 req/min), the daily order cap, or the
per-recipient flood guard. See **Rate limits** in the overview. The
per-minute-budget responses also carry `RateLimit-*` + `Retry-After` headers.
'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: rate_limited
message: rate limit exceeded
Unauthorized:
description: Missing or invalid `X-Api-Key`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Recipient:
type: object
required:
- username
properties:
username:
type: string
description: 'Telegram @username (the leading `@` is optional, case-insensitive). After canonicalisation (strip `@`, lowercase) must match `[a-z0-9_]{1,32}` — invalid or oversized handles return 400.
'
pattern: ^@?[a-zA-Z0-9_]{1,32}$
example: durov
RecipientCheckResult:
type: object
required:
- resolved
- eligible
properties:
resolved:
type: boolean
description: Whether the @username was found on Telegram.
eligible:
type: boolean
description: Whether the recipient can receive the item.
recipient_name:
type:
- string
- 'null'
description: 'The resolved recipient''s display name from Fragment, when available (best-effort) — useful to confirm you''re sending to the right person. `null` if Fragment returned no name.
'
reason:
type:
- string
- 'null'
description: 'Permanent-rejection class, set only when `eligible` is false: `already_subscribed`, `not_found`, or `ineligible`. `null` when eligible.
'
enum:
- already_subscribed
- not_found
- ineligible
- null
telegram_message:
type:
- string
- 'null'
description: 'Fragment''s raw rejection text, propagated verbatim — set only when `eligible` is false. `null` when eligible.
'
indeterminate:
type: boolean
default: false
description: '`true` when the eligibility probe could not reach a verdict and this endpoint FAILED OPEN — `eligible` is then a permissive default, not a measurement. `false` on every real verdict (eligible or not).
Treat an indeterminate response as "unknown", never as "yes": the recipient has not been checked. It is safe to proceed to `POST /v1/orders` (which runs its own authoritative check), but do not present it to a buyer as a confirmed-deliverable recipient.
Always present since 1.11.0. Clients written against an earlier version saw the field absent; absent and `false` mean the same thing.
'
OrderType:
type: string
enum:
- stars
- premium
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
description: Stable machine error code to branch on.
enum:
- bad_request
- unauthorized
- forbidden
- not_found
- conflict
- recipient_ineligible
- rate_limited
- unavailable
- internal
message:
type: string
description: Human-readable description.
telegram_message:
type: string
description: A verbatim user-facing message from Fragment, when present.
RecipientCheckRequest:
type: object
required:
- type
- recipient
properties:
type:
description: 'The product to check — and the product you intend to order. `stars` resolves a Stars recipient; `premium` resolves a Premium-gift recipient and uses `months`. Must match the `type` you pass to `POST /v1/orders`; a Stars check does not prove a Premium gift will be accepted (Premium has extra eligibility rules — see the endpoint description).
'
allOf:
- $ref: '#/components/schemas/OrderType'
recipient:
$ref: '#/components/schemas/Recipient'
months:
type: integer
enum:
- 3
- 6
- 12
description: Only meaningful for `type=premium` (defaults to 3). Must be 3, 6, or 12.
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-Api-Key
description: 'Your secret API key. Get one from [@my_stars_tg_bot](https://t.me/my_stars_tg_bot) → **API access**, then send it in the `X-Api-Key` header on every request. Treat it like a password — anyone with the key can create orders on your tenant, read your order history, and cancel unpaid orders. Each order is settled by its own on-chain payment, so the key by itself cannot move funds. Rotate it any time with `/api_rotate` in the bot.
'
externalDocs:
description: MyStars FaaS API documentation
url: https://mystars.tg/docs