# Integrations

> Sync card due dates with Google Calendar, show the family calendar in Apple Calendar or Outlook, forward school letters by email, sync a board with Google Sheets, send signed webhooks, link GitHub pull requests to cards, reach Zapier, Make and n8n, post to Slack, and bring in Canva designs.

Nobody wants a second calendar, so these integrations are narrow on purpose.
Each one moves a specific thing between The Margin and a tool you already use,
and asks Google for the smallest permission that does the job.

| Integration                                 | What moves                                            | Where you set it up                                     |
| ------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------- |
| Google Calendar                             | Card due dates out, events in                         | The gear on the Calendar page, **Google Calendar sync** |
| Apple Calendar, Outlook, any calendar app   | The family calendar out, read-only, by a private link | **Share and subscribe** on the Calendar page            |
| A published calendar (a school's, a club's) | Its events in, read-only                              | **Share and subscribe** on the Calendar page            |
| Email                                       | A forwarded school letter becomes dates to confirm    | The Calendar's settings, **Forward letters by email**   |
| Google Sheets                               | One board's cards, either way                         | A board's settings, **Google Sheets sync**              |
| Webhooks                                    | Events out to a URL you choose                        | **Settings → Webhooks and API**                         |
| GitHub                                      | Pull requests and issues noted on cards               | **Settings → Integrations**                             |
| Slack                                       | Events out to a channel, through a webhook            | **Settings → Webhooks and API**                         |
| Zapier, Make and n8n                        | Events out by webhook, calls in with an API key       | **Settings → Webhooks and API**                         |
| Canva                                       | Designs in, as pages you can work with                | A whiteboard's **Bring in a Canva design**              |

Connect your Google account once in **Settings → Integrations**. Calendar and
Sheets each ask for their own permission the first time you use them.

## Google Calendar

Open the Calendar page, press the gear and choose **Google Calendar sync**.
Pick a calendar, a direction (**Push (Margin to Calendar)**,
**Pull (Calendar to Margin)** or
**Bidirectional**) and how many days ahead to cover, from 1 to
365\. Turn on **Enable sync**. Nothing moves until you press
**Sync Now**, and nothing runs on a timer: each sync is one
press.

- **Push** sends every open card with a due date inside that window to the
  calendar. A repeating card goes as one repeating event, so a weekly standup
  stays one series. Completed cards stay behind, and so does any column you
  have hidden from the calendar.
- **Pull** brings the calendar's events into a board called Calendar, which
  is made for you the first time. Each event becomes a card with its date.

> **Known limit: Repeating events arrive one card per date** Pull lists each occurrence separately, so a weekly event becomes one card
> for every week inside the window. A 365-day window turns a weekly standup
> into 52 cards. Keep the window short if you pull.

For a pulled card, the calendar is the source. The next pull overwrites its
title, description and date with whatever the event says, so make those
changes in Google.

We ask for `calendar.events`, which lets us create, read and update events and
nothing else: not your calendar settings, not who you share calendars with.
Google turned down our first verification for asking more broadly than that,
and they were right to.

## Google Sheets

From a board's settings, **Google Sheets sync** links the board to a
spreadsheet. Pick one with Google's picker or **Browse**, or paste the link of
a sheet The Margin made for you, then choose a direction:
**Push (Margin to Sheets)** writes the board's cards into the
sheet, **Pull (Sheets to Margin)** reads rows back as cards
(rows it has already imported are not doubled), and
**Bidirectional** does one then the other. With no sheet
chosen, **Create & Sync** makes a new spreadsheet named after
the board. Like the calendar, **Enable sync** has to be on, and a sync runs when
you press it.

It suits the person in the loop who lives in a spreadsheet and is not going to
stop.

We ask for `drive.file`. That covers files you pick through Google's own
picker and files the app created for you, and nothing else in your Drive,
which is why a pasted link only works for a sheet The Margin made.

## Webhooks

