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

# Webhooks and schedules

> Start Plays from authenticated inbound events or cron schedules, with explicit delivery and activation semantics.

[Human guide: work with your agent →](https://deepline.com/docs/human/sdk-v2/webhooks-and-schedules.md)

> [!NOTE]
>
> Configure one authenticated or scheduled entry point and verify its input and
> delivery identity.

Use a **webhook** when another system decides when work starts. Use a **schedule**
when time decides. Both bindings are part of the Play definition and become
active only when you publish the checked Play.

## Inbound webhook contract

The JSON request body becomes the Play input. Keep the input small and explicit:

```json theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
{
  "email": "jane@example.com",
  "company_domain": "example.com",
  "source": "hubspot"
}
```

This binding verifies a Standard Webhooks v1 signature before the handler runs:

```ts theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
import { definePlay } from 'deepline';

type InboundLead = {
  email: string;
  company_domain?: string;
  source?: string;
};

export default definePlay(
  'inbound-lead',
  async (_ctx, input: InboundLead) => ({
    email: input.email,
    company_domain: input.company_domain ?? null,
    source: input.source ?? 'webhook',
  }),
  {
    description: 'Accept an authenticated inbound lead for downstream routing.',
    webhook: {
      auth: {
        type: 'standard-webhooks',
        headerFamily: 'standard',
        signingSecrets: ['INBOUND_RELAY_WEBHOOK_SECRET'],
        toleranceSeconds: 300,
      },
    },
  },
);
```

Set the secret through the hidden CLI prompt. do not put its value in a command,
file, or agent prompt:

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline secrets set INBOUND_RELAY_WEBHOOK_SECRET
```

HubSpot v3 signatures are not Standard Webhooks signatures. Put an authenticated
relay in front of a HubSpot-bound Play: verify the HubSpot signature there, then
sign the forwarded body with `webhook-id`, `webhook-timestamp`, and
`webhook-signature` under Standard Webhooks v1.

Use `webhook: {}` only in an isolated test environment. Require signature
verification before production whenever the sender supports it.

## Webhook delivery identity

Deepline deduplicates a retry only when the sender supplies a stable delivery
identity. Header precedence is:

1. `x-deepline-dedupe-key`
2. `idempotency-key`
3. `x-github-delivery`
4. `x-shopify-webhook-id`
5. `webhook-id`
6. `svix-id`

Reuse the same nonblank value only for a retry of the same delivery. Give each
new delivery a different value.

Without one, every POST begins a new run. Deepline does not infer identity from
identical JSON or a generic top-level `id`.

## Cron schedule

Use a five-field cron expression and an IANA timezone. This minimal Play has no
required input, so its scheduler can invoke it directly:

```ts theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
import { definePlay } from 'deepline';

export default definePlay(
  'daily-account-review',
  async (_ctx) => ({ scheduled_at: new Date().toISOString() }),
  {
    description: 'Start the daily account-review workflow.',
    cron: {
      schedule: '0 9 * * *',
      timezone: 'America/New_York',
    },
  },
);
```

Move your account selection and enrichment logic into the handler. If that
logic processes rows, use a durable dataset as described in
[Write Plays](https://deepline.com/docs/sdk-v2/plays.md).

## Activate and test deliberately

Trigger declarations are inert while the play is a draft.

```bash theme={"languages":{"custom":["/languages/deepline-prompt.json"]}}
deepline plays check ./daily-account-review.play.ts
deepline plays publish ./daily-account-review.play.ts
deepline plays run ./daily-account-review.play.ts --input '{}'
```

The manual run validates the checked handler before the next schedule or
external event. It does not substitute for testing sender authentication or
observing the published binding.

## Verify this task

Check and publish the source, then inspect the generated binding. Test repeated delivery separately from a new event.

Ask your agent to explain a failed check before repeating work or expanding the scope.


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