> ## Documentation Index
> Fetch the complete documentation index at: https://docs.base44.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Internal links on these pages omit the .md extension. Append .md to a docs page URL, or send an Accept: text/markdown header, to get that page as markdown.

# Setting up endpoints

> Register an HTTPS endpoint with a workspace API key, activate it by echoing the test challenge, and pause, update or remove it when your receiver changes.

An endpoint is the HTTPS URL Base44 sends your events to. You can register one in your workspace settings, or with a workspace API key when a script sets up your workspace. This page covers the API. For the settings page, see [Sending workspace events with webhooks](/Enterprise/workspace-webhooks).

<Warning>
  Outbound webhooks are available on the Business and Enterprise plans.
</Warning>

***

## Authenticating

Endpoint requests use a workspace API key with the `outbound_webhooks:write` scope, shown as **Manage outbound webhooks** when you create the key. Send it in the `Authorization` header. The key decides the workspace, so no workspace ID appears in the URL.

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

To create a key, see [Managing workspace secrets](/Enterprise/workspace-secrets). Only workspace owners and admins can create one.

<Warning>
  Treat the key like a password. Anyone who holds it can send your workspace's events to a URL of their choice.
</Warning>

***

## Registering an endpoint

Registering creates the endpoint and activates it in the same call. Base44 sends a signed `webhook.test.v1` event to your URL, and the endpoint becomes **Active** only if your receiver answers with a 2xx within 5 seconds and echoes the challenge.

```bash theme={null}
curl --request POST \
  --url https://app.base44.com/api/v1/outbound-webhooks/endpoints \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "target_url": "https://hooks.yourcompany.com/base44",
    "selected_event_types": ["app.created.v1", "app.published.v1"],
    "description": "Production sync"
  }'
```

The URL must use `https`, can't include a username or password, and can't point at a private network. Base44 never follows redirects, so register the exact URL that answers.

The response is `201` whether or not activation succeeded, because the endpoint was created either way. Check `activated`:

```json theme={null}
{
  "endpoint": {
    "id": "68d4e5f6a7b8c9d0e1f2a3b4",
    "target_url": "https://hooks.yourcompany.com/base44",
    "description": "Production sync",
    "selected_event_types": ["app.created.v1", "app.published.v1"],
    "state": "pending",
    "health": "unknown",
    "consecutive_failed_deliveries": 0
  },
  "activated": false,
  "http_status": 200,
  "failure_category": "client_error",
  "detail": "The receiver answered 2xx but did not echo the challenge from the request body. Return the `challenge` value to confirm you received it."
}
```

When `activated` is `false`, fix your receiver and run the test again. Don't register the endpoint a second time.

### Echoing the challenge

The echo proves you control the URL. Without it, anyone could point Base44's traffic at a host that never asked for it.

The test event's `data.challenge` holds a one-time value. Return it in the response body in either of these forms:

```json theme={null}
{ "challenge": "8f14e45fceea167a5a36dedd4bea2543" }
```

Or the value alone, as the whole body. Anything else fails, including a partial match.

A simple receiver checks the event type before its normal handling:

```js theme={null}
if (event.type === "webhook.test.v1") {
  return Response.json({ challenge: event.data.challenge });
}
```

<Tip>
  Verify the signature on the test event too. It's signed exactly like a real delivery, so a receiver that passes the test has proven it can verify production traffic.
</Tip>

***

## Testing an endpoint again

Run the activation test again after you fix your receiver, or after you change the endpoint's URL.

```bash theme={null}
curl --request POST \
  --url https://app.base44.com/api/v1/outbound-webhooks/endpoints/{endpoint_id}/test \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

The response has the same shape as registration.

***

## Managing endpoints

These requests use the same header as registration. Each returns the endpoint.

| Request | What it does |
| - | - |
| `GET /api/v1/outbound-webhooks/endpoints` | Lists your endpoints, oldest first. Pass the returned `next_cursor` as `cursor` to get the next page. |
| `GET /api/v1/outbound-webhooks/endpoints/{endpoint_id}` | Gets one endpoint. |
| `PATCH /api/v1/outbound-webhooks/endpoints/{endpoint_id}` | Changes `target_url`, `selected_event_types` or `description`. |
| `POST /api/v1/outbound-webhooks/endpoints/{endpoint_id}/pause` | Stops deliveries, for example while you redeploy your receiver. |
| `POST /api/v1/outbound-webhooks/endpoints/{endpoint_id}/resume` | Starts deliveries again. |
| `DELETE /api/v1/outbound-webhooks/endpoints/{endpoint_id}` | Removes the endpoint. |

For every request and response field, see the [API reference](/api-reference/outbound-webhooks/register-an-endpoint).

<Note>
  **What changes an endpoint's state:**

  * Changing `target_url` returns the endpoint to **Pending**. Run the test again to activate the new URL.
  * Changing the selected events or the description keeps it **Active**.
  * Events that happen while an endpoint is paused or pending aren't sent to it, even after it's active again.
  * Resuming an endpoint that Base44 auto-paused runs the activation test first. See [Delivery and retries](/developers/references/outbound-webhooks/get-started/delivery-and-retries).
</Note>

***

## Errors and rate limits

Errors use one shape, with a stable `code` to match on:

```json theme={null}
{
  "error": {
    "code": "invalid_request",
    "message": "The request is invalid.",
    "details": { "reason": "target_url_has_credentials" }
  }
}
```

| Status | `code` | Meaning |
| - | - | - |
| 400 | `invalid_request` | A field is missing or invalid. `details` says which. |
| 401 | `unauthenticated` | The key is missing or not a workspace API key. |
| 403 | `permission_denied` | The key doesn't have the `outbound_webhooks:write` scope, or your plan doesn't include outbound webhooks. |
| 404 | `not_found` | No endpoint with that ID in your workspace. |
| 409 | `limit_exceeded` | Your workspace already has 10 endpoints. |
| 409 | `conflict` | The endpoint changed while the request ran. Get it again and retry. |
| 429 | `rate_limited` | Too many requests. Wait for the time in `Retry-After`. |

Each workspace can make at least 300 endpoint reads, 60 endpoint changes and 10 activation tests per minute.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.