A webhook sends a signed `POST` to your URL when something happens in the
workspace. In **Settings → Webhooks and API**, press
**New webhook**, give it a name and a payload URL, check its
events, then use **Send test** to check the URL answers. The
**Active** switch pauses a webhook without deleting it.

The payload URL has to be a public web address, on any port. An address on a
private network, `localhost` or a cloud server's internal address is refused
when you save it, and checked again before every delivery. Redirects are not
followed: answer at the URL you gave.

**The events you can subscribe to**

- **Workspace and people**: a workspace created or updated, a member added, removed or given a new role.
- **Boards and cards**: a board created, updated or archived; a card created, updated, moved,
  completed or deleted.
- **Notes**: a note made, in the app or from a share, a scan, an email or an automation.
- **Agent pacts**: a pact created or archived, a message posted or its status changed, a
  section updated, a decision raised or resolved, a participant added, joined
  or revoked, a handshake updated.
- **The kitchen**: a meal planned, cooked or removed, a recipe saved, a shopping run finished.

- **Syncs**: a Sheets sync or a Calendar sync finished.

Every delivery carries `X-Margin-Event` with the event name,
`X-Margin-Event-Id` with the event's own id (the same on every retry, so you
can skip one you have already handled), `X-Margin-Delivery` with an id for
that attempt, and `X-Margin-Signature`: an
HMAC-SHA256 of the raw body, keyed with the webhook's secret. The secret is
shown once, when you create the webhook, and you can regenerate it later.
Check the signature before trusting a delivery:

```ts
import { createHmac, timingSafeEqual } from "node:crypto"

// rawBody is the request body exactly as it arrived, before any JSON parsing.
export function isFromMargin(rawBody: string, header: string, secret: string) {
  const expected =
    "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex")
  const a = Buffer.from(expected)
  const b = Buffer.from(header)
  return a.length === b.length && timingSafeEqual(a, b)
}
```

A delivery that fails is tried five times in all, with the wait doubling from
ten seconds. Each webhook lists its **Recent deliveries**, with the event, the
status and the HTTP code your server sent back.

> **On the phone:** The phone app has the same page under **Settings → Connections → Webhooks and API**: add, change, pause, test and delete webhooks,
> read their recent deliveries, regenerate a signing secret, and make or revoke
> API keys. A new secret or key is shown once, with a button that hands it to
> your share sheet to copy.

## Slack

What works today: Margin events posted into a Slack channel. In Slack, make
an incoming webhook for the channel (Slack's own **Incoming Webhooks** app
gives you a `hooks.slack.com` address). Paste that address as the payload URL
of a new webhook in **Settings → Webhooks and API** and pick
the events. The Margin sees it is a Slack address and sends each event as a
short Slack message rather than raw JSON.

> **Known limit: The Slack app is still being set up** **Settings → Integrations** has a Slack card, and today it
> says **Coming soon** with no button. Until the app is ready you cannot type
> `/margin` in Slack or save a Slack message to The Margin.

When the app is ready, an owner or admin presses **Add to Slack**
on that card and Slack asks which channel The Margin may post to. Then
`/margin` and a thought, a link or a to-do lands in this workspace's Inbox,
**Save to Margin** on a message's menu keeps that message
there with a link back, and the chosen channel hears about new cards, finished
cards and new notes through an ordinary webhook you can change or pause. The
app asks Slack only to add a command and post to one channel, so it reads no
channel, and one Slack workspace connects to one Margin workspace.

## GitHub

An owner or admin connects a repository from the GitHub card in
**Settings → Integrations**.
**Connect a repository** gives you a **Payload URL** and a
**Secret**, and the secret is shown only then. In the
repository on GitHub, open Settings, Webhooks, Add webhook, paste both, set the
content type to `application/json` and pick Pull requests and Issues.

To link a pull request or issue to a card, put the card's link (Copy link on
the card) in its description or title. The card gets a comment saying which
pull request or issue it is, once per link. When the pull request is merged,
the card moves to its board's done column and is marked complete. The done
column is the first whose name starts with Done, Shipped, Complete, Finished,
Merged or Closed, and otherwise the last column. Closing an issue does not move the card, because on a
public repository anyone can close one.

