TL;DR
Heroku API を使うと、デプロイ自動化やアプリ管理、アドオン構成、インフラのスケーリングをプログラムで実現できます。OAuth 2.0/トークン認証で、アプリ・ダイノ・ビルド・パイプライン操作が RESTful エンドポイントで可能。レート制限はアカウント単位で1時間10,000リクエスト。本記事では、認証設定から主要エンドポイント、CI/CD連携、本番デプロイ戦略まで具体的な手順とコード例で解説します。
はじめに
Heroku は世界170カ国・400万超のアプリを支えるPaaSです。デプロイ自動化やCI/CDパイプライン運用、多数のアプリ管理を目指す開発者にとって、Heroku API の活用は必須です。
実際、10以上の Heroku アプリを運用しているチームは、手動デプロイや設定変更に毎週8〜12時間を消費しがち。API統合で、デプロイの自動化・トラフィックに応じたダイノスケール・環境間の設定同期が短時間で実現できます。
本記事は、Heroku API の認証、アプリ/ダイノ/ビルド/パイプライン/アドオン管理からエラートラブル対応まで、実装重視で徹底解説します。読み終わる頃には、本番対応の Heroku API 連携が即実装できるはずです。
💡 Apidog は Heroku API テストや認証フロー検証、レスポンス検査、設定デバッグを一元管理できます。API 仕様インポート、モックレスポンス、チームシェアも強力にサポート。
Heroku API とは?
Heroku API は RESTful プラットフォーム API として、Heroku 上のアプリ・インフラ管理を自動化できます。
- アプリ作成/設定/削除
- ダイノのスケーリング・プロセス管理
- ビルド/リリース管理
- アドオンプロビジョニング
- パイプライン管理・昇格
- カスタムドメイン・SSL証明書管理
- ログ/監視・チーム管理
主な機能
| 機能 | 説明 |
|---|---|
| RESTful デザイン | JSONレスポンス・標準HTTPメソッド |
| トークン認証 | OAuth 2.0/ベアラートークン対応 |
| レンジリクエスト | 大量データはページネーション対応 |
| レート制限 | アカウント単位で1時間10,000リクエスト |
| 멱等な作成 | 書き込み系は安全なリトライ設計 |
| Gzip 圧縮 | 帯域節約のためレスポンス圧縮 |
API アーキテクチャ概要
- ベースURL:
https://api.heroku.com/ - JSON:API 仕様に準拠、リソース/関係性パターンが統一
API バージョン比較
| バージョン | ステータス | 認証 | ユースケース |
|---|---|---|---|
| プラットフォーム API (v3) | 現在 | ベアラートークン | すべての新規統合 |
| GitHub 統合 | 現在 | OAuth 2.0 | GitHub連携アプリ |
| コンテナレジストリ | 現在 | Docker認証 | コンテナデプロイ |
はじめに:認証設定
ステップ1:Heroku アカウント作成
- Heroku公式サイトへアクセス
- 「Sign Up」でアカウント登録
- メール認証
- プロファイル設定
ステップ2:Heroku CLI インストール
CLIでAPIトークン生成やコマンドテストが可能。
# macOS
brew tap heroku/brew && brew install heroku
# Windows
npm install -g heroku
# Linux
curl https://cli-assets.heroku.com/install.sh | sh
ステップ3:API トークン生成
# ログイン(ブラウザで認証)
heroku login
# 一時トークン発行
heroku authorizations:create --short-lived
# CI/CD用途など長期トークン
heroku authorizations:create --description "CI/CD Pipeline" --expires-in "1 year"
セキュリティ: トークンは
.env等の環境変数で管理し、コードに直書きしないこと。
# .env
HEROKU_API_KEY="your_api_key_here"
HEROKU_APP_NAME="your-app-name"
ステップ4:トークン認証ヘッダー
全APIリクエストで以下ヘッダーを必須指定。
Authorization: Bearer {api_key}
Accept: application/vnd.heroku+json; version=3
ステップ5:最初のAPIコール
認証テスト例:
curl -n https://api.heroku.com/account \
-H "Accept: application/vnd.heroku+json; version=3" \
-H "Authorization: Bearer $HEROKU_API_KEY"
期待レスポンス例:
{
"id": "user-id-here",
"email": "developer@example.com",
"name": "Developer Name",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2026-03-20T14:22:00Z"
}
ステップ6:コードで認証実装
Node.js用の再利用APIクライアント例:
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();
};
// 使用例
const account = await herokuRequest('/account');
console.log(`ログイン済みユーザー: ${account.email}`);
アプリケーション管理
新規アプリ作成
const createApp = async (appName, region = 'us') => {
const response = await herokuRequest('/apps', {
method: 'POST',
body: JSON.stringify({ name: appName, region }),
});
return response;
};
// 使用例
const app = await createApp('my-awesome-app-2026');
console.log(`作成: ${app.name}`);
console.log(`Git URL: ${app.git_url}`);
console.log(`Web URL: ${app.web_url}`);
レスポンス例
{
"id": "app-uuid-here",
"name": "my-awesome-app-2026",
"region": { "name": "us" },
"created_at": "2026-03-25T10:00:00Z",
"updated_at": "2026-03-25T10:00:00Z",
"git_url": "https://git.heroku.com/my-awesome-app-2026.git",
"web_url": "https://my-awesome-app-2026.herokuapp.com",
"owner": { "email": "developer@example.com" },
"build_stack": { "name": "heroku-24" }
}
アプリ一覧取得
const listApps = async (limit = 50) => {
return await herokuRequest(`/apps?limit=${limit}`);
};
// 使用例
const apps = await listApps();
apps.forEach(app => console.log(`${app.name} - ${app.web_url}`));
アプリ詳細取得
const getApp = async (appName) => {
return await herokuRequest(`/apps/${appName}`);
};
// 使用例
const app = await getApp('my-awesome-app-2026');
console.log(`スタック: ${app.build_stack.name}`);
console.log(`リージョン: ${app.region.name}`);
アプリ設定更新
const updateApp = async (appName, updates) => {
return await herokuRequest(`/apps/${appName}`, {
method: 'PATCH',
body: JSON.stringify(updates)
});
};
// アプリ名変更例
const updated = await updateApp('old-app-name', { name: 'new-app-name' });
アプリ削除
const deleteApp = async (appName) => {
await herokuRequest(`/apps/${appName}`, { method: 'DELETE' });
console.log(`アプリケーション ${appName} を削除しました`);
};
ダイノ管理
ダイノのスケーリング
const scaleDyno = async (appName, processType, quantity) => {
const response = await herokuRequest(`/apps/${appName}/formation/${processType}`, {
method: 'PATCH',
body: JSON.stringify({ quantity }),
});
return response;
};
// Webダイノを3個にスケール
const formation = await scaleDyno('my-app', 'web', 3);
console.log(`Scaled to ${formation.quantity} ${processType} dynos`);
ダイノ構成取得
const getFormation = async (appName, processType = null) => {
const endpoint = processType
? `/apps/${appName}/formation/${processType}`
: `/apps/${appName}/formation`;
return await herokuRequest(endpoint);
};
// 使用例
const formation = await getFormation('my-app');
formation.forEach(proc => console.log(`${proc.type}: ${proc.quantity} dynos (@ ${proc.size})`));
利用可能なダイノサイズ
| ダイノタイプ | ユースケース | 月額費用 |
|---|---|---|
| eco | ホビープロジェクト・デモ | 5ドル |
| basic | 小規模本番アプリ | 7ドル |
| standard-1x | 標準的なワークロード | 25ドル |
| standard-2x | 高性能アプリ | 50ドル |
| performance | 重要本番アプリ | 250ドル以上 |
| private | エンタープライズ分離 | カスタム |
ダイノ再起動
const restartDynos = async (appName, processType = null) => {
const endpoint = processType
? `/apps/${appName}/formation/${processType}`
: `/apps/${appName}/dynos`;
await herokuRequest(endpoint, { method: 'DELETE' });
console.log(`ダイノが ${appName} で再起動されました`);
};
ワンオフダイノ実行
const runCommand = async (appName, command) => {
const response = await herokuRequest(`/apps/${appName}/dynos`, {
method: 'POST',
body: JSON.stringify({ command, size: 'standard-1x' })
});
return response;
};
// 例: データベースマイグレーション
const dyno = await runCommand('my-app', 'npm run migrate');
console.log(`ダイノが開始されました: ${dyno.id}`);
設定変数
環境変数取得
const getConfigVars = async (appName) => {
return await herokuRequest(`/apps/${appName}/config-vars`);
};
// 使用例
const config = await getConfigVars('my-app');
console.log(`DATABASE_URL: ${config.DATABASE_URL}`);
console.log(`NODE_ENV: ${config.NODE_ENV}`);
環境変数設定
const setConfigVars = async (appName, variables) => {
return await herokuRequest(`/apps/${appName}/config-vars`, {
method: 'PATCH',
body: JSON.stringify(variables)
});
};
// 使用例
const updated = await setConfigVars('my-app', {
NODE_ENV: 'production',
API_SECRET: 'your-secret-key',
LOG_LEVEL: 'info'
});
環境変数のベストプラクティス
- シークレットはコミットしない:すべて環境変数で管理
- 環境ごとに変える:ステージング/本番で切替
- 定期的なローテーション:APIキーは四半期ごとに更新
-
プレフィックス付与:例
STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET
ビルドとリリース管理
ビルド作成(API経由デプロイ)
const createBuild = async (appName, sourceBlobUrl) => {
const response = await herokuRequest(`/apps/${appName}/builds`, {
method: 'POST',
body: JSON.stringify({
source_blob: { url: sourceBlobUrl }
})
});
return response;
};
// 使用例
const build = await createBuild('my-app', 'https://storage.example.com/source.tar.gz');
console.log(`ビルド開始: ${build.id}`);
console.log(`ステータス: ${build.status}`);
ビルドステータス取得・ポーリング
const getBuild = async (appName, buildId) => {
return await herokuRequest(`/apps/${appName}/builds/${buildId}`);
};
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('ビルド成功!');
return build;
} else if (build.status === 'failed') {
throw new Error(`ビルド失敗: ${build.output}`);
}
console.log(`ビルド進行中... ${i + 1} 回目`);
await new Promise(resolve => setTimeout(resolve, 5000));
}
throw new Error('ビルドタイムアウト');
};
リリース履歴表示
const listReleases = async (appName, limit = 10) => {
return await herokuRequest(`/apps/${appName}/releases?limit=${limit}`);
};
// 使用例
const releases = await listReleases('my-app');
releases.forEach(release => {
console.log(`v${release.version} - ${release.description} - ${release.created_at}`);
});
リリースロールバック
const rollback = async (appName, releaseId) => {
const response = await herokuRequest(`/apps/${appName}/releases`, {
method: 'POST',
body: JSON.stringify({ rollback: releaseId })
});
return response;
};
// 例: バージョン42へロールバック
const rollbackRelease = await rollback('my-app', 42);
console.log(`v${rollbackRelease.version} にロールバックしました`);
パイプライン管理
パイプライン作成
const createPipeline = async (pipelineName) => {
const response = await herokuRequest('/pipelines', {
method: 'POST',
body: JSON.stringify({ name: pipelineName })
});
return response;
};
// 使用例
const pipeline = await createPipeline('my-app-pipeline');
console.log(`パイプライン作成: ${pipeline.id}`);
パイプラインにアプリを追加
const addAppToPipeline = async (pipelineId, appName, stage) => {
return await herokuRequest('/pipeline-couplings', {
method: 'POST',
body: JSON.stringify({
pipeline: pipelineId,
app: appName,
stage // 'development', 'staging', 'production'
})
});
};
// ステージ追加例
await addAppToPipeline(pipelineId, 'my-app-dev', 'development');
await addAppToPipeline(pipelineId, 'my-app-staging', 'staging');
await addAppToPipeline(pipelineId, 'my-app-prod', 'production');
スラグの昇格
const promoteSlug = async (slugId, toApp) => {
await herokuRequest('/promotions', {
method: 'POST',
body: JSON.stringify({
from: toApp,
to: toApp,
slug: slugId
})
});
console.log(`スラグ ${slugId} を ${toApp} に昇格`);
};
アドオン管理
アドオンのプロビジョニング
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;
};
// PostgreSQL プロビジョニング例
const db = await provisionAddon('my-app', 'heroku-postgresql:mini', {});
console.log(`DBプロビジョニング: ${db.addon.name}`);
console.log(`DATABASE_URL: ${db.addon.config_vars.DATABASE_URL}`);
人気アドオン
| アドオン | プラン | 開始価格 | ユースケース |
|---|---|---|---|
| heroku-postgresql | mini | 月額5ドル | 本番DB |
| heroku-redis | mini | 月額5ドル | キャッシュ/セッション |
| papertrail | choklad | 月額7ドル | ログ集約 |
| sentry | developer | 無料 | エラートラッキング |
| mailgun | sandbox | 無料 | メール配信 |
| newrelic | lite | 無料 | アプリ監視 |
アドオン一覧取得
const listAddons = async (appName) => {
return await herokuRequest(`/apps/${appName}/addons`);
};
// 使用例
const addons = await listAddons('my-app');
addons.forEach(addon => {
console.log(`${addon.plan.name} - $${addon.pricing.plan.price} - ${addon.state}`);
});
アドオン削除
const removeAddon = async (appName, addonId) => {
await herokuRequest(`/apps/${appName}/addons/${addonId}`, { method: 'DELETE' });
console.log(`アドオン ${addonId} 削除 (${appName})`);
};
ドメインとSSL管理
カスタムドメイン追加
const addDomain = async (appName, domainName) => {
const response = await herokuRequest(`/apps/${appName}/domains`, {
method: 'POST',
body: JSON.stringify({ hostname: domainName })
});
return response;
};
// 使用例
const domain = await addDomain('my-app', 'api.example.com');
console.log(`CNAMEターゲット: ${domain.cname}`);
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;
};
ACMによる自動SSL
const enableACM = async (appName, domainName) => {
const response = await herokuRequest(`/apps/${appName}/domains/${domainName}/sni_endpoint`, {
method: 'POST',
body: JSON.stringify({ kind: 'acm' })
});
return response;
};
レート制限とクォータ
レート制限の概要
- 標準制限: 1時間あたり10,000リクエスト/アカウント
- ウィンドウ: 60分ローリング
- リセット: 時間経過で自動
超過時は HTTP 429 (Too Many Requests) が返ります。
レート制限処理(指数バックオフ)
const makeRateLimitedRequest = async (endpoint, options = {}, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await herokuRequest(endpoint, options);
const remaining = response.headers.get('RateLimit-Remaining');
const resetTime = response.headers.get('RateLimit-Reset');
if (remaining < 100) {
console.warn(`残りクォータ少: ${remaining}, リセット: ${resetTime}`);
}
return response;
} catch (error) {
if (error.message.includes('429') && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000;
console.log(`レート制限。${delay}ms後にリトライ`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
};
レート制限ヘッダー
| ヘッダー | 説明 |
|---|---|
RateLimit-Limit |
1時間あたりの最大リクエスト数 |
RateLimit-Remaining |
ウィンドウ内の残りリクエスト数 |
RateLimit-Reset |
リセットされるUnixタイムスタンプ |
よくある問題のトラブルシューティング
問題:認証が 401 エラー
- API キー・トークンが正しいか
heroku authorizationsで確認 - トークン有効期限切れをチェック
- 環境変数に余計な空白がないか
- 必要ならトークン再生成
問題:アプリ名が既に利用中
- グローバル一意な名前にする(チーム名やランダム接尾辞付与)
- UUIDやタイムスタンプの利用
- チーム名-アプリ名-環境 で名前空間化
const generateUniqueAppName = (baseName) => {
const timestamp = Date.now().toString(36);
const random = Math.random().toString(36).substring(2, 6);
return `${baseName}-${timestamp}-${random}`;
};
問題:ダイノ構成が失敗
- Procfile に該当プロセスがあるか
- ダイノクォータ残があるか
- アプリが停止状態でないか
-
heroku ps --app=my-appで稼働状況確認
問題:ビルドがタイムアウト
- 最適なビルドパックを選択
- 依存キャッシュ活用
- 大きなビルドは小分け
- 事前ビルド済みスラグで高速化
問題:レート制限超過
- リクエストキューイングを実装
- 指数バックオフでリトライ
- バッチ処理
- レート制限ヘッダーの積極監視
// シンプルなレートリミッター
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;
}
}
本番デプロイチェックリスト
本番前に必ず確認:
- [ ] CI/CDは有効期間の長いAPIトークンを利用
- [ ] シークレット管理サービス(Vault, AWS Secrets Manager等)で安全に保管
- [ ] レート制限・リクエストキューイング実装
- [ ] 例外処理・ロギング追加
- [ ] ダイノ使用時間監視
- [ ] 外部ロギング用ログドレイン設定
- [ ] パイプラインプロモーション設定
- [ ] 自動SSL証明書管理有効化
- [ ] DBバックアップ戦略
監視とアラート
const metrics = {
apiCalls: { total: 0, successful: 0, failed: 0, rateLimited: 0 },
dynoHours: { used: 0, quota: 1000 },
deployments: { successful: 0, failed: 0, avg_duration: 0 }
};
const failureRate = metrics.apiCalls.failed / metrics.apiCalls.total;
if (failureRate > 0.05) sendAlert('Heroku API failure rate above 5%');
if (metrics.dynoHours.used > metrics.dynoHours.quota * 0.8) sendAlert('Dyno hour usage above 80%');
実際のユースケース
CI/CD自動化パイプライン
- 課題:手動デプロイでエラー・遅延多発
- 解決:GitHub Actions + Heroku API
- 結果:ダウンタイムゼロ、リリース90%高速化
実装フロー:
- GitHubプッシュでワークフロートリガー
- CIでテスト
- Heroku APIでビルド作成
- ステージング→本番へ昇格
- 成否でチーム通知
マルチ環境管理
- 課題:手動設定同期の非効率
- 解決:APIによる中央設定管理
- 結果:一貫運用・週8時間削減
主な統合:
- 環境変数同期
- アドオン自動プロビジョニング
- バルク操作でクライアントオンボーディング
トラフィック連動自動スケール
- 課題:セール時の手動スケール対応困難
- 解決:Heroku APIとメトリクスAPIで自動スケール
- 結果:トラフィック10倍でもダウンタイムゼロ
実装例:
- p95レイテンシ監視でスケールアップ/ダウン
- 高負荷持続時はアラート
結論
Heroku API でプラットフォーム全体を効率的に自動化できます。
- ベアラートークン認証は安全管理・定期ローテ
- レート制限(1時間1万件)は事前監視
- パイプラインAPIで堅牢なCI/CD
- エラー処理で信頼性向上
- Apidogは統合APIテストとチーム連携を効率化
FAQ セクション
Heroku API は何に使う?
アプリ/ダイノ/アドオン/インフラのプログラム管理。CI/CD自動化や多アプリ管理ツール、自動スケール、監視ダッシュボードに活用。
Heroku APIキー取得方法は?
Heroku CLIインストール→heroku login→heroku authorizations:createでトークン発行し、必ず環境変数で安全保管。
Heroku API は無料?
API自体は無料。ダイノ/アドオン等リソース利用は通常料金。レート制限は1時間1万リクエスト/アカウント。
認証方式は?
ベアラートークン認証。全リクエストでAuthorization: Bearer {api_key}が必須。トークンの有効期限は1時間/1年の2種。
レート制限はどう処理?
RateLimit-Remainingを監視し、リクエストキュー・指数バックオフで制御。1分150リクエスト以下推奨。
Gitなしデプロイは可能?
はい。Builds APIでソースブロブURLから直接デプロイ可能。S3/GCS等にコードを置きURL指定でOK。
デプロイ自動化の方法は?
Pipeline APIでCI/CDを設計。ビルド作成→スラグ昇格→GitHubや独自CIと連携。
リリースとビルドの違いは?
ビルド=ソース→スラグ作成。リリース=スラグ+設定変数でアプリバージョン生成。
失敗したデプロイのロールバック方法は?
Releases APIで履歴取得→/releasesにrollback:<release_id>指定でPOST。自動で新リリース生成。
複数Herokuアカウント管理は?
アカウントごとにAPIトークンを切り替え、HEROKU_API_KEY環境変数で管理可能。

Top comments (0)