📩Webhooks

Webhooks let DevPayr tap your backend on the shoulder and say, “Hey, something just changed — you may want to react.”

Instead of polling DevPayr for updates, you give us an HTTPS endpoint and we send signed JSON requests whenever important events happen on your projects, licenses, or domains.

Common things you might do with webhooks:

  • Activate or lock a user’s account after a license is created or suspended

  • Sync project/domain changes into your own admin panel

  • Trigger emails or notifications when a project is marked as paid

  • Keep your billing system and DevPayr in sync without manual work

1. Where to Configure Webhooks

You can define a webhook endpoint in two places:

a) Account-level webhook (profile / settings)

From your DevPayr dashboard:

  • Go to Settings → Account

  • Set your Webhook Endpoint — e.g. https://yourapp.com/devpayr/webhooks

This acts as a fallback URL used by all projects that don’t have their own project-level webhook.

b) Project-level webhook

When creating or editing a project (see the “Create New Project” screen):

  • In Integration / Webhook Settings, set:

    • Project Webhook URL – where this project’s webhooks should be sent

    • Webhook Secret – a secret string used to sign payloads (more on this below)

If a project has its own Project Webhook URL, that URL is used instead of the profile-level one.

Rule of thumb

  • Project Webhook URL set? → use that

  • Otherwise → use profile-level webhook URL

  • If neither exists → no webhooks are sent for that project

2. Events DevPayr Sends

DevPayr sends webhooks for changes around projects, domains, and licenses.

Each webhook payload has this general structure:

And every request includes helpful HTTP headers (explained in the next section).

Project-level events

These events help you keep your own system in sync with what’s happening to a project.

  • project.created Fired when a new project is created in DevPayr.

  • project.updated Fired when key project fields change (name, slug, description, logo, redirect URL, meta, etc.).

  • project.paid_status_toggled Fired whenever the has_paid flag on a project is turned on or off. Useful if you treat “has_paid = false” as “lock this product”.

Project domain events

These events are about domains attached to a project.

  • project.domain.added A domain has been added to the project (including environment, whether it’s primary, verified, etc.).

  • project.domain.deleted A domain has been removed from the project.

  • project.domain.environment_updated The domain’s environment changed (e.g., from staging to production).

  • project.domain.primary_set A domain has been set as the primary domain for the project.

License events

These events track the lifecycle of a license and the domains attached to it.

  • license.created A new license was created for a project.

  • license.suspended A license was suspended / revoked (you’ll usually want to lock the user here).

  • license.reactivated A previously suspended license is re-enabled.

  • license.domain.added A new domain has been attached/learned for that license (license-level domain mode).

  • license.domain.removed A domain has been detached from that license.

You don’t need to memorize all of these — your endpoint will always receive the event name in the payload and in a header so you can switch on it.

3. Request Format & Headers

Every webhook delivery is:

  • An HTTP POST

  • With Content-Type: application/json

  • Carrying the JSON payload described above

In addition, DevPayr includes a few headers to help you route and verify the request:

  • X-Webhook-Event – the event name (e.g. license.created)

  • X-Project-ID – the numeric ID of the project firing the event

  • X-License-ID – present for license-related events (license created / suspended / etc.)

  • X-Signature – HMAC-SHA256 signature of the JSON payload using your project’s Webhook Secret

4. Example Payloads

These examples show the shape of the data you’ll receive. Field names may grow over time, but the structure remains similar.

4.1 project.created

You can use this to auto-create a matching record in your own database.

4.2 project.paid_status_toggled

Typical reaction in your system:

  • has_paid = true → unlock the software, enable premium features

  • has_paid = false → schedule a downgrade, show a “payment required” message, etc.

4.3 license.created

You might:

  • Attach this license to the customer record in your own DB

  • Trigger a “Your license is ready” email with the masked key

  • Start a provisioning job for the customer’s environment

4.4 license.suspended

Typical reactions:

  • Mark the customer’s subscription as “suspended”

  • Lock logins or reduce features in your app

  • Show an in-app banner telling them to contact billing or renew

4.5 project.domain.added

You could:

  • Log this domain in your control panel

  • Use it to configure routing, SSL, or DNS automation in your own infra

4.6 license.domain.added

If you use DevPayr’s license-level domain tracking, this lets you see where a license is being activated.

5. Verifying the Signature

To make sure a webhook really came from DevPayr and not from a random script, you should verify the X-Signature header using your Webhook Secret.

The logic is:

  1. Take the raw JSON body exactly as received.

  2. Compute HMAC-SHA256(body, webhook_secret)

  3. Compare that value to the X-Signature header (constant-time compare if possible).

  4. If they don’t match, reject the request.

Example – Node.js (Express)

Example – PHP (generic)

You can adapt the same pattern in any language that supports HMAC-SHA256.

Tip

Always respond quickly (just 200 OK) and push heavy work (emails, database tasks, external API calls) to a background job or queue. Webhooks should be treated like fire alarms — acknowledge fast, handle details in the background.

6. Best Practices

To get the most out of DevPayr webhooks:

  • Always use HTTPS for your webhook endpoint.

  • Set a Webhook Secret for each project and verify X-Signature on every request.

  • Use project-level webhooks when different projects need to hit different systems.

  • Log incoming webhooks on your side while integrating — it makes debugging far easier.

  • Make processing idempotent (don’t double-process the same event if your endpoint is called twice). Using a combination of event + resource ID + timestamp is usually enough.

  • Return a 2xx status code once you’ve accepted the event. Non-2xx means “delivery failed”.

Once your webhook endpoint is wired up, DevPayr becomes much more than “just a license check”. Your own systems will be able to react in real-time whenever licenses, domains, or project billing status change — without you writing extra cron jobs or manual sync scripts.

Last updated