Every site that deploys from Git has its own deploy hook: a URL and a secret. Your Git host uses them to tell us about pushes, and your CI pipeline can use them too, to deploy once its own checks have passed. That is the usual way to run a site set to Manually (Deploy modes).
Before you start
- Your site has a Git repository connected (Deploy from Git). The URL and secret appear once it has.
- Anyone who can see the site's Deploys tab can read the secret. Store it in your CI as a secret variable, never in your repository.
Set it up
-
Open Sites → your site → Deploys, then Git settings (or open Deploy from Git).
-
Under Auto-deploy on push, copy the URL and the Secret.
-
In your CI, save the secret as a masked secret variable, for example
VELDHOST_DEPLOY_SECRET. -
Add a step after your tests:
curl -fsS -X POST -H "X-Veldhost-Token: $VELDHOST_DEPLOY_SECRET" "WEBHOOK_URL" -
Run the pipeline. The deploy appears at the top of the Deploys tab, and in Recent deploys when it finishes.
The secret goes in the X-Veldhost-Token header only. A secret in the URL (?token=) is refused, because a URL ends up in logs along the way.
What the call deploys
A call with no body has no branch or tag in it, so it is not a push. It deploys your site's branch to the live site straight away, in every deploy mode, including Manually and On release tags.
A call with a JSON body containing a ref is treated exactly like a push from your Git host, and your deploy mode decides what happens. For example, with On release tags you can deploy a tag your pipeline has just created:
curl -fsS -X POST -H "X-Veldhost-Token: $VELDHOST_DEPLOY_SECRET" \
-H "Content-Type: application/json" \
-d '{"ref":"refs/tags/v1.4.0"}' "WEBHOOK_URL"
The tag deploys only if it matches your Release tag pattern. In Manually mode a call with a ref never deploys.
Read the answer
The hook answers with JSON:
202with"status": "deploy_queued": the deploy has started.202with"status": "queued_behind_running_deploy": a deploy is already running. Yours is kept and runs as soon as that one finishes.200with"status": "ignored": nothing was deployed. Most answers add areason(manual mode, not a release tag, site not deployable); a push to a branch we don't deploy only echoes theref.401: the secret is wrong. The same answer is given for a site that does not exist, so check the URL as well.
-f in the curl above makes your pipeline step fail on a 401. A 202 only means the deploy has started: the build, your tests and the publish happen afterwards. Follow the result on the Deploys tab, or with GET /api/v1/sites/{slug}/deploys.
The hook is rate-limited. A pipeline that calls it on every commit of a busy repository can be refused for a while; deploy on merges or tags instead.
With an API token instead
If your pipeline already has a personal API token with the deploy scope, POST /api/v1/sites/{slug}/deploy does the same as a call without a body, except that while a deploy is running it answers already_queued and does not queue another. See the API reference.
Note: With the CI/CD add-on on, a deploy started by the hook is built and tested, then waits for someone to approve it. The hook cannot approve it for you.
If the secret leaks
Anyone with the URL and the secret can start a deploy. It still deploys code from your own repository. If you think the secret has leaked, contact us.