Guide

Deploy hooks

A secret URL that rebuilds your site when it is called: connect Contentful, Sanity, WordPress or any CMS so publishing content updates the site.

On this page

A deploy hook is a secret URL that rebuilds your site. Paste it into your CMS (Contentful, Sanity, WordPress and others), and every time an editor publishes, the site is rebuilt with the new content. No code push needed.

Deploy hooks work for projects connected to GitHub, because a hook builds the latest commit on a branch. If your project is not connected yet, see Import from GitHub.

Create a hook

  1. Open your project in Hosting and choose the Settings tab.
  2. Find Deploy hooks. (It only appears once the project is connected to GitHub.)
  3. Under Create hook, give it a Name you will recognise later, such as CMS publish (up to 60 characters).
  4. Leave Branch as your production branch to update the live site, or type another branch to build a preview of it (see Production and preview branches).
  5. Choose Create hook.

What you'll see: "CMS publish is ready. Copy its URL now: it won't be shown again." with the URL and a ready-made curl command, each with a copy button.

Copy the URL now. Zeloxa only stores a fingerprint of it, so it cannot show it again. If you lose it, delete the hook and create a new one.

The URL looks like this:

https://zeloxalabs.com/api/host/hooks/zdh_…

Treat it like a password. Anyone who has it can start builds of your site (and nothing else). A project can have up to 10 hooks, so give each CMS or person its own, and delete one without affecting the others.

Test it

Send an empty POST to the URL:

curl -X POST "https://zeloxalabs.com/api/host/hooks/zdh_…"

What you'll see: a reply with status 202 and a new build on the project's Git tab:

{ "job": { "state": "PENDING", "deploymentId": "6f1c2b8e-…" } }

Any request body is ignored, so your CMS can send whatever it normally sends. Opening the URL in a browser does nothing (a GET is refused with 405), so a link preview or a crawler cannot start builds.

Production and preview branches

The hook's branchWhat a call does
Your production branch (the one on the Git tab)Builds the latest commit and, if the build succeeds, makes it live. Exactly like a push.
Any other branchBuilds that branch's preview at its own address. The live site does not change.

A hook on another branch only works while previews are on for the project. If they are off, the call fails with 409 and the message "Previews are off for this project, so a hook on … cannot build. Turn previews on or point the hook at …".

A hook builds even when Deploy automatically on every push is off on the Git tab.

Responses

StatusMeaning
202 with "state": "PENDING"A build started. deploymentId names it.
202 with "state": "QUEUED"A build was already running, so this one did not start yet. The latest commit of your production branch builds as soon as the running build ends, so the new content still goes live.
202 with "state": "SKIPPED"Nothing was started: a build for this preview branch is already running, or every build slot is busy. The response includes a reason. Call the hook again in a minute.
404Unknown URL. A deleted hook, a typo and a made-up URL all get the same answer: "Deploy hook not found."
409The project is no longer connected to GitHub, or the hook is on a preview branch and previews are off.
429The hook was called less than 10 seconds ago. Wait and call again. The response has a Retry-After: 10 header.
403Builds are paused because the organization's subscription is inactive.

Errors use the same JSON shape as the rest of the Zeloxa Host API (see Errors):

{ "error": { "code": "RATE_LIMITED", "message": "This hook was triggered moments ago. Wait 10 seconds between calls.", "details": { "retryAfterSeconds": 10 } } }

The 10-second cooldown

Each hook can start one build every 10 seconds. This stops a leaked URL, or a CMS stuck in a loop, from filling your builds.

If an editor publishes several items in quick succession, later calls inside the 10 seconds get 429. A call made while a production build is running is not lost: it is queued and builds again when the current build ends. To be sure the very last change is included, publish (or call the hook) again a little later.

Use it from your CMS

Every CMS has a "webhook" setting. Point it at your deploy hook URL, method POST, and choose the events that should rebuild the site. Menu names change over time; look for these settings.

Contentful

  1. In your space, open Settings → Webhooks and choose Add Webhook.
  2. Name it, for example "Zeloxa deploy".
  3. URL: method POST, then paste your deploy hook URL.
  4. Triggers: choose the events to rebuild on, usually Publish and Unpublish for entries and assets.
  5. Save.

Sanity

  1. Open your project at sanity.io/manage and go to API → Webhooks.
  2. Choose Create webhook.
  3. Paste your deploy hook URL as the URL, pick the dataset, and choose the trigger events (create, update, delete).
  4. HTTP method: POST. Save.

WordPress

WordPress has no webhook setting of its own. Use one of these:

  • A webhook plugin: add a webhook that fires when a post is published or updated, with your deploy hook URL and method POST.

  • A few lines in your theme or a small plugin, run when a post is published:

    add_action('transition_post_status', function ($new, $old, $post) {
        if ($new === 'publish' || $old === 'publish') {
            wp_remote_post('https://zeloxalabs.com/api/host/hooks/zdh_…', ['blocking' => false]);
        }
    }, 10, 3);

Keep the URL out of public code repositories: anyone who reads it can start builds.

Any other service

Anything that can send an HTTP POST can use a deploy hook: a scheduler for a nightly rebuild, a form tool, a spreadsheet script, or a CI job.

Revoke a hook

  1. Open the project's Settings tab and find Deploy hooks.
  2. Choose Delete next to the hook and confirm.

What you'll see: "Delete the deploy hook "CMS publish"? Its URL stops working immediately." After you confirm, calls to the URL get 404.

Delete and recreate a hook whenever its URL may have leaked, and when someone who had it no longer should. Disconnecting the project from GitHub also stops every hook from building (409).

Ready when you are

Everything in this guide is under Hosting in your dashboard.

Open Hosting

Something unclear or missing? Tell us.