DEV Community

Alex Spinov
Alex Spinov

Posted on

Vercel Has a Free API: Here's How to Use It for Deployment Automation

Vercel's REST API lets you manage deployments, domains, environment variables, and edge functions programmatically. Combined with the free Hobby plan, you get a powerful deployment platform with full API control.

Why Use the Vercel API?

  • Deploy from any CI/CD pipeline or script
  • Manage environment variables across projects
  • Monitor deployment status and logs
  • Automate domain configuration and SSL

Getting Started

Get your token from vercel.com > Settings > Tokens:

export VERCEL_TOKEN="your-token"

# List projects
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
  "https://api.vercel.com/v9/projects" | jq '.projects[] | {name: .name, framework: .framework, updatedAt: .updatedAt}'

# List deployments
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
  "https://api.vercel.com/v6/deployments?limit=5" | jq '.deployments[] | {url: .url, state: .state, created: .created}'
Enter fullscreen mode Exit fullscreen mode

Python Client

import requests
import time

class VercelClient:
    def __init__(self, token):
        self.url = "https://api.vercel.com"
        self.headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}

    def list_projects(self):
        resp = requests.get(f"{self.url}/v9/projects", headers=self.headers)
        return resp.json().get('projects', [])

    def get_project(self, name):
        resp = requests.get(f"{self.url}/v9/projects/{name}", headers=self.headers)
        return resp.json()

    def list_deployments(self, project_id=None, limit=10):
        params = {'limit': limit}
        if project_id:
            params['projectId'] = project_id
        resp = requests.get(f"{self.url}/v6/deployments", params=params, headers=self.headers)
        return resp.json().get('deployments', [])

    def create_deployment(self, name, files, project_settings=None):
        payload = {'name': name, 'files': files}
        if project_settings:
            payload['projectSettings'] = project_settings
        resp = requests.post(f"{self.url}/v13/deployments", json=payload, headers=self.headers)
        return resp.json()

    def get_deployment(self, deployment_id):
        resp = requests.get(f"{self.url}/v13/deployments/{deployment_id}", headers=self.headers)
        return resp.json()

    def set_env_var(self, project_id, key, value, target=None):
        payload = {'key': key, 'value': value, 'type': 'plain'}
        if target:
            payload['target'] = target
        resp = requests.post(f"{self.url}/v10/projects/{project_id}/env", json=payload, headers=self.headers)
        return resp.json()

    def add_domain(self, project_id, domain):
        resp = requests.post(f"{self.url}/v10/projects/{project_id}/domains", json={'name': domain}, headers=self.headers)
        return resp.json()

# Usage
vercel = VercelClient('your-token')

for project in vercel.list_projects():
    print(f"{project['name']:30s} Framework: {project.get('framework', 'N/A')}")
Enter fullscreen mode Exit fullscreen mode

Deploy from Script

import base64
import os

def deploy_static_site(vercel, project_name, directory):
    files = []
    for root, dirs, filenames in os.walk(directory):
        for filename in filenames:
            filepath = os.path.join(root, filename)
            relpath = os.path.relpath(filepath, directory)

            with open(filepath, 'rb') as f:
                content = f.read()

            files.append({
                'file': relpath,
                'data': base64.b64encode(content).decode('utf-8'),
                'encoding': 'base64'
            })

    deployment = vercel.create_deployment(project_name, files)
    print(f"Deploying to: https://{deployment.get('url')}")

    # Wait for ready
    deploy_id = deployment['id']
    for _ in range(60):
        status = vercel.get_deployment(deploy_id)
        state = status.get('readyState', status.get('state'))
        if state == 'READY':
            print(f"Live at: https://{status['url']}")
            return status
        elif state in ('ERROR', 'CANCELED'):
            print(f"Deployment failed: {state}")
            return None
        time.sleep(2)

deploy_static_site(vercel, 'my-site', './dist')
Enter fullscreen mode Exit fullscreen mode

Environment Variable Management

def sync_env_vars(vercel, project_id, env_file='.env.production'):
    with open(env_file) as f:
        for line in f:
            line = line.strip()
            if line and not line.startswith('#') and '=' in line:
                key, value = line.split('=', 1)
                vercel.set_env_var(project_id, key.strip(), value.strip(), target=['production'])
                print(f"Set {key.strip()} for production")

sync_env_vars(vercel, 'prj_xxxx', '.env.production')
Enter fullscreen mode Exit fullscreen mode

Deployment Dashboard

def deployment_report(vercel):
    for project in vercel.list_projects():
        deployments = vercel.list_deployments(project_id=project['id'], limit=3)

        print(f"\n{project['name']}:")
        for dep in deployments:
            state = dep.get('state', dep.get('readyState', 'unknown'))
            created = time.strftime('%Y-%m-%d %H:%M', time.gmtime(dep['created']/1000))
            url = dep.get('url', 'N/A')
            print(f"  {created} | {state:10s} | {url}")

deployment_report(vercel)
Enter fullscreen mode Exit fullscreen mode

Real-World Use Case

A marketing team needed to deploy 20+ landing pages for different campaigns. They built a deployment script using the Vercel API — each landing page is generated from a template, deployed with unique environment variables (tracking codes, copy), and gets a custom domain assigned. What took 2 hours of manual work per landing page now takes 30 seconds.

What You Can Build

  • Auto-deploy pipeline from any CI/CD system
  • Preview environment manager for feature branches
  • Multi-site deployer for landing pages
  • Environment sync tool across dev/staging/production
  • Deployment dashboard with rollback capabilities

Need custom deployment automation? I build DevOps tools and CI/CD pipelines.

Email me: spinov001@gmail.com
Check out my developer tools: https://apify.com/spinov001

Top comments (0)