TL;DR
A API Heroku permite automatizar deploys, gerenciar aplicações, configurar add-ons e escalar infraestrutura de forma programática. Suporta OAuth 2.0, autenticação por token e endpoints RESTful para apps, dynos, builds e pipelines (10.000 req/hora/conta). Este guia mostra como configurar autenticação, acessar endpoints essenciais, integrar CI/CD e aplicar estratégias para deploys em produção.
Introdução
O Heroku é utilizado por mais de 4 milhões de aplicações em 170+ países. Se você constrói automações de deploy, pipelines CI/CD ou ferramentas para múltiplos apps, integrar com a API Heroku é essencial para eficiência.
Equipes com mais de 10 apps Heroku podem perder 8–12 horas/semana em deploys e configurações manuais. Uma integração sólida com a API automatiza o deploy, escala dynos conforme o tráfego e sincroniza configs entre ambientes.
Este guia aborda a integração completa com a API Heroku: autenticação por token, gestão de apps, dynos, builds, pipelines, add-ons e solução de problemas. No final, você terá uma integração pronta para produção.
💡 Dica: O Apidog facilita testes de integração de API: teste endpoints Heroku, valide autenticação, inspecione respostas e debugue configs em um único workspace. Importe specs, simule respostas e compartilhe cenários de teste com sua equipe.
O Que É a API Heroku?
A API de Plataforma RESTful do Heroku permite gerenciar aplicações e infraestrutura Heroku via código. Principais operações:
- Criar, configurar e excluir apps
- Escalar dynos e gerenciar processos
- Gerenciar builds/releases
- Provisionar/configurar add-ons
- Orquestrar pipelines e promoções
- Gerenciar domínios e certificados SSL
- Configurar log drains e monitoramento
- Gerenciar times e colaboradores
Funcionalidades Principais
| Funcionalidade | Descrição |
|---|---|
| Design RESTful | Métodos HTTP padrão, respostas JSON |
| Autenticação por Token | Token Bearer, suporte OAuth 2.0 |
| Requisições de Intervalo | Paginação para grandes volumes |
| Limite de Taxa | 10.000 req/hora/conta |
| Criações Idempotentes | Escritas seguras para repetição |
| Compressão Gzip | Economia de banda |
Visão Geral da Arquitetura da API
A base da API é:
https://api.heroku.com/
A API segue o padrão JSON:API, com versionamento e recursos consistentes.
Versões da API Comparadas
| Versão | Status | Autenticação | Caso de Uso |
|---|---|---|---|
| API da Plataforma (v3) | Atual | Token Bearer | Novas integrações |
| Integração GitHub | Atual | OAuth 2.0 | Apps conectados ao GitHub |
| Registro de Contêiner | Atual | Docker Auth | Deploys via contêiner |
Primeiros Passos: Configuração da Autenticação
Passo 1: Crie Sua Conta Heroku
- Acesse o site do Heroku
- Clique em Sign Up e crie uma conta
- Verifique o e-mail e conclua o cadastro
Passo 2: Instale a CLI do Heroku
A CLI do Heroku é essencial para gerar tokens e testar comandos rapidamente:
# macOS
brew tap heroku/brew && brew install heroku
# Windows
npm install -g heroku
# Linux
curl https://cli-assets.heroku.com/install.sh | sh
Passo 3: Gere o Token de API
Autentique-se pela CLI:
heroku login
# Abre navegador para autenticação
Gere tokens:
# Token de curta duração
heroku authorizations:create --short-lived
# Token de longa duração (CI/CD)
heroku authorizations:create --description "CI/CD Pipeline" --expires-in "1 year"
Dica de segurança: Guarde tokens em variáveis de ambiente, nunca no código!
# .env
HEROKU_API_KEY="sua_chave_api_aqui"
HEROKU_APP_NAME="seu-nome-app"
Passo 4: Autenticação por Token
Todas as requisições devem conter estes headers:
Authorization: Bearer {api_key}
Accept: application/vnd.heroku+json; version=3
Passo 5: Faça Sua Primeira Chamada de API
Teste sua autenticação via cURL:
curl -n https://api.heroku.com/account \
-H "Accept: application/vnd.heroku+json; version=3" \
-H "Authorization: Bearer $HEROKU_API_KEY"
Resposta esperada:
{
"id": "id-usuario-aqui",
"email": "desenvolvedor@example.com",
"name": "Nome do Desenvolvedor",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2026-03-20T14:22:00Z"
}
Passo 6: Implemente a Autenticação no Código
Exemplo de cliente reutilizável em JavaScript:
const HEROKU_API_KEY = process.env.HEROKU_API_KEY;
const HEROKU_BASE_URL = 'https://api.heroku.com';
const herokuRequest = async (endpoint, options = {}) => {
const response = await fetch(`${HEROKU_BASE_URL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${HEROKU_API_KEY}`,
'Accept': 'application/vnd.heroku+json; version=3',
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Heroku API Error: ${error.message}`);
}
return response.json();
};
// Uso
const account = await herokuRequest('/account');
console.log(`Logado como: ${account.email}`);
Gerenciamento de Aplicações
Criando um Novo App
const createApp = async (appName, region = 'us') => {
const response = await herokuRequest('/apps', {
method: 'POST',
body: JSON.stringify({
name: appName,
region: region
})
});
return response;
};
// Uso
const app = await createApp('meu-app-incrivel-2026');
console.log(`App criado: ${app.name}`);
console.log(`URL Git: ${app.git_url}`);
console.log(`URL Web: ${app.web_url}`);
Resposta esperada:
{
"id": "uuid-app-aqui",
"name": "meu-app-incrivel-2026",
"region": { "name": "us" },
"created_at": "2026-03-25T10:00:00Z",
"updated_at": "2026-03-25T10:00:00Z",
"git_url": "https://git.heroku.com/meu-app-incrivel-2026.git",
"web_url": "https://meu-app-incrivel-2026.herokuapp.com",
"owner": { "email": "desenvolvedor@example.com" },
"build_stack": { "name": "heroku-24" }
}
Listando Todos os Apps
const listApps = async (limit = 50) => {
const response = await herokuRequest(`/apps?limit=${limit}`);
return response;
};
// Uso
const apps = await listApps();
apps.forEach(app => {
console.log(`${app.name} - ${app.web_url}`);
});
Obtendo Detalhes de um App
const getApp = async (appName) => {
const response = await herokuRequest(`/apps/${appName}`);
return response;
};
// Uso
const app = await getApp('meu-app-incrivel-2026');
console.log(`Stack: ${app.build_stack.name}`);
console.log(`Região: ${app.region.name}`);
Atualizando Configuração do App
const updateApp = async (appName, updates) => {
const response = await herokuRequest(`/apps/${appName}`, {
method: 'PATCH',
body: JSON.stringify(updates)
});
return response;
};
// Uso
const updated = await updateApp('nome-antigo-app', {
name: 'nome-novo-app'
});
Excluindo um App
const deleteApp = async (appName) => {
await herokuRequest(`/apps/${appName}`, {
method: 'DELETE'
});
console.log(`App ${appName} excluído com sucesso`);
};
Gerenciamento de Dynos
Dimensionando Dynos
const scaleDyno = async (appName, processType, quantity) => {
const response = await herokuRequest(`/apps/${appName}/formation/${processType}`, {
method: 'PATCH',
body: JSON.stringify({
quantity: quantity
})
});
return response;
};
// Uso
const formation = await scaleDyno('meu-app', 'web', 3);
console.log(`Escalado para ${formation.quantity} dynos de ${processType}`);
Obtendo a Formação de Dynos
const getFormation = async (appName, processType = null) => {
const endpoint = processType
? `/apps/${appName}/formation/${processType}`
: `/apps/${appName}/formation`;
const response = await herokuRequest(endpoint);
return response;
};
// Uso
const formation = await getFormation('meu-app');
formation.forEach(proc => {
console.log(`${proc.type}: ${proc.quantity} dynos (@ ${proc.size})`);
});
Tamanhos de Dynos Disponíveis
| Tipo de Dyno | Caso de Uso | Custo/Mês |
|---|---|---|
| eco | Projetos hobby, demos | $5 |
| basic | Pequenas produções | $7 |
| standard-1x | Workloads padrão | $25 |
| standard-2x | Alto desempenho | $50 |
| performance | Produção crítica | $250+ |
| private | Isolamento empresarial | Personalizado |
Reiniciando Dynos
const restartDynos = async (appName, processType = null) => {
const endpoint = processType
? `/apps/${appName}/formation/${processType}`
: `/apps/${appName}/dynos`;
await herokuRequest(endpoint, {
method: 'DELETE'
});
console.log(`Dynos reiniciados para ${appName}`);
};
Executando Dynos Avulsos
const runCommand = async (appName, command) => {
const response = await herokuRequest(`/apps/${appName}/dynos`, {
method: 'POST',
body: JSON.stringify({
command: command,
size: 'standard-1x'
})
});
return response;
};
// Exemplo: rodar migração
const dyno = await runCommand('meu-app', 'npm run migrate');
console.log(`Dyno iniciado: ${dyno.id}`);
Variáveis de Configuração
Obtendo Variáveis
const getConfigVars = async (appName) => {
const response = await herokuRequest(`/apps/${appName}/config-vars`);
return response;
};
// Uso
const config = await getConfigVars('meu-app');
console.log(`DATABASE_URL: ${config.DATABASE_URL}`);
console.log(`NODE_ENV: ${config.NODE_ENV}`);
Configurando Variáveis
const setConfigVars = async (appName, variables) => {
const response = await herokuRequest(`/apps/${appName}/config-vars`, {
method: 'PATCH',
body: JSON.stringify(variables)
});
return response;
};
// Uso
const updated = await setConfigVars('meu-app', {
NODE_ENV: 'production',
API_SECRET: 'sua-chave-secreta',
LOG_LEVEL: 'info'
});
Boas Práticas
- Nunca commite segredos: sempre use variáveis de ambiente.
- Configs separadas por ambiente: staging ≠ produção.
- Gire segredos regularmente: troque chaves/senhas todo trimestre.
-
Prefixe variáveis:
STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET.
Gerenciamento de Builds e Releases
Criando um Build
const createBuild = async (appName, sourceBlobUrl) => {
const response = await herokuRequest(`/apps/${appName}/builds`, {
method: 'POST',
body: JSON.stringify({
source_blob: {
url: sourceBlobUrl
}
})
});
return response;
};
// Uso
const build = await createBuild('meu-app', 'https://storage.example.com/source.tar.gz');
console.log(`Build iniciado: ${build.id}`);
console.log(`Status: ${build.status}`);
Verificando Status do Build
const getBuild = async (appName, buildId) => {
const response = await herokuRequest(`/apps/${appName}/builds/${buildId}`);
return response;
};
const checkBuildStatus = async (appName, buildId, maxAttempts = 30) => {
for (let i = 0; i < maxAttempts; i++) {
const build = await getBuild(appName, buildId);
if (build.status === 'succeeded') {
console.log('Build bem-sucedido!');
return build;
} else if (build.status === 'failed') {
throw new Error(`Build falhou: ${build.output}`);
}
console.log(`Build em andamento... tentativa ${i + 1}`);
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error('Tempo limite do build');
};
Listando Releases
const listReleases = async (appName, limit = 10) => {
const response = await herokuRequest(`/apps/${appName}/releases?limit=${limit}`);
return response;
};
// Uso
const releases = await listReleases('meu-app');
releases.forEach(release => {
console.log(`v${release.version} - ${release.description} - ${release.created_at}`);
});
Rollback de Release
const rollback = async (appName, releaseId) => {
const response = await herokuRequest(`/apps/${appName}/releases`, {
method: 'POST',
body: JSON.stringify({
rollback: releaseId
})
});
return response;
};
// Uso
const rollbackRelease = await rollback('meu-app', 42);
console.log(`Revertido para v${rollbackRelease.version}`);
Gerenciamento de Pipeline
Criando um Pipeline
const createPipeline = async (pipelineName) => {
const response = await herokuRequest('/pipelines', {
method: 'POST',
body: JSON.stringify({
name: pipelineName
})
});
return response;
};
// Uso
const pipeline = await createPipeline('meu-app-pipeline');
console.log(`Pipeline criado: ${pipeline.id}`);
Adicionando Apps ao Pipeline
const addAppToPipeline = async (pipelineId, appName, stage) => {
const response = await herokuRequest('/pipeline-couplings', {
method: 'POST',
body: JSON.stringify({
pipeline: pipelineId,
app: appName,
stage: stage // 'development', 'staging', 'production'
})
});
return response;
};
// Uso
await addAppToPipeline(pipelineId, 'meu-app-dev', 'development');
await addAppToPipeline(pipelineId, 'meu-app-staging', 'staging');
await addAppToPipeline(pipelineId, 'meu-app-prod', 'production');
Promovendo Slug
const promoteSlug = async (slugId, toApp) => {
await herokuRequest('/promotions', {
method: 'POST',
body: JSON.stringify({
from: toApp,
to: toApp,
slug: slugId
})
});
console.log(`Slug ${slugId} promovido para ${toApp}`);
};
Gerenciamento de Add-Ons
Provisionando Add-Ons
const provisionAddon = async (appName, addonPlan, config = {}) => {
const response = await herokuRequest('/addon-attachments', {
method: 'POST',
body: JSON.stringify({
app: appName,
plan: addonPlan,
config: config
})
});
return response;
};
// Uso
const db = await provisionAddon('meu-app', 'heroku-postgresql:mini', {});
console.log(`Banco de dados provisionado: ${db.addon.name}`);
console.log(`DATABASE_URL: ${db.addon.config_vars.DATABASE_URL}`);
Add-Ons Populares
| Add-On | Plano | Preço Inicial | Caso de Uso |
|---|---|---|---|
| heroku-postgresql | mini | $5/mês | Banco de dados |
| heroku-redis | mini | $5/mês | Cache/sessões |
| papertrail | choklad | $7/mês | Agregação de logs |
| sentry | developer | Grátis | Rastreamento de erros |
| mailgun | sandbox | Grátis | Entrega de e-mail |
| newrelic | lite | Grátis | Monitoramento |
Listando Add-Ons
const listAddons = async (appName) => {
const response = await herokuRequest(`/apps/${appName}/addons`);
return response;
};
// Uso
const addons = await listAddons('meu-app');
addons.forEach(addon => {
console.log(`${addon.plan.name} - $${addon.pricing.plan.price} - ${addon.state}`);
});
Removendo Add-Ons
const removeAddon = async (appName, addonId) => {
await herokuRequest(`/apps/${appName}/addons/${addonId}`, {
method: 'DELETE'
});
console.log(`Add-on ${addonId} removido de ${appName}`);
};
Gerenciamento de Domínio e SSL
Adicionando Domínios Personalizados
const addDomain = async (appName, domainName) => {
const response = await herokuRequest(`/apps/${appName}/domains`, {
method: 'POST',
body: JSON.stringify({
hostname: domainName
})
});
return response;
};
// Uso
const domain = await addDomain('meu-app', 'api.example.com');
console.log(`Alvo CNAME: ${domain.cname}`);
Configurando Certificados SSL
const addSslCertificate = async (appName, domainId, certificateChain, privateKey) => {
const response = await herokuRequest(`/apps/${appName}/domains/${domainId}/ssl_endpoint`, {
method: 'PATCH',
body: JSON.stringify({
ssl_cert: {
cert_chain: certificateChain,
private_key: privateKey
}
})
});
return response;
};
SSL Automatizado com ACM
const enableACM = async (appName, domainName) => {
const response = await herokuRequest(`/apps/${appName}/domains/${domainName}/sni_endpoint`, {
method: 'POST',
body: JSON.stringify({
kind: 'acm'
})
});
return response;
};
Limites de Taxa e Cotas
Entendendo os Limites
- Padrão: 10.000 req/hora/conta
- Janela: 60 minutos contínuos
- Reset: Automático após janela
Se você ultrapassar, recebe HTTP 429.
Tratamento Programático de Limite de Taxa
const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await herokuRequest(endpoint, options);
// Cheque cabeçalhos RateLimit
const remaining = response.headers.get('RateLimit-Remaining');
const resetTime = response.headers.get('RateLimit-Reset');
if (remaining < 100) {
console.warn(`Cota baixa restante: ${remaining}, reseta em ${resetTime}`);
}
return response;
} catch (error) {
if (error.message.includes('429') && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`Limite de taxa atingido. Tentando novamente em ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
};
Cabeçalhos de Limite
| Cabeçalho | Descrição |
|---|---|
RateLimit-Limit |
Máximo de req/hora |
RateLimit-Remaining |
Restantes na janela |
RateLimit-Reset |
Timestamp Unix do reset |
Solução de Problemas Comuns
Problema: 401 Autenticação Falha
- Sintoma: “Invalid credentials”
-
Soluções:
- Confirme a API key:
heroku authorizations - Verifique validade do token (duração)
- Remova espaços extras em variáveis
- Gere novo token:
heroku authorizations:create
- Confirme a API key:
Problema: Nome de App Já Ocupado
- Sintoma: “name is already taken”
-
Soluções:
- Use nomes únicos (ex: sufixo aleatório)
- Nomes baseados em UUID:
app-${Date.now()} - Prefixos de equipe:
squad-proj-env
const generateUniqueAppName = (baseName) => {
const timestamp = Date.now().toString(36);
const random = Math.random().toString(36).substring(2, 6);
return `${baseName}-${timestamp}-${random}`;
};
Problema: Formação de Dyno Falha
- Sintoma: Erro ao escalar dynos
-
Soluções:
- Confirme o tipo de processo no Procfile
- Cheque cota de dynos
- Verifique se o app não está suspenso
- Revise uso:
heroku ps --app=meu-app
Problema: Build Falha por Timeout
- Sintoma: Build trava/expira após 30min
-
Soluções:
- Use buildpack correto
- Faça cache de dependências
- Quebre builds grandes
- Use slugs pré-construídos
Problema: Limite de Taxa Excedido
- Sintoma: HTTP 429
-
Soluções:
- Enfileire requests
- Use backoff exponencial
- Agrupe requisições
- Monitore cabeçalhos de limite
// Limitador de taxa simples
class HerokuRateLimiter {
constructor(requestsPerMinute = 150) {
this.queue = [];
this.interval = 60000 / requestsPerMinute;
this.processing = false;
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject });
this.process();
});
}
async process() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
while (this.queue.length > 0) {
const { requestFn, resolve, reject } = this.queue.shift();
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
}
if (this.queue.length > 0) {
await new Promise(r => setTimeout(r, this.interval));
}
}
this.processing = false;
}
}
Checklist de Implantação em Produção
Antes de ir para produção, garanta que:
- [ ] Use tokens de API de longa duração para CI/CD
- [ ] Tokens armazenados em gerenciadores de segredo (Vault, AWS Secrets)
- [ ] Implemente limite de taxa/enfileiramento
- [ ] Adicione tratamento de erros robusto
- [ ] Logue todas as chamadas de API
- [ ] Monitore uso de horas de dyno
- [ ] Configure log drains para logs externos
- [ ] Use promoções de pipeline para CI/CD
- [ ] Habilite gerenciamento automático de SSL
- [ ] Tenha backup de banco de dados
Monitoramento e Alerta
Monitore métricas:
const metrics = {
apiCalls: {
total: 0,
successful: 0,
failed: 0,
rateLimited: 0
},
dynoHours: {
used: 0,
quota: 1000
},
deployments: {
successful: 0,
failed: 0,
avg_duration: 0
}
};
// Alerta de falha
const failureRate = metrics.apiCalls.failed / metrics.apiCalls.total;
if (failureRate > 0.05) {
sendAlert('Taxa de falha da API Heroku acima de 5%');
}
if (metrics.dynoHours.used > metrics.dynoHours.quota * 0.8) {
sendAlert('Uso de horas de dyno acima de 80%');
}
Casos de Uso do Mundo Real
Pipeline CI/CD Automatizado
Contexto: Equipe SaaS automatiza deploys do GitHub.
- Desafio: Deploy manual = erros/atrasos
- Solução: GitHub Actions + API Heroku
- Resultado: Deploys zero downtime, 90% mais rápidos
Fluxo:
- Push no GitHub aciona workflow
- CI executa testes
- API Heroku faz build do código
- Promove staging → produção
- Notifica a equipe
Gerenciamento de Multi-Ambientes
Contexto: Consultoria gerencia 50+ apps.
- Desafio: Sincronizar configs manualmente
- Solução: Gestão centralizada via API Heroku
- Resultado: Consistência e economia de 8h/semana
Chaves:
- Sincronize configs dev/staging/prod
- Automatize add-ons
- Operações em massa para clientes
Autoescalamento Baseado em Tráfego
Contexto: E-commerce lida com picos de acesso.
- Desafio: Escalar manualmente em eventos
- Solução: Autoescalamento via API Heroku
- Resultado: Zero downtime em picos 10x
Como:
- Monitore via API de métricas
- Escale quando latência p95 > 500ms
- Reduza dynos em baixa demanda
- Alerta em uso elevado
Conclusão
A API Heroku oferece controle total da plataforma via código. Pontos principais:
- Autenticação por token exige armazenamento seguro e rotação
- Limite de taxa (10K/hora): monitore e trate programaticamente
- Gerenciamento de pipeline = CI/CD robusto
- Tratamento de erros = deploy confiável
- Apidog otimiza testes de API e colaboração em times Heroku
Seção de Perguntas Frequentes
Para que serve a API Heroku?
Permite gerenciar apps, dynos, add-ons e infraestrutura via código. Útil para automação CI/CD, ferramentas multi-app, autoescalamento e dashboards de monitoramento.
Como obtenho uma chave de API Heroku?
Instale a CLI, rode heroku login e crie autorização com heroku authorizations:create. Armazene o token em variáveis de ambiente.
A API Heroku é gratuita para usar?
Sim, mas você paga pelos recursos provisionados (dynos, add-ons). Limite de 10.000 req/hora/conta.
Que autenticação a API Heroku usa?
Token Bearer. Adicione Authorization: Bearer {api_key} em cada requisição. Tokens podem durar de 1h a 1 ano.
Como lido com limites de taxa?
Monitore RateLimit-Remaining e implemente enfileiramento. Use backoff exponencial ao receber HTTP 429. Evite ultrapassar 150 req/min.
Posso implantar sem Git?
Sim. Use a API de Builds e envie o código via URL de blob (S3, GCS etc).
Como automatizo deploys?
Use a API de Pipeline para configurar CI/CD: crie builds, promova slugs e integre com GitHub ou CI próprio.
Qual a diferença entre release e build?
Build: compila o código-fonte.
Release: combina o slug do build com configs para deploy.
Como faço rollback de um deploy que falhou?
Liste releases, depois POST em /releases com rollback: <release_id>. Heroku cria novo release na versão anterior.
Posso gerenciar múltiplas contas Heroku?
Sim, basta alternar o token em HEROKU_API_KEY para cada conta.

Top comments (0)