Gramix API v1
Use este guia como contrato para desenvolver sua integração no servidor.
Informações gerais
A API pública permite consultar o saldo, adicionar fundos à carteira e comprar Telegram Stars, Telegram Premium e GRAM.
URL base
https://api.gramix.io/api/v1Formato dos dados
- Os corpos das requisições e as respostas da API usam application/json.
- Os valores monetários são enviados como strings com quatro casas decimais. Para fazer cálculos exatos, use tipos decimais ou mantenha os valores como strings.
- As datas dos webhooks usam o formato ISO 8601. Não dependa de campos JSON desconhecidos.
Métodos disponíveis
| Método | Endpoint | Finalidade | Status HTTP |
|---|---|---|---|
GET | /api/v1/wallets/balance | Retorna o saldo atual. | 200 |
POST | /api/v1/wallets/balance | Cria ou retorna o address e o memo necessários para adicionar fundos à carteira na rede TON. | 201 |
POST | /api/v1/purchase/stars | Compra de 50 a 1.000.000 de Telegram Stars para o nome de usuário do Telegram informado. | 201 |
POST | /api/v1/purchase/premium/{duration} | Compra o Telegram Premium por 3, 6 ou 12 meses. | 201 |
POST | /api/v1/purchase/gram | Compra e envia de 1 a 10.000 GRAM para o destinatário do Telegram informado. | 201 |
Autenticação
Todos os métodos exigem uma chave de API ativa enviada no cabeçalho HTTP x-api-key.
x-api-key: YOUR_API_KEYExemplo de requisição
curl --request GET 'https://api.gramix.io/api/v1/wallets/balance' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Accept: application/json'Se o cabeçalho estiver ausente ou a chave for inválida, revogada ou inativa, a API retornará 401 Unauthorized.
Formato geral das respostas
Resposta bem-sucedida
Uma resposta bem-sucedida contém statusCode e data. As requisições POST retornam o status HTTP 201.
{
"statusCode": 200,
"data": {}
}Resposta de erro
Os erros contêm statusCode e uma message legível. A lógica do cliente deve se basear principalmente no código de status HTTP.
{
"statusCode": 400,
"message": "Idempotency-Key header is required"
}Erros comuns
| Status HTTP | message |
|---|---|
400 | Bad Request |
401 | Unauthorized |
403 | Insufficient balance |
404 | Not Found |
405 | Method Not Allowed |
500 | Internal server error |
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"statusCode": 401,
"message": "Unauthorized"
}HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"statusCode": 403,
"message": "Insufficient balance"
}Esquemas comuns
PaymentCurrency
paymentCurrency seleciona o saldo usado para pagar a compra. Apenas gram e usdt em letras minúsculas são aceitos.
type PaymentCurrency = "gram" | "usdt";RecipientName
recipientName é o nome de usuário do destinatário no Telegram sem @. Deve ter de 5 a 32 caracteres e pode conter letras latinas minúsculas, números e _.
durov
user_123
telegram_user@durov
User123
1username
user-name
abcPurchaseRequestBase
{
"recipientName": "telegram_user",
"paymentCurrency": "usdt"
}PurchaseResponse
Todos os métodos de compra retornam orderId, status e idempotencyKey. Um pedido novo normalmente tem o status processing.
{
"statusCode": 201,
"data": {
"orderId": "7ba77616-7706-4215-9e6f-b6c67e4df292",
"status": "processing",
"idempotencyKey": "order_20260713_0001"
}
}type OrderStatus = "created" | "processing" | "completed" | "failed" | "canceled";Idempotência das compras
Todos os métodos /purchase/* exigem um cabeçalho idempotency-key com 8 a 64 caracteres.
idempotency-key: UNIQUE_REQUEST_KEY- São aceitos letras latinas, números, _ e -. A chave deve ser única para cada chave de API.
- Após um erro de rede, repita a mesma requisição com a mesma chave. Use uma nova chave para uma nova compra.
order_20260713_0001
01J2Y5VN7CV8ZQ7DPZ9J0P6E4M
client-req-12345678Possíveis erros
{
"statusCode": 400,
"message": "Idempotency-Key header is required"
}{
"statusCode": 400,
"message": "Idempotency-Key must be between 8 and 64 characters"
}{
"statusCode": 400,
"message": "Idempotency-Key contains invalid characters"
}Carteiras
GET /api/v1/wallets/balance
Retorna o saldo atual.
| Cabeçalhos | Obrigatório | Descrição |
|---|---|---|
x-api-key | sim | Autenticação |
Accept | não | application/json |
Exemplo de requisição
curl --request GET 'https://api.gramix.io/api/v1/wallets/balance' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Accept: application/json'{
"statusCode": 200,
"data": {
"gram": "14.2500",
"usdt": "125.5000"
}
}POST /api/v1/wallets/balance
Cria ou retorna o address e o memo necessários para adicionar fundos à carteira na rede TON.
| Cabeçalhos | Obrigatório | Descrição |
|---|---|---|
x-api-key | sim | Autenticação |
Accept | não | application/json |
curl --request POST 'https://api.gramix.io/api/v1/wallets/balance' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Accept: application/json'{
"statusCode": 201,
"data": {
"address": "UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"memo": "a1b2c3d4e5f6g7h8"
}
}Os depósitos são creditados de forma assíncrona. GRAM é creditado em gram, enquanto o USDT na rede TON é creditado em usdt.
Fluxo de recarga recomendado
POST /wallets/balance- Sempre inclua o memo no comentário da transação ou no forward payload. Sem ele, a transferência não será creditada automaticamente.
GET /wallets/balance
Compras
As compras são processadas de forma assíncrona. A API valida a requisição e o saldo, cria o pedido, debita os fundos e retorna orderId com o status processing.
Se o pedido passar para failed, o valor debitado será devolvido ao mesmo saldo.
POST /api/v1/purchase/stars
Compra de 50 a 1.000.000 de Telegram Stars para o nome de usuário do Telegram informado.
| Cabeçalhos | Obrigatório | Descrição |
|---|---|---|
x-api-key | sim | Autenticação |
idempotency-key | sim | 8–64 |
Accept | não | application/json |
Content-Type | sim | application/json |
{
"recipientName": "telegram_user",
"paymentCurrency": "usdt",
"stars": 500
}curl --request POST 'https://api.gramix.io/api/v1/purchase/stars' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'idempotency-key: stars_20260713_0001' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"recipientName": "telegram_user",
"paymentCurrency": "usdt",
"stars": 500
}'{
"statusCode": 201,
"data": {
"orderId": "7ba77616-7706-4215-9e6f-b6c67e4df292",
"status": "processing",
"idempotencyKey": "stars_20260713_0001"
}
}POST /api/v1/purchase/premium/{duration}
Compra o Telegram Premium por 3, 6 ou 12 meses.
| Cabeçalhos | Obrigatório | Descrição |
|---|---|---|
x-api-key | sim | Autenticação |
idempotency-key | sim | 8–64 |
Accept | não | application/json |
Content-Type | sim | application/json |
{
"recipientName": "telegram_user",
"paymentCurrency": "gram"
}curl --request POST 'https://api.gramix.io/api/v1/purchase/premium/6' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'idempotency-key: premium_6_20260713_0001' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"recipientName": "telegram_user",
"paymentCurrency": "gram"
}'{
"statusCode": 201,
"data": {
"orderId": "18ca3cce-8441-4de6-874a-fd34792ae1b5",
"status": "processing",
"idempotencyKey": "premium_6_20260713_0001"
}
}{
"statusCode": 400,
"message": "Invalid premium duration. Allowed values: 3, 6, 12"
}POST /api/v1/purchase/gram
Compra e envia de 1 a 10.000 GRAM para o destinatário do Telegram informado.
| Cabeçalhos | Obrigatório | Descrição |
|---|---|---|
x-api-key | sim | Autenticação |
idempotency-key | sim | 8–64 |
Accept | não | application/json |
Content-Type | sim | application/json |
{
"recipientName": "telegram_user",
"paymentCurrency": "usdt",
"gram": 2.5
}curl --request POST 'https://api.gramix.io/api/v1/purchase/gram' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'idempotency-key: gram_20260713_0001' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"recipientName": "telegram_user",
"paymentCurrency": "usdt",
"gram": 2.5
}'{
"statusCode": 201,
"data": {
"orderId": "882dd8ca-5d68-4b85-bb26-c25ee38d9a98",
"status": "processing",
"idempotencyKey": "gram_20260713_0001"
}
}Webhook de status do pedido
Se um webhookUrl estiver configurado para a chave de API, a API enviará uma requisição POST após a conclusão do pedido.
POST {webhookUrl}
Content-Type: application/jsonUm pedido bem-sucedido envia o evento order.completed; um pedido malsucedido envia order.failed.
{
"event": "order.completed",
"orderId": "7ba77616-7706-4215-9e6f-b6c67e4df292",
"status": "completed",
"processingStatus": "completed_fragment_purchase",
"type": "stars",
"amount": "7.6500",
"currency": "usd",
"recipientName": "telegram_user",
"createdAt": "2026-07-13T10:20:30.000Z"
}{
"event": "order.failed",
"orderId": "7ba77616-7706-4215-9e6f-b6c67e4df292",
"status": "failed",
"processingStatus": "failure_fragment_purchase",
"type": "stars",
"amount": "7.6500",
"currency": "usd",
"recipientName": "telegram_user",
"createdAt": "2026-07-13T10:20:30.000Z"
}Esquema do webhook
| Campo | Tipo | Restrições |
|---|---|---|
event | string | order.completed | order.failed |
orderId | UUID | — |
status | string | completed | failed |
type | string | stars | gram | premium_* |
amount | decimal(4) | — |
currency | string | gram | usd |
recipientName | string | — |
createdAt | ISO 8601 | — |
Requisitos do receptor do webhook
Retorne uma resposta HTTP 2xx o mais rápido possível, processe os eventos de forma idempotente e não dependa da ordem de entrega.
Exemplo completo do fluxo do cliente
- Consulte o saldo.
- Se necessário, obtenha os dados de recarga, adicione fundos à carteira e aguarde a alteração do saldo.
- Crie uma compra com um idempotency-key exclusivo.
- Salve orderId, status e idempotencyKey. Uma resposta 201 significa que o pedido foi aceito para processamento.
- Aguarde order.completed ou order.failed e associe o evento usando orderId.
GET /api/v1/wallets/balance
x-api-key: YOUR_API_KEYPOST /api/v1/wallets/balance
x-api-key: YOUR_API_KEYPOST /api/v1/purchase/stars
x-api-key: YOUR_API_KEY
idempotency-key: order_20260713_0001
Content-Type: application/json
{
"recipientName": "telegram_user",
"paymentCurrency": "usdt",
"stars": 500
}Exemplo de cliente TypeScript
type SuccessResponse<T> = {
statusCode: number;
data: T;
};
type ApiError = {
statusCode: number;
message: string;
};
type PurchaseResponse = {
orderId: string;
status: "created" | "processing" | "completed" | "failed" | "canceled";
idempotencyKey: string;
};
type WalletBalance = {
gram: string;
usdt: string;
};
const BASE_URL = "https://api.gramix.io";
async function apiRequest<T>(path: string, apiKey: string, init: RequestInit = {}): Promise<T> {
const response = await fetch(
`${BASE_URL}${path}`,
{
...init,
headers: {
Accept: "application/json",
"x-api-key": apiKey,
...(init.body ? { "Content-Type": "application/json" } : {}),
...init.headers,
},
},
);
const payload = (await response.json()) as SuccessResponse<T> | ApiError;
if (!response.ok) {
const error = payload as ApiError;
throw new Error(`[${error.statusCode}] ${error.message}`);
}
return (payload as SuccessResponse<T>).data;
}
export function getBalance(apiKey: string): Promise<WalletBalance> {
return apiRequest<WalletBalance>("/api/v1/wallets/balance", apiKey);
}
export function purchaseStars(
apiKey: string,
idempotencyKey: string,
input: {
recipientName: string;
paymentCurrency: "gram" | "usdt";
stars: number;
},
): Promise<PurchaseResponse> {
return apiRequest<PurchaseResponse>("/api/v1/purchase/stars", apiKey, {
method: "POST",
headers: { "idempotency-key": idempotencyKey },
body: JSON.stringify(input),
});
}Tudo pronto para iniciar a integração?
Crie uma chave de API e configure a URL do webhook.