{
	"components": {
		"schemas": {
			"Error": {
				"properties": {
					"error": {
						"description": "What went wrong, in English",
						"type": "string"
					},
					"status": {
						"description": "The HTTP status again",
						"type": "integer"
					}
				},
				"required": [
					"status",
					"error"
				],
				"type": "object"
			}
		}
	},
	"info": {
		"description": "Telegram catalog API. Search 2.7M channels, 260K groups and 400K bots by meaning using hybrid search (embedding similarity + BM25 keyword matches), or fetch the profile details and latest posts of channels, groups and bots by exact username, read live from Telegram.",
		"title": "Semagram",
		"version": "3.0.0",
		"x-guidance": "Use POST /api/agent/search to find Telegram channels, groups, and bots you cannot name: pass query param 'q' with your search text and optional 'limit' for max results (default 100, max 1000), priced at 0.01 USDC per 100 results. Use POST /api/agent/fetch when you already know the names: pass query param 'usernames' with up to 100 comma-separated Telegram usernames and get each one's profile details plus its latest posts read live from Telegram (text and captions only), priced at 0.01 USDC per name. Both require x402 payment."
	},
	"openapi": "3.1.0",
	"paths": {
		"/api/agent/fetch": {
			"post": {
				"operationId": "fetch",
				"parameters": [
					{
						"description": "Telegram usernames, comma-separated. Between 1 and 100 of them; more is refused with 400 and charged nothing. Each name is charged for whether or not the catalogue holds it.",
						"in": "query",
						"name": "usernames",
						"required": true,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"content": {
							"application/json": {
								"schema": {
									"items": {
										"properties": {
											"avatar_url": {
												"type": "string"
											},
											"bio": {
												"type": "string"
											},
											"canonical_username": {
												"type": "string"
											},
											"commands": {
												"description": "A bot's commands, name to description",
												"type": "object"
											},
											"description": {
												"type": "string"
											},
											"fetched_at": {
												"description": "When the entry was read from Telegram. The data is fetched live at the moment of the call.",
												"format": "date-time",
												"type": "string"
											},
											"lang": {
												"type": "string"
											},
											"mau": {
												"description": "Monthly active users. Bots only",
												"type": "integer"
											},
											"messages": {
												"description": "The latest posts, newest first, read live from Telegram. Present only for a channel, and then always an array. Absent for a group, a bot or an absent name: Telegram publishes no readable history for them. Text and captions only, never media files.",
												"items": {
													"properties": {
														"forwarded_from": {
															"description": "Where the post came from: the origin's username when the origin is public, true when the origin hid itself, absent when the post is original.",
															"type": [
																"string",
																"boolean"
															]
														},
														"id": {
															"type": "integer"
														},
														"link": {
															"type": "string"
														},
														"posted_at": {
															"format": "date-time",
															"type": "string"
														},
														"text": {
															"description": "The post's text, or the caption of a media post. Absent when the post carried neither.",
															"type": "string"
														},
														"view_count": {
															"type": "integer"
														}
													},
													"required": [
														"id",
														"posted_at",
														"link"
													],
													"type": "object"
												},
												"type": "array"
											},
											"name": {
												"type": "string"
											},
											"stale": {
												"description": "True when Telegram did not answer and the entry comes from the catalog instead; fetched_at is then the catalog snapshot time.",
												"type": "boolean"
											},
											"type": {
												"description": "channel, group, bot, absent when Telegram holds nothing under the name, or invalid when the name cannot be a Telegram username",
												"enum": [
													"channel",
													"group",
													"bot",
													"absent",
													"invalid"
												],
												"type": "string"
											},
											"user_count": {
												"description": "Subscribers for a channel, members for a group. Never present for a bot",
												"type": "integer"
											},
											"username": {
												"type": "string"
											}
										},
										"required": [
											"type",
											"username"
										],
										"type": "object"
									},
									"type": "array"
								}
							}
						},
						"description": "One entry per name asked for, in the order asked"
					},
					"400": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "No usernames given, or more than 100 of them. Nothing is charged."
					},
					"402": {
						"description": "Payment Required"
					},
					"409": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "The payment is already in use: another request carrying it is being answered, or it has already bought an answer. Nothing more is charged; a new request needs a new payment."
					},
					"429": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "Rate limited: the payer has asked for more names in the last minute than one payer may fetch (a budget of names, not of requests; 300 per minute by default). Nothing is charged, and the same payment may be sent again after Retry-After.",
						"headers": {
							"Retry-After": {
								"description": "Seconds to wait before retrying (60)",
								"schema": {
									"type": "integer"
								}
							}
						}
					},
					"502": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "Upstream catalogue service unavailable"
					}
				},
				"summary": "Stored messages and profile details for named Telegram channels, groups, and bots",
				"tags": [
					"Fetch"
				],
				"x-payment-info": {
					"basePrice": "0.01",
					"pricingMode": "dynamic",
					"pricingRule": "names * basePrice",
					"protocols": [
						"x402",
						"mpp"
					]
				}
			}
		},
		"/api/agent/search": {
			"post": {
				"operationId": "search",
				"parameters": [
					{
						"description": "Semantic search query",
						"in": "query",
						"name": "q",
						"required": true,
						"schema": {
							"type": "string"
						}
					},
					{
						"description": "Maximum number of results. Price scales with limit (ceil(limit/100) * base price).",
						"in": "query",
						"name": "limit",
						"required": false,
						"schema": {
							"default": 100,
							"maximum": 1000,
							"minimum": 1,
							"type": "integer"
						}
					},
					{
						"description": "Language filter (ISO 639-1 code, e.g. \"en\", \"ru\"). Entities whose language could not be detected are kept",
						"in": "query",
						"name": "lang",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"description": "Entity type filter (\"channel\", \"group\", or \"bot\")",
						"in": "query",
						"name": "kind",
						"required": false,
						"schema": {
							"enum": [
								"channel",
								"group",
								"bot"
							],
							"type": "string"
						}
					},
					{
						"description": "Minimum subscriber/member count",
						"in": "query",
						"name": "min_users",
						"required": false,
						"schema": {
							"type": "integer"
						}
					},
					{
						"description": "Maximum subscriber/member count",
						"in": "query",
						"name": "max_users",
						"required": false,
						"schema": {
							"type": "integer"
						}
					}
				],
				"responses": {
					"200": {
						"content": {
							"application/json": {
								"schema": {
									"items": {
										"properties": {
											"avatar_url": {
												"type": "string"
											},
											"bio": {
												"type": "string"
											},
											"description": {
												"type": "string"
											},
											"id": {
												"description": "Stable identifier of the entity",
												"type": "integer"
											},
											"kind": {
												"type": "string"
											},
											"lang": {
												"description": "Detected language (ISO 639-1), absent when it could not be detected",
												"type": "string"
											},
											"name": {
												"type": "string"
											},
											"user_count": {
												"type": "integer"
											},
											"username": {
												"type": "string"
											}
										},
										"required": [
											"id",
											"username"
										],
										"type": "object"
									},
									"type": "array"
								}
							}
						},
						"description": "Successful response"
					},
					"400": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "Empty q, an unknown kind, or min_users/max_users that is not a non-negative integer. Nothing is charged."
					},
					"402": {
						"description": "Payment Required"
					},
					"409": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "The payment is already in use: another request carrying it is being answered, or it has already bought an answer. Nothing more is charged; a new request needs a new payment."
					},
					"502": {
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Error"
								}
							}
						},
						"description": "Upstream search service unavailable"
					}
				},
				"summary": "Semantic search across Telegram channels, groups, and bots",
				"tags": [
					"Search"
				],
				"x-payment-info": {
					"basePrice": "0.01",
					"pricingMode": "dynamic",
					"pricingRule": "ceil(limit / 100) * basePrice",
					"protocols": [
						"x402",
						"mpp"
					]
				}
			}
		}
	},
	"x-discovery": {
		"ownershipProofs": []
	}
}
