Confere um cupom no checkout do deploy
POST /cloud/coupons/check
Escopo do token: servers:write. Recurso: Catálogo e cupons.
Não resgata: mostra a primeira fatura do plano (mês cheio) com o cupom. Cupom que não vale, por qualquer motivo (inexistente, vencido, esgotado, já usado, de outro plano), responde 422 coupon.unavailable com a mesma mensagem (“Cupom inválido ou indisponível.”, campo coupon_code): respostas diferentes diriam quais códigos existem. Limite de tentativas por conta e por IP (429 coupon.rate_limited). O cartão continua obrigatório.
Exemplo de requisição
Seção intitulada “Exemplo de requisição”Os exemplos leem o token da variável de ambiente HALVER_API_TOKEN (um token sc_live_… criado em Desenvolvedores › Tokens de API). Nunca escreva o token no código.
curl -X POST "https://dash.halver.com.br/api/v1/cloud/coupons/check" \ -H "Authorization: Bearer $HALVER_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "code": "BEMVINDO10", "plan_id": "a30bf51c-7749-4ed5-8983-8201f864273b"}'package main
import ( "fmt" "io" "net/http" "os" "strings" "time")
func main() { body := strings.NewReader(`{ "code": "BEMVINDO10", "plan_id": "a30bf51c-7749-4ed5-8983-8201f864273b"}`) req, err := http.NewRequest(http.MethodPost, "https://dash.halver.com.br/api/v1/cloud/coupons/check", body) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer "+os.Getenv("HALVER_API_TOKEN")) req.Header.Set("Content-Type", "application/json") client := &http.Client{Timeout: 30 * time.Second} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, err := io.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(resp.Status) fmt.Println(string(out))}import os
import requests
resp = requests.post( "https://dash.halver.com.br/api/v1/cloud/coupons/check", headers={ "Authorization": f"Bearer {os.environ['HALVER_API_TOKEN']}", }, json={ "code": "BEMVINDO10", "plan_id": "a30bf51c-7749-4ed5-8983-8201f864273b", }, timeout=30,)resp.raise_for_status()print(resp.json())Corpo da requisição
Seção intitulada “Corpo da requisição”application/json, obrigatório.
-
codestring obrigatório -
plan_idstring (uuid) obrigatório
{ "code": "BEMVINDO10", "plan_id": "a30bf51c-7749-4ed5-8983-8201f864273b"}Respostas
Seção intitulada “Respostas”Cupom válido.
Campos da resposta
-
card_requiredboolean obrigatórioO cartão continua obrigatório para o deploy.
-
codestring obrigatório -
descriptionstring obrigatório -
first_discount_centsinteger (int64) obrigatório -
first_gross_centsinteger (int64) obrigatório -
first_net_centsinteger (int64) obrigatório -
summarystring obrigatórioO desconto em palavras (ex. “10% na primeira fatura”).
{ "card_required": false, "code": "BEMVINDO10", "description": "Servidor de produção", "first_discount_cents": 89900, "first_gross_cents": 89900, "first_net_cents": 89900, "summary": ""}Todo erro vem como application/problem+json (RFC 9457), com um code estável, a mensagem em português em detail, o motivo de cada campo em errors (nos erros de validação) e o request_id, que você informa ao suporte. Veja a lista completa de códigos.
| Status | Quando | Códigos |
|---|---|---|
| 400 | Requisição inválida (JSON malformado, campo desconhecido, parâmetro inválido ou falha de validação). | validation_failed, request.invalid_json |
| 401 | Não autenticado (token ausente, inválido ou expirado; credenciais inválidas). | auth.unauthorized |
| 403 | Autenticado, mas sem permissão para a área ou a operação. | api_token.insufficient_scope |
| 422 | Entrada válida, mas viola uma regra de negócio. | coupon.unavailable |
| 429 | Limite de requisições excedido. Retry-After diz em quantos segundos cabe a próxima requisição; os limites de taxa também mandam RateLimit-Policy e RateLimit (draft-ietf-httpapi-ratelimit-headers). |
rate_limited, coupon.rate_limited |
{ "type": "about:blank", "title": "Forbidden", "status": 403, "detail": "o token não tem o escopo servers:write; crie um token com esse escopo em Desenvolvedores › Tokens de API", "code": "api_token.insufficient_scope", "request_id": "6f1c0b2a9e4d7c3b5a8f0e1d"}