Only pull requests and issues opened by the repository's owner, its
organization's members or its collaborators do anything; one from anyone else
that names a card is ignored. Each delivery is acted on once, so redelivering
it from GitHub changes nothing. Slack and GitHub write as the person who
connected them, so they stop saving anything if that person leaves the
workspace or the plan no longer includes integrations; connect them again from
an account that is still there.

## Zapier, Make and n8n

None of the three has an app to install yet. Each one works through the two
general doors here: a webhook for events going out, and an API key for calls
coming in.

**Zapier.** Events: a **Webhooks by Zapier** Catch Hook trigger, its address
pasted into a new webhook here. Calls: a Webhooks by Zapier POST or GET
action with the header `Authorization: Bearer mk_...`.

**Make.** Events: add a Custom webhook module, copy its address into a new
webhook in **Settings → Webhooks and API** and pick the
events. Calls: an HTTP "Make a request" module with the same header.

**n8n.** Events: a Webhook node, its production URL pasted into a new webhook
here. Calls: an HTTP Request node with the same header. n8n's MCP client node
can also connect to the MCP server, with the Streamable HTTP transport and an
access token as the Authorization header, which gives it every tool an
assistant gets. See [Agents and MCP](https://themarginapp.com/docs/agents-and-mcp).

Make an API key on the **API Keys** tab of
**Settings → Webhooks and API** with the permissions you need
(Read, Write, Webhooks). It is shown once, so save it then. A key belongs to one workspace
and acts as the person who made it, so it stops working if that person leaves
the workspace or is held out by its two-factor rule. Its writes also stop once
the plan no longer includes integrations; reads keep working. What it can call:

| Call                                              | What it does                                                                                                                           |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/webhooks/actions/boards`                | boards and their columns                                                                                                               |
| `GET /api/webhooks/actions/cards?boardId=`        | cards on a board                                                                                                                       |
| `POST /api/webhooks/actions/cards`                | a card: `boardId`, `columnId`, `title`, optional `description`, `priority`, `dueDate`                                                  |
| `POST /api/webhooks/actions/notes`                | a note in the Inbox: `title` and/or `content` (markdown)                                                                               |
| `GET /api/webhooks/actions/shopping-items`        | the shopping lists                                                                                                                     |
| `POST /api/webhooks/actions/shopping-items`       | an item: `name` ("2 liters of milk" works), optional `quantity`, `listId`. Family plan; an item already on the list is not added twice |
| `POST /api/webhooks/subscribe` and `/unsubscribe` | REST hooks: `url` and `events` in, `webhookId` out                                                                                     |
| `GET /api/webhooks/poll?eventType=`               | recent events, newest first                                                                                                            |

All of them live under `https://themarginapp.com`. For anything wider than
this, connect an MCP client instead. See [Agents and MCP](https://themarginapp.com/docs/agents-and-mcp).

## Canva

A Canva design comes in as its pages and the words on them, kept in the
workspace beside your whiteboards, where you can lay its pages on a
whiteboard or share it. You keep editing it in Canva.

### Bring a design in

Press **Bring in a Canva design** in a whiteboard's top bar, **Bring in a
design** under **Canva designs** on the Whiteboards page, or **Bring in a
Canva handover** on a card to tie the design to that card. The dialog has up
to three tabs.

- **Upload a PDF or image** (the one it opens on, because it always works):
  download the design from Canva as a PDF or an image and drop it in, up to
  50 MB. Its pages and text are read in your browser, and every page comes
  across. This needs no Canva account connected.
- **Paste link**: paste a Canva share link. Without a connection that brings
  the cover and the title, and on a whiteboard nothing is placed on the canvas
  until the pages arrive (the dialog says so). With your Canva account
  connected, a link to one of your own designs brings every page.
- **Your Canva designs**: shown once you connect. Search your own designs,
  pick one, and press **Render from Canva**. Canva renders
  every page and they arrive in a moment.

### Connect your Canva account

Connecting is optional. In **Settings → Integrations**, the
Canva card has **Connect Canva**, which sends you to Canva to
approve. The Margin asks Canva only to read your designs; it never changes
one. **Disconnect** on the same card deletes the stored
access and ends it at Canva too.

### When a design goes

Deleting a design removes its rendered pages from storage along with it.
Deleting a workspace does the same for every design in it, and deleting your
account also ends your Canva connection at Canva. PDFs were never stored, so
there is nothing of them to remove.

### Work with a design

Open a design to see its pages beside what was read from them: its color
palette, its fonts and its text. From there:

- **Open in Canva** opens it in Canva's editor, or opens the
  link it came from.
- **Refresh from Canva** fetches the pages again after you
  have changed the design in Canva.
- **PDF** has Canva export the whole design as a PDF and opens
  it. The link Canva gives lasts about a day.
- **Embed on a board** places its pages on a whiteboard you
  pick, and **Share** shares it like any other item.

Refresh and PDF appear only while your account is connected and the design is
one Canva knows from that account.

The text read from a design also goes into the Mind, so asking Margin
Intelligence for "the poster that says spring fair" can find it.

> **On the phone:** On a phone in the browser, the whiteboard's **More whiteboard actions** menu
> has **Bring in a Canva design**, so a design can land on a whiteboard from
> your phone. The phone app lists Canva under
> **Settings → Connections**, and connecting the account
> happens on the web.

The Canva design hub is part of Pro, Family and Team. See
[Whiteboards and Canva](https://themarginapp.com/docs/whiteboards-and-canvases) for designs on
whiteboards.

## Calendar links and feeds

A calendar link is a private web address ending in `.ics` that any calendar app
can subscribe to. Make one for the whole household or for one person. Apple
Calendar opens it straight from **Open in Apple Calendar**. In Outlook, choose
**Add calendar**, then **Subscribe from web**, and paste the link. Repeating
events, time zones and all-day events arrive as they are in Margin. Calendar
apps check for changes on their own schedule, usually every few hours.

The link is read-only, and anyone who has it can read that calendar. Revoke it
from the same place and it stops working at once. Tasks are left out unless you
check **Include tasks** when you make the link.

Going the other way, paste the address of a published calendar and give it a
name and the people it is for. Its events show on the family calendar in their
colors, read-only, and refresh about once an hour. Remove it, and its events
go with it.

## Forwarding letters by email

Each family workspace can have a private address of the form
`family+…@themarginapp.com`. Forward a school's email to it, attachments
included, and the dates it finds wait under **Letters to review** on the
Calendar. Nothing is added until someone in the household confirms it. Make a
new address or turn it off from the Calendar's settings; the old one stops
working immediately. Reading a letter uses the household's AI actions and is
part of the Family plan.

## Availability

Calendar links and published calendars work on every plan.

> **Known limit: Pro and up** Google Calendar, Google Sheets, webhooks (Slack included), GitHub, the API
> keys Zapier, Make and n8n use, and the Canva design hub are part of Pro,
> Family and Team. Free does not include them. Connecting GitHub or Slack takes
> a workspace owner or admin.

Setting any of these up needs a connection. It is account configuration rather
than your content, so it is one of the few things that does not work offline.

**Where to next**

- [Agents and MCP](https://themarginapp.com/docs/agents-and-mcp): let an outside agent read and write your workspace
- [Plans and limits](https://themarginapp.com/docs/plans-and-limits): which plan turns each integration on
- [Planner, Today and Calendar](https://themarginapp.com/docs/planner-today-and-calendar): where due dates show up in the app


---

Section: Control and connections. Checked against the running product on October 5, 2026.
Web page: https://themarginapp.com/docs/integrations. Every docs page: https://themarginapp.com/docs/llms.txt
