# Vercel Hosting Deploy apps to Vercel by uploading files. Multipart file uploads are the preferred path; JSON file lists are supported for programmatic callers. ## Prerequisites Provision this resource before use. Edge requests without provisioning will error. ### Provision curl -s -X POST https://cohesivity.ai/api/resources/vercel-hosting \ -H "Authorization: Bearer " ### Delete curl -s -X DELETE https://cohesivity.ai/api/resources/vercel-hosting \ -H "Authorization: Bearer " **Important:** Provision this resource now, before building or running the application. Provisioning is the agent's job, not the application's. ## Common Mistakes - **Setting `NEXT_PUBLIC_*` env vars after the first deploy.** In Next.js, these are baked at build time. Set all env vars via `POST /api/vercel/env` **before** the first deploy. If you add or change them later, redeploy. - **Not setting maxDuration for slow routes.** Vercel default serverless timeout is 10s. For slow routes (AI, image processing), add `export const maxDuration = 60;` at the top of the route file. - **Using create-next-app or other interactive scaffolders.** Write your files directly — interactive scaffolders fail in agent environments. Write package.json manually. ## What Happens on Provision - Creates a Vercel project: `coh-` - Returns `deployment_url` (e.g. `https://.cohesivity.xyz`) - If an ephemeral tenant is paused later, Cohesivity can promote a tiny redirect deployment that sends all requests to the tenant `claim_url` ## How to Deploy POST `multipart/form-data` to `/api/vercel/deploy` — each project file is a `files` part. The endpoint translates the multipart body to Vercel's JSON-with-base64 shape internally; binary files (images, fonts, wasm) are auto-detected and base64-encoded for you. Append `?wait=ready` to the URL and the request blocks until the deployment reaches `state: "READY"` (typical 3-10s for static, 25-60s for Next.js builds). The response then contains the final state, `canonical_url`, and (on ERROR) a curated `last_error` field. Without `?wait=ready` the response returns immediately with `state: "INITIALIZING"` — see the bridge directive below. Use the response's **`canonical_url`** (alias of `project_url`) as the URL you share with the user. The `url` field is per-deployment and changes on every deploy; `vercel_url` is an alias for tooling. ### curl ``` curl -F "files=@index.html" \ -F "files=@app.js" \ -F "files=@assets/logo.png" \ -H "Authorization: Bearer " \ https://cohesivity.ai/api/vercel/deploy?wait=ready ``` ### Python ``` import requests files = [("files", open(p, "rb")) for p in ["index.html", "app.js", "assets/logo.png"]] r = requests.post( f"{BASE_URL}/api/vercel/deploy?wait=ready", files=files, headers={"Authorization": f"Bearer {KEY}"}, ) print(r.json()["canonical_url"], r.json()["state"]) ``` ### Node (server-side only — never run from a browser; the management key is a secret) ``` import fs from "node:fs"; const fd = new FormData(); fd.append("files", new Blob([fs.readFileSync("index.html")]), "index.html"); fd.append("files", new Blob([fs.readFileSync("app.js")]), "app.js"); const r = await fetch(`${BASE_URL}/api/vercel/deploy?wait=ready`, { method: "POST", body: fd, headers: { "Authorization": `Bearer ${KEY}` } }); ``` ### JSON shape (legacy / programmatic) Both shapes are supported indefinitely. Use JSON when you already have file contents in memory and don't want to spawn a multipart body: ``` POST https://cohesivity.ai/api/vercel/deploy?wait=ready Authorization: Bearer Content-Type: application/json { "files": [ { "file": "index.html", "data": "..." }, { "file": "app.js", "data": "// ..." }, { "file": "logo.png", "data": "", "encoding": "base64" } ], "projectSettings": { "framework": "nextjs" } } ``` `projectSettings` is optional. If omitted, Vercel auto-detects the framework. Set `"framework": "nextjs"` for Next.js apps. Max payload size: 10 MB. A typical Next.js app with 30-50 source files is well within this limit. ### Response shape ``` { "success": true, "deployment_id": "dpl_...", "url": "https://.vercel.app", // changes every deploy — do not share "state": "READY", // canonical (use this) "status": "READY", // legacy alias — removed in a future runtime "canonical_url": "https://.cohesivity.xyz", // user-facing URL — share this "project_url": "https://.cohesivity.xyz", // alias of canonical_url "vercel_url": "https://.vercel.app", // for tooling/scripts "file_count": 14, "wait_timed_out": false, // only on ?wait=ready "last_error": { "ts": "...", "level": "error", "source": "build", "text": "..." } // only on ERROR } ``` ### Bridge: poll until READY (without `?wait=ready`) After `POST /api/vercel/deploy` returns `state: "INITIALIZING"`, poll `GET /api/vercel/deployments/:id` until `deployment.state === "READY"`. Static deploys typically reach READY in 3-10 seconds; Next.js builds in 25-60 seconds. ERROR / CANCELED responses include a curated `last_error` field. Or use `?wait=ready` on the POST to skip the polling loop entirely. ### Static / SPA deploys For plain HTML/CSS/JS sites, omit `projectSettings` entirely; Vercel auto-detects. For SPA fallback (every path serves `index.html`), include a `vercel.json` in your files with: ``` { "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] } ``` After deploy, the site is live at `canonical_url` (= `.cohesivity.xyz`). If the tenant remains ephemeral and later gets paused, the hosted domain redirects to its Cohesivity claim page until the tenant is claimed. ## Redeploy To update, call `POST /api/vercel/deploy` again with the new files. The production URL stays the same. ## Custom Subdomain (claimed tenants) Once your tenant is claimed, you can attach a vanity subdomain like `acme.cohesivity.xyz` alongside the auto-generated `.cohesivity.xyz`. Both hosts serve the same deployment — your existing URL keeps working. Ephemeral tenants get a 403 with the claim URL until they claim. - **Check availability** (no auth): `GET https://cohesivity.ai/api/vercel/custom-subdomain/check?name=acme` → `{ "name": "acme", "available": true, "reason": "ok" }`. Possible `reason` values: `ok`, `taken`, `invalid_format`, `name_reserved`. - **Get current** (auth): `GET https://cohesivity.ai/api/vercel/custom-subdomain` with `Authorization: Bearer ` → `{ "name": "acme" | null, "host": "acme.cohesivity.xyz" | null, "tenant_host": ".cohesivity.xyz" }`. - **Set or swap** (auth): `POST https://cohesivity.ai/api/vercel/custom-subdomain` with `{ "name": "acme" }`. If a vanity is already set, the old name is released and the new one is attached in one call. Returns 403 `tenant_must_be_claimed` for ephemeral tenants, 422 `invalid_name_format` or `name_reserved` for bad input, 409 `name_unavailable` if someone else has it. - **Release** (auth): `DELETE https://cohesivity.ai/api/vercel/custom-subdomain`. The name becomes immediately available for any other tenant to claim. **Name rules:** 3-32 characters, lowercase a-z, 0-9, hyphens; cannot start or end with a hyphen. Common names (`api`, `admin`, `mail`, `www`, hosting/provider brand names, runtime version namespace `v1-…`) are reserved. Ownership is for the lifetime of the tenant — names are released only on swap, explicit DELETE, or tenant/account deletion. No transfers. **Account-wide cap:** Free tier holds **5** vanities, Plus holds **20**, Pro holds **100** (matches the per-account project ceiling). The cap is checked per Cohesivity user across all their tenants. Swaps and idempotent re-sets do not count — only net-new claims. Hitting the cap returns 403 `vanity_limit_reached` with your current count and limit; release a vanity on a different tenant or upgrade your plan to claim more. ## Deployment Management All endpoints require `Authorization: Bearer ` header. - **List deployments:** `GET https://cohesivity.ai/api/vercel/deployments` - **Deployment details:** `GET https://cohesivity.ai/api/vercel/deployments/:id` - **Cancel deployment:** `POST https://cohesivity.ai/api/vercel/deployments/:id/cancel` - **Build logs:** `GET https://cohesivity.ai/api/vercel/deployments/:id/logs` - **Runtime logs:** `GET https://cohesivity.ai/api/vercel/runtime-logs?since=&cursor=&limit=` — per-request runtime invocation logs for the tenant's deployed app. Reads from Axiom (populated by the Vercel→Axiom integration's Log Drain). Each item carries `ts, level, message, method, path, status, host, user_agent, duration_ms, memory_mb, deployment_id, region, route, environment, request_id`. `since` for delta polls; `cursor` to continue an in-progress page (cursor wins if both are passed). `limit` clamped to plan cap (Free 50, Plus 200, Pro 500). 2-3 minute propagation lag from Vercel through Axiom. ## Environment Variables All endpoints require `Authorization: Bearer ` header. - **List env vars:** `GET https://cohesivity.ai/api/vercel/env` - **Create env var:** `POST https://cohesivity.ai/api/vercel/env` with `{ "key": "MY_SECRET", "value": "abc123", "target": ["production"] }` - **Delete env var:** `DELETE https://cohesivity.ai/api/vercel/env/:key` ## Security Never expose keys in frontend code. Store secrets as Vercel env vars via the endpoint above. ## Launch Rate Limits Ephemeral tenants pause as a whole if any authoritative hard cap below is exceeded. Claimed tiers use account-scoped buckets shared across every project owned by the Cohesivity user; OpenAI, Deepgram, and Exa are fluid-only after tier, rate, and concurrency checks; Deepgram has no fixed monthly usage bucket for claimed tiers. **Ephemeral** - projects: 1 max total - deploys: 20 per ephemeral tenant lifetime before claim or expiry - edge requests: 5000 per ephemeral tenant lifetime before claim or expiry - function invocations: 1000 per ephemeral tenant lifetime before claim or expiry - edge function invocations: 5000 per ephemeral tenant lifetime before claim or expiry - fast data transfer: 512 MB per ephemeral tenant lifetime before claim or expiry - deploys: 3 per minute **Claimed Free** - projects: 10 max total - deploys: 3 per minute - edge requests: 100000 per month - function invocations: 25000 per month - edge function invocations: 100000 per month - fast data transfer: 20 GB per month - deploys: 60 per month **Claimed Plus** - projects: 30 max total - deploys: 10 per minute - edge requests: 1000000 per month - function invocations: 250000 per month - edge function invocations: 1000000 per month - fast data transfer: 200 GB per month - deploys: 200 per month **Claimed Pro** - projects: 100 max total - deploys: 10 per minute - edge requests: 5000000 per month - function invocations: 1250000 per month - edge function invocations: 5000000 per month - fast data transfer: 1024 GB per month - deploys: 600 per month ### Notes - Hosted-runtime metrics are soft and poll-based, not inline. Cohesivity currently records Vercel edge requests, function invocations, edge function invocations, and fast data transfer through the observability backstop.