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

> ## Agent Instructions
> The docs are served at https://docs.devias.io. Every path in these docs is relative to that root: /llms.txt is https://docs.devias.io/llms.txt.
> Devias is an open-source platform that works as an operating system for a business: a core (records, views, workflows, agents, permissions) with installable modules.
> Pages are typed by folder. concepts/ explains what things are, guides/ gives procedures, reference/ is exhaustive (SDK, CLI, HTTP API), operate/ covers hosting. Use /start/glossary for exact terms.
> Every id in a module (module, object, field, view, action, workflow, step, connection, variable, event, policy) is a uuid. Generate them with `devias id <count>`. Never invent dotted or readable ids.
> Run `devias plan` and read its output before `devias apply`. Apply only what the plan says.
> The OpenAPI document, including the routes of the modules in the reference setup, is at /reference/api/openapi.json.
> Devias is young and changes quickly. If a page and the source repository (github.com/devias-io/devias) disagree, the repository is right.

# Connections and events in a module

> How a module connects to an outside service. Covers defineConnection (api_key and oauth2, workspace or personal), connection tests, defineVariable settings, and defineEvent with a webhook parse function that verifies signatures and returns events deduplicated by externalId.

Many modules talk to a service such as Stripe, Resend or Google. Devias stores credentials safely, asks people to connect, and receives events. A module declares a **connection**, optional **variables** and the **events** it receives.

## Declare a connection with defineConnection

A connection is how a workspace or a person signs in to the service. There are two kinds.

| Kind | For | Belongs to |
| - | - | - |
| `api_key` | A key or token the user pastes in. You list the fields to ask for. | The workspace, by default |
| `oauth2` | "Sign in with…". You give the authorize and token URLs and the scopes. | Each person, by default |

```ts theme={"dark"}
defineConnection({
  id: ids.connections.default,
  kind: 'api_key',
  label: 'Stripe',
  fields: [{ name: 'secret_key', label: 'Secret key', placeholder: 'sk_live_…' }],
})
```

`visibility` is `workspace`, `user` or `both` and chooses who may make a connection. Credentials are encrypted at rest and shown back only as a masked hint. In server code, `ctx.connection()` returns the connection in use.

A **connection test** in server code gives people an immediate "it works" or a clear error when they connect. If the service refuses the credentials, `ctx.reportAuthFailure()` makes Devias ask people to reconnect.

## Declare a variable with defineVariable

A variable is a setting the module's code reads, such as a region or an OAuth app's client id. `secret` keeps it write-only, `required` makes the module ask for it, and `defaultValue` gives it a value when nobody sets one. Admins set variables on the module's page in **Settings → Modules**.

```ts theme={"dark"}
defineVariable({
  id: ids.variables.min_match_score,
  label: 'Minimum match score',
  description: 'How sure the service must be, from 0 to 100.',
  defaultValue: '70',
})
```

In server code, `ctx.variables[id]` is the value in effect: the workspace's own, else the default. A variable that nobody set and that has no default is absent.

## Declare events with defineEvent

An event is something the service reports, such as `invoice.paid`. Workflows can start from the declared events.

1. **Declare the events.**

   Give each event an id and its name as the service writes it:

   ```ts theme={"dark"}
   defineEvent({
     id: ids.events.invoice_paid,
     name: 'invoice.paid',
     description: 'An invoice was paid.',
   })
   ```

2. **Handle the webhook.**

   In server code, add a `webhook` with a `parse` function. It verifies the delivery's signature using the connection and returns the events the delivery carries. Throw `WebhookRejected` for a bad signature or an unreadable body. Returning an empty array acknowledges the delivery with a success response and stores nothing.

3. **Give the service the address.**

   Each connection has its own webhook address, shown on the module's **Events** tab. `webhookHelp` in the manifest tells people where to paste it in the service.

Devias stores every event once, even if the service sends it twice, provided the returned event carries the service's own id as `externalId`. It then announces the event to workflows that listen for it. A module can ship such a workflow itself, which is how the Stripe module records a payment when Stripe reports one.

## Related

* [Workflows in a module](https://docs.devias.io/guides/modules/workflows.md): react to events in the background.
* [Install and connect modules](https://docs.devias.io/guides/studio/modules.md): what users see.
* [Actions and server code](https://docs.devias.io/guides/modules/actions-and-server-code.md): the handler context.


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