{"slug":"vercel-api-deployments","title":"Vercel API: Deployments, Environment Variables, and Domains","tags":["vercel","deployment","api","cli","devops"],"agent_summary":"Vercel REST API and CLI reference for managing deployments, environment variables, domains, and project lifecycle programmatically.","trigger_phrases":["Vercel API","Vercel deployment","Vercel CLI","Vercel environment variables","vercel.json","Vercel domains API"],"runnable":false,"markdown":"\n## Overview\n\nVercel exposes a REST API and CLI for full programmatic control of deployments, environment variables, domains, and edge config. Use the CLI for interactive ops; use the REST API for automation.\n\n## Authentication\n\n```bash\n# CLI login\nvercel login\n\n# REST API — Bearer token (generate at vercel.com/account/tokens)\nAuthorization: Bearer <token>\n```\n\n## Core CLI Commands\n\n```bash\n# Deploy current directory\nvercel                     # Preview deployment\nvercel --prod              # Production deployment\n\n# Project management\nvercel ls                  # List projects\nvercel inspect <url>       # Deployment details\nvercel logs <url>          # Stream logs\n\n# Environment variables\nvercel env add NAME production     # Add env var\nvercel env ls                      # List all env vars\nvercel env rm NAME production      # Remove env var\nvercel env pull .env.local         # Pull env vars to local file\n\n# Domains\nvercel domains add example.com     # Add domain\nvercel domains ls                  # List domains\n\n# Rollback\nvercel rollback [deployment-url]   # Rollback to previous\n```\n\n## Environment Variables API\n\n```typescript\n// List env vars for a project\nconst vars = await fetch(\n  \"https://api.vercel.com/v9/projects/{projectId}/env\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n\n// Create env var\nawait fetch(\"https://api.vercel.com/v10/projects/{projectId}/env\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${token}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    key: \"MY_API_KEY\",\n    value: \"secret-value\",\n    type: \"encrypted\",           // \"plain\" | \"encrypted\" | \"secret\"\n    target: [\"production\", \"preview\", \"development\"],\n  }),\n});\n```\n\n## Deployments API\n\n```typescript\n// List deployments\nconst deploys = await fetch(\n  \"https://api.vercel.com/v6/deployments?projectId={id}&limit=20\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n\n// Trigger a deployment (from Git)\nawait fetch(\"https://api.vercel.com/v13/deployments\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${token}`, \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({\n    name: \"my-project\",\n    gitSource: {\n      type: \"github\",\n      repoId: \"123456\",\n      ref: \"main\",\n    },\n    target: \"production\",\n  }),\n});\n\n// Get deployment status\nconst deploy = await fetch(\n  \"https://api.vercel.com/v13/deployments/{deploymentId}\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n// deploy.readyState: \"QUEUED\" | \"BUILDING\" | \"READY\" | \"ERROR\"\n```\n\n## vercel.json Configuration\n\n```json\n{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \".next\",\n  \"installCommand\": \"npm ci\",\n  \"framework\": \"nextjs\",\n  \"regions\": [\"iad1\"],\n  \"headers\": [\n    {\n      \"source\": \"/api/(.*)\",\n      \"headers\": [{ \"key\": \"Cache-Control\", \"value\": \"no-store\" }]\n    }\n  ],\n  \"rewrites\": [\n    { \"source\": \"/old-path\", \"destination\": \"/new-path\" }\n  ],\n  \"redirects\": [\n    { \"source\": \"/old\", \"destination\": \"/new\", \"permanent\": true }\n  ],\n  \"crons\": [\n    { \"path\": \"/api/cron/daily\", \"schedule\": \"0 8 * * *\" }\n  ]\n}\n```\n\n## Domains API\n\n```typescript\n// Add domain to project\nawait fetch(\"https://api.vercel.com/v10/projects/{projectId}/domains\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${token}`, \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ name: \"example.com\" }),\n});\n\n// Verify domain\nconst check = await fetch(\n  \"https://api.vercel.com/v6/domains/{domain}/config\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n// check.misconfigured: bool — true means DNS not yet propagated\n```\n\n## GitHub Actions Integration\n\n```yaml\nname: Deploy to Vercel\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Deploy\n        run: |\n          npm install -g vercel\n          vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}\n          vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}\n          vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}\n        env:\n          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}\n          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}\n```\n\n## Edge Config\n\nLow-latency key-value store read at the edge before your function runs:\n\n```typescript\nimport { get } from \"@vercel/edge-config\";\n\nexport async function middleware(request: NextRequest) {\n  const maintenanceMode = await get<boolean>(\"maintenanceMode\");\n  if (maintenanceMode) {\n    return NextResponse.rewrite(new URL(\"/maintenance\", request.url));\n  }\n}\n```\n\nUpdate via REST API — changes propagate in milliseconds globally.\n","html":"<h2>Overview</h2>\n<p>Vercel exposes a REST API and CLI for full programmatic control of deployments, environment variables, domains, and edge config. Use the CLI for interactive ops; use the REST API for automation.</p>\n<h2>Authentication</h2>\n<pre><code class=\"language-bash\"># CLI login\nvercel login\n\n# REST API — Bearer token (generate at vercel.com/account/tokens)\nAuthorization: Bearer &#x3C;token>\n</code></pre>\n<h2>Core CLI Commands</h2>\n<pre><code class=\"language-bash\"># Deploy current directory\nvercel                     # Preview deployment\nvercel --prod              # Production deployment\n\n# Project management\nvercel ls                  # List projects\nvercel inspect &#x3C;url>       # Deployment details\nvercel logs &#x3C;url>          # Stream logs\n\n# Environment variables\nvercel env add NAME production     # Add env var\nvercel env ls                      # List all env vars\nvercel env rm NAME production      # Remove env var\nvercel env pull .env.local         # Pull env vars to local file\n\n# Domains\nvercel domains add example.com     # Add domain\nvercel domains ls                  # List domains\n\n# Rollback\nvercel rollback [deployment-url]   # Rollback to previous\n</code></pre>\n<h2>Environment Variables API</h2>\n<pre><code class=\"language-typescript\">// List env vars for a project\nconst vars = await fetch(\n  \"https://api.vercel.com/v9/projects/{projectId}/env\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n\n// Create env var\nawait fetch(\"https://api.vercel.com/v10/projects/{projectId}/env\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${token}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    key: \"MY_API_KEY\",\n    value: \"secret-value\",\n    type: \"encrypted\",           // \"plain\" | \"encrypted\" | \"secret\"\n    target: [\"production\", \"preview\", \"development\"],\n  }),\n});\n</code></pre>\n<h2>Deployments API</h2>\n<pre><code class=\"language-typescript\">// List deployments\nconst deploys = await fetch(\n  \"https://api.vercel.com/v6/deployments?projectId={id}&#x26;limit=20\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n\n// Trigger a deployment (from Git)\nawait fetch(\"https://api.vercel.com/v13/deployments\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${token}`, \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({\n    name: \"my-project\",\n    gitSource: {\n      type: \"github\",\n      repoId: \"123456\",\n      ref: \"main\",\n    },\n    target: \"production\",\n  }),\n});\n\n// Get deployment status\nconst deploy = await fetch(\n  \"https://api.vercel.com/v13/deployments/{deploymentId}\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n// deploy.readyState: \"QUEUED\" | \"BUILDING\" | \"READY\" | \"ERROR\"\n</code></pre>\n<h2>vercel.json Configuration</h2>\n<pre><code class=\"language-json\">{\n  \"buildCommand\": \"npm run build\",\n  \"outputDirectory\": \".next\",\n  \"installCommand\": \"npm ci\",\n  \"framework\": \"nextjs\",\n  \"regions\": [\"iad1\"],\n  \"headers\": [\n    {\n      \"source\": \"/api/(.*)\",\n      \"headers\": [{ \"key\": \"Cache-Control\", \"value\": \"no-store\" }]\n    }\n  ],\n  \"rewrites\": [\n    { \"source\": \"/old-path\", \"destination\": \"/new-path\" }\n  ],\n  \"redirects\": [\n    { \"source\": \"/old\", \"destination\": \"/new\", \"permanent\": true }\n  ],\n  \"crons\": [\n    { \"path\": \"/api/cron/daily\", \"schedule\": \"0 8 * * *\" }\n  ]\n}\n</code></pre>\n<h2>Domains API</h2>\n<pre><code class=\"language-typescript\">// Add domain to project\nawait fetch(\"https://api.vercel.com/v10/projects/{projectId}/domains\", {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${token}`, \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ name: \"example.com\" }),\n});\n\n// Verify domain\nconst check = await fetch(\n  \"https://api.vercel.com/v6/domains/{domain}/config\",\n  { headers: { Authorization: `Bearer ${token}` } }\n).then(r => r.json());\n// check.misconfigured: bool — true means DNS not yet propagated\n</code></pre>\n<h2>GitHub Actions Integration</h2>\n<pre><code class=\"language-yaml\">name: Deploy to Vercel\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Deploy\n        run: |\n          npm install -g vercel\n          vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}\n          vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}\n          vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}\n        env:\n          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}\n          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}\n</code></pre>\n<h2>Edge Config</h2>\n<p>Low-latency key-value store read at the edge before your function runs:</p>\n<pre><code class=\"language-typescript\">import { get } from \"@vercel/edge-config\";\n\nexport async function middleware(request: NextRequest) {\n  const maintenanceMode = await get&#x3C;boolean>(\"maintenanceMode\");\n  if (maintenanceMode) {\n    return NextResponse.rewrite(new URL(\"/maintenance\", request.url));\n  }\n}\n</code></pre>\n<p>Update via REST API — changes propagate in milliseconds globally.</p>\n"}