Integrations
Connect a project to Vercel, Supabase or Cloudflare once, and ApiVault keeps what it manages there in step with your keys — on every change, with a retry sweep behind it, and with a preview whenever you sync by hand.
How it works
Service tokens let a pipeline pull secrets when it runs. An integration pushes them instead, so the platform holds the values itself — which is what Vercel builds, Supabase Edge Functions and Cloudflare Workers expect.
A connection belongs to a project, not to the person who created it, so syncing keeps working when that person leaves the team. Only project owners and admins can connect, link or disconnect; editors and viewers see the status.
ApiVault syncs a linked Vercel project, Supabase project or Cloudflare Worker:
- right after a key is added, edited, deleted or imported, when auto-sync is on;
- on a scheduled sweep that retries anything that failed, with growing gaps between attempts;
- whenever an admin clicks Sync now.
Connecting Vercel
Open your project, go to Integrations and click Connect Vercel. Vercel asks you to choose your personal account or a team, and whether ApiVault may see all projects or only the ones you select. When you approve, Vercel sends you back to the project's Vercel page.
To sync to projects in another Vercel account or team, click Connect Another Team at the bottom of the Vercel page. Each team gets its own connection.
Linking a Vercel project
On the Integrations page, click Manage on the Vercel card to open your Vercel connections, then click Add Project on the connection. First search for and choose the Vercel project, then tick which Vercel targets each environment goes to and set the options. One ApiVault project can feed several Vercel projects, each with its own mapping and options.
Environment mapping
Production, Staging and Development are always listed, even before they hold keys, along with any other environment your keys use. Each can be sent to any of Vercel's three targets: production, preview and development. ApiVault suggests a mapping from the environment's name:
productionorprod→ productionpreview,stagingorstage→ previewdevelopment,devorlocal→ development
Anything else starts unmapped, and its keys are not sent. A Vercel target can come from only one environment — otherwise the same variable would have two values — and at least one environment must be mapped.
What ApiVault changes
ApiVault only ever creates, updates and deletes the variables it created. Vercel tags each one with the integration that made it, and ApiVault checks that tag before touching anything. Variables you added in Vercel yourself are never modified or deleted. If two ApiVault projects sync to the same Vercel project through one team, each only changes the variables it created, and a variable the other project created with the same name is reported as a conflict.
If you already have a variable in Vercel with the same name on an overlapping target, ApiVault skips that key for the link and reports a conflict. Delete or rename your copy in Vercel, then click Sync now to let ApiVault take it over.
Deleting a key in ApiVault deletes the variable ApiVault created for it. Editing a variable ApiVault owns directly in Vercel is overwritten on the next sync.
Variable names
A key's name is used as the variable name exactly, as with apivault run. Names must start with a letter or underscore, contain only letters, digits and underscores, and must not start with VERCEL_, which Vercel reserves. Keys with other names are skipped and listed in the sync's issues — rename the key in ApiVault to include it.
Sensitive and encrypted variables
Variables sent only to production or preview are created as Sensitive, so nobody can read them back in Vercel's dashboard. Vercel does not allow sensitive variables on the development target, so a variable that includes development is created as Encrypted.
Projects with a custom vault key
In custom encryption mode the server cannot decrypt your keys on its own, so it cannot sync in the background. Auto-sync is off and cannot be turned on. Click Sync now and enter the vault key: the sync runs within that request, and the key is not stored, logged or kept for a later retry.
Switching a project to custom mode turns auto-sync off on all of its links.
Redeploying on change
Vercel reads environment variables at build time, so a changed value reaches a live deployment only after it is rebuilt. Turn on Redeploy production on change for a link and, whenever a sync changes a production variable, ApiVault redeploys the latest ready production deployment. It is off by default.
A redeploy that fails does not undo the sync. It is reported as an issue on the link, and the variables stay updated.
Sync now and previews
Sync now first compares ApiVault with Vercel and shows what would change, grouped as Create, Update, Delete, Conflicts and Skipped. Only names and targets are shown, never values. Nothing is written until you click Apply.
The preview reflects Vercel at that moment. If Vercel changes before you apply, ApiVault does not apply the old plan — it shows the new one and asks you to review again.
Sync now works regardless of auto-sync, retry delays or an Action needed status, and a successful run clears the failure count.
Unlinking and disconnecting
Both actions are in the ⋯ menu: a linked project's menu holds Unlink, and the connection's menu holds Disconnect.
Unlink deletes every variable ApiVault created in that Vercel project, then removes the link. If Vercel cannot be reached, the link shows Removing… N left and ApiVault keeps retrying, so it never forgets a variable it still owns. When Vercel refuses ApiVault's access altogether, retrying cannot help: ApiVault asks whether to Remove anyway instead of waiting.
Disconnect unlinks every project on the connection the same way, then removes ApiVault from your Vercel account or team. If another ApiVault project is connected to the same account or team, they share one installation, so it stays until the last of them disconnects.
If ApiVault is removed from your Vercel account or team on Vercel's side, Vercel deletes the variables ApiVault created and syncing stops. Reconnect to sync again, or unlink the projects to clear them from ApiVault.
Troubleshooting by status
Each link shows a status. View details lists the last sync's issues by key, and every sync is recorded in the project's audit log under Integrations. A sync that ends in an error is recorded as a failed sync. Connecting, linking, editing, unlinking and disconnecting are recorded too, including attempts that fail; a disconnect is one entry rather than one per linked project, and an unlink or disconnect that finishes in the background adds a Finished entry.
- Not synced yet — the link is new, or auto-sync is off. Click Sync now.
- Syncing — a sync is running. The page refreshes when it finishes.
- Synced — everything mapped is in Vercel.
- Conflict — the sync finished, but some keys were skipped: a variable you created in Vercel has the same name, or the key's name is not a valid variable name. Fix it, then click Sync now. Conflicts are not retried automatically, because retrying cannot fix them.
- Retrying — Vercel returned an error or was unreachable. ApiVault retries on its own, waiting longer after each failure, up to six hours between attempts.
- Action needed — ApiVault stopped retrying. The Vercel project was deleted or is no longer shared with ApiVault, the connection was revoked or disabled on Vercel, or ten attempts in a row failed. Owners and admins are notified. Fix the cause — reconnect, or share the project with ApiVault again in Vercel — then click Sync now.
- Removing… N left — an unlink is still deleting variables. It retries on its own; see Unlinking and disconnecting.
Supabase Edge Function secrets
The Supabase integration pushes one ApiVault environment into a Supabase project's Edge Function secrets. Functions see a changed secret as soon as the sync finishes; nothing needs redeploying. Syncing runs on the same triggers as Vercel: key changes when auto-sync is on, the retry sweep, and Sync now.
Connecting Supabase
On Integrations, click Connect Supabase. Supabase asks you to choose one organization and approve ApiVault's access to its projects and secrets, then sends you back to the project's Supabase page. To sync to projects in another organization, click Connect Another Organization; each organization gets its own connection.
Linking a Supabase project
Click Add Project on the connection, choose the Supabase project, then choose the ApiVault environment it receives. ApiVault suggests one from the project's name — prod → Production, staging → Staging, dev → Development — when your keys use that environment. A Supabase project receives exactly one environment; link separate Supabase projects for production and staging. Paused projects cannot be linked until you restore them. To send a different environment later, choose Change environment in the link's ⋯ menu; the next sync deletes the secrets the new environment does not contain.
What ApiVault changes in Supabase
Supabase does not record who created a secret, so ApiVault keeps its own list of the secrets it created for each link and only ever updates or deletes those. If a secret you created yourself has the same name as a key, ApiVault skips the key and reports a conflict; delete or rename your secret in Supabase, then click Sync now. Supabase allows at most 100 secrets per project, not counting its built-in SUPABASE_ secrets; keys beyond that are reported as over limit.
A key's name is used as the secret name exactly. Names must start with a letter or underscore, contain only letters, digits and underscores, and must not start with SUPABASE_, which Supabase reserves. Keys with other names are skipped and listed in the sync's issues.
Access, custom vault keys and removal
Projects with a custom vault key work as they do for Vercel: auto-sync is off, and Sync now asks for the key. If the organization stops authorizing ApiVault, the connection shows Access lost, its links show Action needed and owners and admins are notified; click Reconnect to resume. Revoking ApiVault in Supabase does not delete the secrets it created.
Unlink deletes the secrets ApiVault created in that Supabase project, then removes the link; Disconnect unlinks every project and then revokes ApiVault's access, unless another ApiVault project is still connected to the same organization: Supabase would revoke that project's access too, so the authorization stays until the last one disconnects. If the Supabase project was deleted, the link is removed right away. If the connection lost access, the secrets cannot be deleted and Remove anyway lists the ones left in Supabase. The statuses match Troubleshooting by status, with Supabase in place of Vercel.
Cloudflare Workers secrets
The Cloudflare integration pushes your keys into a Worker's secrets and its build variables. Syncing runs on the same triggers as Vercel: key changes when auto-sync is on, the retry sweep, and Sync now, which previews every change first. Workers are supported; Pages projects are not yet.
Connecting Cloudflare
On Integrations, click Connect Cloudflare. Cloudflare asks you to pick one or more accounts and approve ApiVault's access to their Workers, then sends you back to the project's Cloudflare page. One approval is one connection, however many accounts it covers. To add more, click Connect Another Cloudflare Account, with the same Cloudflare login or a different one. If every account you pick is already connected, nothing changes. An approval for other accounts becomes its own connection and leaves the first one as it was. One that adds an account to everything a connection already has updates that connection instead. ApiVault hands back any approval it doesn't keep. Reconnect always replaces the connection it belongs to.
Linking a Worker and its targets
Click Add Worker on the connection, choose the account and the Worker, then tick which targets each ApiVault environment goes to:
- Production — the Worker's secrets. Cloudflare deploys a new Worker version whenever they change, so ApiVault batches a sync's changes into as few writes as it can (usually one deployment) and applies this target last.
- Previews — the secrets every Preview starts from. Changes apply to Previews created after the sync.
- Build · Production and Build · Previews — secret build variables for Workers Builds on your production branch and on other branches. They take effect at the next build; ApiVault does not start one.
ApiVault suggests production or prod → Production and preview, staging or stage → Previews; anything else starts unmapped. A target can come from only one environment. Wrangler environments such as [env.staging] deploy separate Workers (my-api-staging), so link each one. To change the targets later, choose Edit mapping in the link's ⋯ menu.
A target the Worker doesn't offer is greyed out, with the reason:
- Previews aren't enabled for this Worker.
- Build variables need a Git repository connected to the Worker in Cloudflare.
- Build · Previews also needs preview builds, which you turn on in Cloudflare under Settings › Build › Branch control.
What ApiVault changes in Cloudflare
Cloudflare does not record who created a secret, so ApiVault keeps its own list of what it created for each link and target, and only ever updates or deletes those. Anything else with the same name on a target — a secret, plain variable or binding you created, or a plain build variable — is a conflict: the key is skipped on that target only, and the others still sync. Delete or rename your copy in Cloudflare, then click Sync now.
Cloudflare never shows secret values back, so ApiVault can't see an edit made in the dashboard. The next change to the key in ApiVault overwrites it, and a secret deleted in Cloudflare is created again on the next sync.
A key's name is used exactly. Names must start with a letter or underscore and contain only letters, digits and underscores; build targets also reserve CI and names starting with WORKERS_CI, which Workers Builds sets itself. Values over 5 KiB are skipped without being sent. How many variables a Worker may hold depends on your Cloudflare plan: when Cloudflare refuses more, the keys it refused are reported as over limit and the rest are still sent.
Gradual deployments
While a Worker's latest version is only partly deployed, Cloudflare refuses changes to its secrets. The link shows Retrying with "Cloudflare refused the change because the Worker's latest version isn't fully deployed. Finish or roll back the gradual deployment." ApiVault keeps retrying; after ten failures in a row it stops and notifies owners and admins.
Access, custom vault keys and removal
Projects with a custom vault key work as they do for Vercel: auto-sync is off, and Sync now asks for the key. If you revoke ApiVault in Cloudflare (Profile → Manage OAuth authorizations), the connection shows Access lost, its links show Action needed and owners and admins are notified; click Reconnect to resume. If an account is left out of a new approval, its Workers show Action needed until you connect again and include it. A target that stops being available is reported as Unavailable on the link while the other targets keep syncing.
Unlink deletes the secrets and build variables ApiVault created on every target, then removes the link; deleting production secrets deploys a new Worker version. Disconnect unlinks every Worker and then hands back that project's Cloudflare tokens. Each project's connection is its own approval, so another ApiVault project connected with the same Cloudflare login keeps working. If ApiVault can't reach the account, Remove anyway lists what stays in Cloudflare. The statuses match Troubleshooting by status, with Cloudflare in place of Vercel.
Handing the tokens back stops ApiVault reaching your account, but Cloudflare still lists the application under My Profile → Access Management → Connected Applications, because it keeps the approval itself separate from the tokens issued against it. To clear that entry too, select Revoke there; that cuts off every ApiVault project connected with that Cloudflare login.
Self-hosting
A self-hosted ApiVault needs its own integration registered in Vercel's Integrations Console, with the redirect URL https://<your-host>/api/integrations/vercel/callback and these scopes: project (read), project environment variables (read and write), deployments (read and write) and integration configuration (read and write). Then set:
VERCEL_INTEGRATION_CLIENT_IDandVERCEL_INTEGRATION_CLIENT_SECRET— from the consoleVERCEL_INTEGRATION_SLUG— the integration's URL slugCRON_SECRET— a random value that authorizes the retry sweep
Without the first three, the Integrations page says the integration is not configured. The retry sweep at /api/cron/integrations runs once a day from vercel.json, the most often Vercel's Hobby plan allows. On Pro, a */5 * * * * schedule retries failed syncs within minutes. Elsewhere, call it on a schedule with Authorization: Bearer $CRON_SECRET.
For Supabase, create an OAuth app in your Supabase organization (Organization settings → OAuth Apps) with the redirect URL https://<your-host>/api/integrations/supabase/callback and the scopes Secrets (read and write), Projects (read) and Organizations (read). Then set SUPABASE_INTEGRATION_CLIENT_ID and SUPABASE_INTEGRATION_CLIENT_SECRET.
For Cloudflare, create an OAuth client in your Cloudflare account (Manage account → OAuth clients) with the response type Code, the grant types Authorization Code and Refresh Token, the token authentication method Client Secret Basic, the redirect URL https://<your-host>/api/integrations/cloudflare/callback and these five permission scopes: Workers Scripts Read, Workers Scripts Write, Workers CI Read, Workers CI Write and Account Settings Read (workers-scripts.read, workers-scripts.write, workers-ci.read, workers-ci.write, account-settings.read). ApiVault also asks for offline_access when it sends you to Cloudflare, which is what returns a refresh token; it is an OIDC scope and is not registered on the client. Then set CLOUDFLARE_INTEGRATION_CLIENT_ID and CLOUDFLARE_INTEGRATION_CLIENT_SECRET. A new client is private: only members of the account that created it can approve it until you make it public. The same retry sweep and CRON_SECRET cover every provider.