Hooks

Overview

Hooks let Grain notify your server when something happens. Create one with a hook_type and a URL, and Grain sends a POST request to that URL whenever a matching event occurs.

Hook Types

Type Fires on include support
recording_added A recording was created Recording Include
recording_updated A recording was updated Recording Include
recording_deleted A recording was deleted N/A
highlight_added A highlight was created Highlight Include
highlight_updated A highlight was updated Highlight Include
highlight_deleted A highlight was deleted N/A
story_added A story was created N/A
story_updated A story was updated N/A
story_deleted A story was deleted N/A
upload_added An upload was created Upload Include
upload_updated An upload was updated Upload Include

The include field works the same as it does on List/Get endpoints, controlling what's present on data in the delivered payload. Its shape depends on the hook_type's resource (see above).

See Common Response Objects for the available fields.

Payload Examples

Every hook fires a POST to hook_url with the same envelope:

Field
type The hook_type that fired
user_id Id of the user the event belongs to
data The resource itself, shaped by include (see Hook Types)

Recording Added

{
  "type": "recording_added",
  "user_id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "data": {
    "id": "pppp6666-qq77-rr88-ss99-tttt00000000",
    "title": "All Hands",
    "source": "zoom",
    "share_state": "public",
    "url": "https://grain.com/share/recording/pppp6666-qq77-rr88-ss99-tttt00000000",
    "media_type": "video",
    "tags": [],
    "start_datetime": "2026-01-01T09:30:00Z",
    "teams": [
      {
        "id": "aaaa1111-bb22-cc33-dd44-eeee55555555",
        "name": "My Team"
      }
    ],
    "workspace_shared": false,
    "recorders": [
      {
        "id": "kkkk1111-ll22-mm33-nn44-oooo55555555",
        "name": "Luke Skywalker",
        "email": "luke@example.com"
      }
    ],
    "end_datetime": "2026-01-01T10:00:00Z",
    "duration_ms": 1800000,
    "thumbnail_url": "https://media.grain.com/public_thumbnails/recordings/pppp6666",
    "meeting_type": {
      "id": "ffff6666-gg77-hh88-ii99-jjjj00000000",
      "name": "Project & Team Coordination",
      "scope": "internal"
    }
  }
}

Recording Added (with Include)

Same event, but the hook was created with include: {"participants": true}.

{
  "type": "recording_added",
  "user_id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "data": {
    "id": "pppp6666-qq77-rr88-ss99-tttt00000000",
    "title": "All Hands",
    "source": "zoom",
    "share_state": "public",
    "url": "https://grain.com/share/recording/pppp6666-qq77-rr88-ss99-tttt00000000",
    "media_type": "video",
    "tags": [],
    "start_datetime": "2026-01-01T09:30:00Z",
    "teams": [
      {
        "id": "aaaa1111-bb22-cc33-dd44-eeee55555555",
        "name": "My Team"
      }
    ],
    "workspace_shared": false,
    "recorders": [
      {
        "id": "kkkk1111-ll22-mm33-nn44-oooo55555555",
        "name": "Luke Skywalker",
        "email": "luke@example.com"
      }
    ],
    "participants": [
      {
        "id": "eeee1111-ff22-gg33-hh44-iiii55555555",
        "name": "Luke Skywalker",
        "scope": "internal",
        "email": "luke@example.com",
        "confirmed_attendee": true
      },
      {
        "id": "jjjj6666-kk77-ll88-mm99-nnnn00000000",
        "name": "Han Solo",
        "scope": "internal",
        "email": "solo@example.com",
        "confirmed_attendee": false
      }
    ],
    "end_datetime": "2026-01-01T10:00:00Z",
    "duration_ms": 1800000,
    "thumbnail_url": "https://media.grain.com/public_thumbnails/recordings/pppp6666",
    "meeting_type": {
      "id": "ffff6666-gg77-hh88-ii99-jjjj00000000",
      "name": "Project & Team Coordination",
      "scope": "internal"
    }
  }
}

Recording Deleted

_deleted hook types have no include support. data is always just the deleted resource's id.

{
  "type": "recording_deleted",
  "user_id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "data": {
    "id": "pppp6666-qq77-rr88-ss99-tttt00000000"
  }
}