Endpoints

API Domain is: https://api.grain.com

OAuth2

Generate Token

Endpoint

POST /_/public-api/oauth2/token

Params

Param
client_id Obtained separately in Step 1 of the OAuth Flow
client_secret Obtained separately in Step 1 of the OAuth Flow
* Required for server-side applications
grant_type Must be authorization_code
code String obtained in Step 4 of the OAuth Flow
code_verifier String sent as code_challenge in Step 2 of the OAuth Flow

Response

Field
token_type Always bearer
access_token Token to be used in the Authorization header
refresh_token Token to be used to refresh the access_token. (See Refresh Token)
expires_in Denotes how many seconds the access_token will live for after its generation.

NOTE: Some legacy clients do not return refresh_token nor expires_in.
For these cases the access_token does not expire.

Example Request

curl -X POST \
  -H 'Content-Type: application/json' \
  --data '{"grant_type": "authorization_code", "code": "CODE", "client_id": "CLIENT_ID", "client_secret": "CLIENT_SECRET"}' \
  https://api.grain.com/_/public-api/oauth2/token

Example Response

{
  "token_type": "bearer",
  "access_token": "aaaaa33333EEEEENNNNNoooooKKKKK33333lllll",
  "refresh_token": "IIIIIQQQQQxxxxx4444422222CCCCCoooooWWWWW",
  "expires_in": 3600
}

Refresh Token

Endpoint

POST /_/public-api/oauth2/token

Params

Param
client_id Obtained separately in Step 1 of the OAuth Flow
client_secret Obtained separately in Step 1 of the OAuth Flow
* Required for server-side applications
grant_type Must be refresh_token
refresh_token Obtained when generating or refreshing an access_token

Response

Field
token_type Always bearer
access_token Token to be used in the Authorization header
refresh_token Token to be used to re-refresh the access_token
expires_in Denotes how many seconds the access_token will live for after its generation.

Example Request

curl -X POST \
  -H 'Content-Type: application/json' \
  --data '{"grant_type": "refresh_token", "refresh_token": "IIIIIQQQQQxxxxx4444422222CCCCCoooooWWWWW", "client_id": "CLIENT_ID", "client_secret": "CLIENT_SECRET"}' \
  https://api.grain.com/_/public-api/oauth2/token

Example Response

{
  "token_type": "bearer",
  "access_token": "bbbbb44444FFFFFOOOOOpppppLLLLL44444mmmmm",
  "refresh_token": "JJJJJRRRRRyyyyy5555533333DDDDDpppppXXXXX",
  "expires_in": 3600
}

Recordings

List Recordings

Endpoint

POST /_/public-api/v2/recordings

Params

Param Type
cursor string Used to paginate through the list.
filter object Recording Filter
include object Recording Include

Response

Field Type
cursor string
*nullable
Can be sent as a param to retrieve the next page of the list
recordings object array List of Recordings

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"filter": {"title_search": "hands"}, "include": {"participants": true}}' \
  https://api.grain.com/_/public-api/v2/recordings

Example Response

{
  "cursor": "ApJNWoNoBHcCdjJ3DWNocm9ub2xvZ2ljYWx3BGRlc2NoAm4HAO5FaSm2QgZuBwAVPC0qtkIG",
  "recordings": [
    {
      "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",
          "participant_id": "eeee1111-ff22-gg33-hh44-iiii55555555"
        }
      ],
      "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"
      }
    }
  ]
}

Get Recording

Endpoint

POST /_/public-api/v2/recordings/:recording_id

Params

Param Type
include object Recording Include

Response

Field Type
Recording object

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"include": {"participants": true, "calendar_event": true}}' \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000

Example Response

{
  "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",
      "participant_id": "eeee1111-ff22-gg33-hh44-iiii55555555"
    }
  ],
  "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"
  },
  "calendar_event": {
    "ical_uid": "meeting-abc123",
    "scheduled_start_datetime": "2026-01-01T09:00:00Z",
    "scheduled_end_datetime": "2026-01-01T10:00:00Z"
  }
}

Get Recording Transcript (json)

Endpoint

GET /_/public-api/v2/recordings/:recording_id/transcript

Params

N/A

Response

Field Type
participant_id UUID string
*nullable
id of the participant
speaker string Name of the participant
start integer Timestamp in ms from the recording of when this section started.
end integer Timestamp in ms from the recording of when this section ended.
text string Text of this transcript section.

Example Request

curl \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/transcript

Example Response

[
  {
    "start": 8000,
    "text": "Hello there.",
    "end": 9000,
    "speaker": "Obi Wan Kenobi",
    "participant_id": "oooo1111-pp22-qq33-rr44-ssss55555555"
  },
  {
    "start": 11482,
    "text": "General Kenobi...",
    "end": 13000,
    "speaker": "General Grievous",
    "participant_id": "yyyy1111-zz22-aabb-cc44-dddd55555555"
  }
]

Get Recording Transcript (text formats)

Endpoint

GET /_/public-api/v2/recordings/:recording_id/transcript.txt
GET /_/public-api/v2/recordings/:recording_id/transcript.vtt
GET /_/public-api/v2/recordings/:recording_id/transcript.srt

Params

N/A

Response

Transcript text

Example Request

curl \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/transcript.txt

Example Response

Obi Wan Kenobi: Hello there.
General Grievous: General Kenobi...

Download Recording

Endpoint

GET /_/public-api/v2/recordings/:recording_id/download

Params

N/A

Response

Recording file

Example Request

curl \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  -L --output recording.mp4 \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/download

Example Response

Recording file

Update Recording

Endpoint

PATCH /_/public-api/v2/recordings/:recording_id

Params

Param Type
title string New title for the recording

Response

Field Type
success Always true

Example Request

curl -X PATCH \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"title": "A new title"}' \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000

Example Response

{
  "success": true
}

Add a Tag to a Recording

Endpoint

PUT /_/public-api/v2/recordings/:recording_id/tags

Params

Param Type
tag Regex checked string

format: (Regex101)
/^[\p{L}\d][\p{L}\d-]*$/u
Tag to be added to the recording

(Letters and numbers separated by dashes - )

Response

Field Type
success Always true

Example Request

curl -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"tag": "my-new-tag"}' \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/tags

Example Response

{
  "success": true
}

Remove a Tag from a Recording

Endpoint

DELETE /_/public-api/v2/recordings/:recording_id/tags/:tag

Params

N/A

Response

Field Type
success Always true

Example Request

curl -X DELETE \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/tags/my-new-tag

Example Response

{
  "success": true
}

Share Recording to a User

Endpoint

PUT /_/public-api/v2/recordings/:recording_id/users

Params

Param Type
user_id UUID string User to share the recording with.
Obtained through List Users

Response

Field Type
success Always true

Example Request

curl -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"user_id": "7890-abcd-ef01-2222-3456-7890ffff"}' \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/users

Example Response

{
  "success": true
}

Unshare Recording from a User

Endpoint

DELETE /_/public-api/v2/recordings/:recording_id/users/:user_id

Params

N/A

Response

Field Type
success Always true

Example Request

curl -X DELETE \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/users/7890-abcd-ef01-2222-3456-7890ffff

Example Response

{
  "success": true
}

Share Recording to a Team

Endpoint

PUT /_/public-api/v2/recordings/:recording_id/teams

Params

Param Type
team_id UUID string Team to share the recording with.
Obtained through List Teams

Response

Field Type
success Always true

Example Request

curl -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"team_id": "aaaa1111-bb22-cc33-dd44-eeee55555555"}' \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/teams

Example Response

{
  "success": true
}

Unshare Recording from a Team

Endpoint

DELETE /_/public-api/v2/recordings/:recording_id/teams/:team_id

Params

N/A

Response

Field Type
success Always true

Example Request

curl -X DELETE \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/recordings/pppp6666-qq77-rr88-ss99-tttt00000000/teams/aaaa1111-bb22-cc33-dd44-eeee55555555

Example Response

{
  "success": true
}

Uploads

Create Upload

Creates an upload for the given media_type, which becomes a recording.
See the Uploads page for details and examples.

Endpoint

POST /_/public-api/v2/uploads/create

Params

Param Type
media_type
required
One of:
- video
- audio
- transcript
Media type of the upload
auto_promote boolean Whether the upload continues to promoting or stays in staged.

Defaults to true
include object Upload Include
attributes
required for transcript
object Upload Attributes Input

Response

Field Type
Upload object

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"media_type": "video", "auto_promote": false}' \
  https://api.grain.com/_/public-api/v2/uploads/create

Example Response

{
  "id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "media_type": "video",
  "title": "Recording Upload 2026-01-01 09:30",
  "status": "awaiting",
  "auto_promote": false,
  "recording_id": null,
  "created_datetime": "2026-01-01T09:30:00Z",
  "updated_datetime": "2026-01-01T09:30:00Z",
  "media": {
    "status": "awaiting",
    "upload": {
      "url": "https://example.com/generated_url",
      "expires_at": "2026-01-02T09:30:00Z",
      "headers": {
        "If-None-Match": "*"
      },
      "max_duration_sec": 10800,
      "max_upload_bytes": 4294967296
    }
  }
}

List Uploads

Endpoint

POST /_/public-api/v2/uploads

Params

Param Type
cursor string Cursor obtained from a previous List Uploads response, for pagination
include object Upload Include
filter object Upload Filter

Response

Field Type
uploads object array List of Uploads
cursor string
*nullable
Pass to the next List Uploads call to get the next page

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"filter": {"media_type": "video"}}' \
  https://api.grain.com/_/public-api/v2/uploads

Example Response

{
  "uploads": [
    {
      "id": "eeee1111-ff22-gg33-hh44-iiii55555555",
      "media_type": "video",
      "title": "All Hands (corrected)",
      "status": "success",
      "auto_promote": false,
      "recording_id": "pppp6666-qq77-rr88-ss99-tttt00000000",
      "created_datetime": "2026-01-01T09:30:00Z",
      "updated_datetime": "2026-01-01T09:42:00Z"
    }
  ],
  "cursor": null
}

Get Upload

Endpoint

POST /_/public-api/v2/uploads/:upload_id

Params

Param Type
include object Upload Include

Response

Field Type
Upload object

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/uploads/eeee1111-ff22-gg33-hh44-iiii55555555

Example Response

{
  "id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "media_type": "video",
  "title": "Recording Upload 2026-01-01 09:30",
  "status": "staged",
  "auto_promote": false,
  "recording_id": null,
  "created_datetime": "2026-01-01T09:30:00Z",
  "updated_datetime": "2026-01-01T09:35:00Z",
  "media": {
    "status": "uploaded",
    "expires_at": "2026-01-08T09:35:00Z"
  }
}

Update Upload

Updates the attributes of an upload whose status is awaiting or staged with auto_promote: false.

Endpoint

PATCH /_/public-api/v2/uploads/:upload_id

Params

Param Type
include object Upload Include
attributes object Upload Attributes Input

Response

Field Type
Upload object

Example Request

curl -X PATCH \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"attributes": {"title": "All Hands (corrected)"}}' \
  https://api.grain.com/_/public-api/v2/uploads/eeee1111-ff22-gg33-hh44-iiii55555555

Example Response

{
  "id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "media_type": "video",
  "title": "All Hands (corrected)",
  "status": "staged",
  "auto_promote": false,
  "recording_id": null,
  "created_datetime": "2026-01-01T09:30:00Z",
  "updated_datetime": "2026-01-01T09:40:00Z"
}

Promote Upload

Manually starts promoting a staged upload that was created with auto_promote: false.
See the Uploads page.

Endpoint

POST /_/public-api/v2/uploads/:upload_id/promote

Params

Param Type
include object Upload Include

Response

Field Type
Upload object

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/uploads/eeee1111-ff22-gg33-hh44-iiii55555555/promote

Example Response

{
  "id": "eeee1111-ff22-gg33-hh44-iiii55555555",
  "media_type": "video",
  "title": "All Hands (corrected)",
  "status": "promoting",
  "auto_promote": false,
  "recording_id": null,
  "created_datetime": "2026-01-01T09:30:00Z",
  "updated_datetime": "2026-01-01T09:41:00Z"
}

Hooks

Create Hook

Creates a hook to be notified of a hook_type event.
See the Hooks page for hook types and the delivered payload shape.

Endpoint

POST /_/public-api/v2/hooks/create

Params

Param Type
hook_url
required
string
Secure (https://) URL
Endpoint to be called when the event is triggered.
hook_type
required
One of Hook Types Type of notifications the hook will be sent.
include object See Hook Types for include support per hook_type

NOTE: A POST reachability test is made to hook_url on creation.
It must respond with a 2xx status, or the hook won't be created.

Response

Field Type
Hook object

Example Request

curl \
  -X POST \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -H "Public-Api-Version: 2026-10-01" \
  --data '{"hook_type": "recording_added", "hook_url": "https://example.com/hook"}' \
  https://api.grain.com/_/public-api/v2/hooks/create

Example Response

{
  "enabled": true,
  "id": "zzzz6666-aa77-bb88-cc99-dddd00000000",
  "include": {},
  "inserted_at": "2026-01-01T09:30:00Z",
  "hook_url": "https://example.com/hook",
  "hook_type": "recording_added"
}

List Hooks

Endpoint

POST /_/public-api/v2/hooks

Params

Param Type
filter object Hook Filter

Response

Field Type
hooks object array List of Hooks

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/hooks

Example Response

{
  "hooks": [
    {
      "enabled": true,
      "id": "zzzz6666-aa77-bb88-cc99-dddd00000000",
      "include": {},
      "inserted_at": "2026-01-01T09:30:00Z",
      "hook_url": "https://example.com/hook",
      "hook_type": "recording_added"
    }
  ]
}

Delete Hook

Endpoint

DELETE /_/public-api/v2/hooks/:hook_id

Params

N/A

Response

Field Type
success Always true

Example Request

curl -X DELETE \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/hooks/zzzz6666-aa77-bb88-cc99-dddd00000000

Example Response

{
  "success": true
}

Others

Token Info

Endpoint

GET /_/public-api/v2/token-info

Params

N/A

Response

Field Type
type One of:
- oauth
- personal_access_token
- workspace_access_token
Type of token used to authenticate.
See Token Types
scope One of:
- personal
- workspace
Scope of the token.
See Token Types
user_id
scope: personal
UUID string Id of the token's owner
workspace_id
scope: workspace
UUID string Id of the token's owning workspace
name string Name of the user or workspace
expires_at ISO8601 formatted timestamp
2026-01-01T09:30:00Z
*nullable
UTC datetime the token expires.
null indicates the token doesn't expire

Example Request

curl -X GET \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/token-info

Example Response

{
  "type": "personal_access_token",
  "scope": "personal",
  "user_id": "7890-abcd-ef01-2222-3456-7890ffff",
  "name": "Luke Skywalker",
  "expires_at": null
}

List Users

Endpoint

POST /_/public-api/v2/users

Params

N/A

Response

Field Type
users object array List of Users

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/users

Example Response

{
  "users": [
    {
      "id": "7890-abcd-ef01-2222-3456-7890ffff",
      "name": "Luke Skywalker",
      "email": "luke@example.com"
    }
  ]
}

List Teams

Endpoint

POST /_/public-api/v2/teams

Params

N/A

Response

Field Type
teams object array List of Teams

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/teams

Example Response

{
  "teams": [
    {
      "id": "aaaa1111-bb22-cc33-dd44-eeee55555555",
      "name": "My Team"
    }
  ]
}

List Meeting Types

Endpoint

POST /_/public-api/v2/meeting_types

Params

N/A

Response

Field Type
meeting_types object array List of Meeting Types

Example Request

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -H "Public-Api-Version: 2026-10-01" \
  https://api.grain.com/_/public-api/v2/meeting_types

Example Response

{
  "meeting_types": [
    {
      "id": "aaaa1111-bb22-cc33-dd44-eeee55555555",
      "name": "Sales",
      "scope": "external"
    },
    {
      "id": "ffff6666-gg77-hh88-ii99-jjjj00000000",
      "name": "Project & Team Coordination",
      "scope": "internal"
    }
  ]
}

Common Request Objects

Recording Filter

This object is used to filter for specific recordings.

Param Type
before_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
Only return recordings which start_datetime is after the selected date (exclusive)
after_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
Only return recordings which start_datetime is before the selected date (inclusive)
attendance
only for
personal scope
One of:
- hosted
- attended
hosted
Only return recordings where the user was the meeting host.

attended
Only return recordings where the user attended the meeting.
participant_scope One of:
- internal
- external
internal
Only return recordings of internal / team meetings.

external
Only return recordings of external / customer meetings.
title_search string Only return recordings which title matches the given search string.
team uuid Only return recordings which team matches the given team id.

Team ids can be found through the List Teams endpoint.
meeting_type uuid Only return recordings which meeting type matches the given meeting type id.

Meeting type ids can be found through the List Meeting Types endpoint.

Recording Include

Param Type
highlights boolean Include clips / highlights in the response
participants boolean Include participants in the response
ai_action_items boolean Include the ai_action_items in the response
ai_summary boolean Include the ai_summary in the response
private_notes
only for
personal scope
boolean Include your private notes in the response
calendar_event boolean Include calendar event data in the response
hubspot boolean Include HubSpot related data in the response
screenshares boolean Include screenshare ranges in the response
ai_template_sections object Includes ai_template_sections in the response
ai_template_sections
format
One of:
- json
- markdown
- text
Controls the output of ai_template_sections

Defaults to json
ai_template_sections
allowed_sections
string array Only include sections which title matches the given allowed_sections

Case insensitive

Highlight Include

Param Type
transcript boolean Include the highlight's transcript in the response
speakers boolean Include the highlight's speakers in the response

Hook Filter

Param Type
hook_type One of Hook Types Only return hooks with the matching hook_type
state One of:
- enabled
- disabled
Only return hooks that are either enabled or disabled.

Upload Attributes Input

All attributes are optional for an upload unless stated otherwise.

Param Type
title string Title for the recording and upload
start_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
When the recording took place. Cannot be in the future.
team_id uuid Team to attach the resulting recording to.

Team ids can be found through the List Teams endpoint.
recorder_ids
required for workspace scope
uuid array Users to credit as recorders.

User ids can be found through the List Users endpoint.
participants object array A participant must have at least one of name, email or phone.
participants
name
string Name of the participant
participants
email
string Email of the participant
participants
phone
string Phone number of the participant
participants
speaker_key
string Used to match a participant to the speaker_key in transcript.segments
transcript
required for transcript
object Transcript for the recording
transcript
language
string Language code, e.g. en
transcript
segments
object array
transcript
segments
speaker_key
string Used to match to a participants entry. An anonymous speaker will be made if none matches
transcript
segments
start
integer Segment start, in ms from the recording start
transcript
segments
end
integer Segment end, in ms from the recording start
transcript
segments
text
string Segment text

Upload Include

Param Type
attributes boolean Include the attributes in the response, save for the transcript
transcript boolean Include the transcript in the response

Upload Filter

Param Type
media_type One of:
- video
- audio
- transcript
Only return uploads with the matching media_type

Common Response Objects

Recording

Field Type
id UUID string Id of the recording
title string Title of the recording
start_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
UTC datetime at which grain started the recording
end_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
UTC datetime at which the recording ended
duration_ms integer Duration of the recording in ms
media_type One of:
- video
- audio
- transcript
Media type of the recording
source One of:
- aircall
- local_capture
- meet
- teams
- upload
- webex
- zoom
- other
From what source did Grain get the recording
share_state One of:
- public
- workspace
- restricted
public
Anyone with the link
workspace
All workspace members
restricted
Only people with access
url string URL to the recording in Grain
thumbnail_url string
*nullable
URL to the recording's thumbnail
highlights object array List of Highlights
tags string array Tags of the recording
teams object array List of Teams the recording belongs to.
workspace_shared boolean Whether the recording is shared with the whole workspace
recorders object array List of users that recorded the meeting
recorders
id
UUID string User id of the recorder
recorders
name
string Name of the recorder
recorders
email
string Email of the recorder
recorders
participant_id
include: participants
UUID string
*nullable
Participant id of the recorder
meeting_type object
*nullable
Recording's Meeting Type
ai_template_sections
include: ai_template_sections
object array List of AI Template Sections
ai_action_items
include: ai_action_items
object array List of Action Items
ai_action_items
status
One of:
- pending
- completed
Status of the action item
ai_action_items
timestamp
integer Observed timestamp in ms at which the action item was mentioned
ai_action_items
text
string Content of the action item
ai_action_items
assignee
object
*nullable
Assignee of the action item
ai_action_items
assignee
id
UUID string Id of the assignee
ai_action_items
assignee
name
string Name of the assignee
ai_action_items
assignee
user_id
UUID string
*nullable
User id of the assignee
ai_summary
include: ai_summary
object
ai_summary
text
markdown formatted string Markdown text of the ai summary
calendar_event
include: calendar_event
object
*nullable
calendar_event
ical_uid
string
*nullable
Ical UID of the related event
calendar_event
scheduled_start_datetime
ISO8601 formatted timestamp
2026-01-01T09:00:00Z
*nullable
UTC datetime of the scheduled calendar event start time
calendar_event
scheduled_end_datetime
ISO8601 formatted timestamp
2026-01-01T10:00:00Z
*nullable
UTC datetime of the scheduled calendar event end time
hubspot
include: hubspot
object
hubspot
hubspot_company_ids
string array List of HubSpot company ids related to the recording
hubspot
hubspot_deal_ids
string array List of HubSpot deal ids related to the recording
participants
include: participants
object array
participants
id
UUID string id of the participant
participants
name
string Name of the participant
participants
email
string
*nullable
Email of the participant
participants
scope
One of:
- internal
- external
- unknown
Scope of the participant
participants
confirmed_attendee
boolean Whether or not the participant was present in the recording
participants
hs_contact_id
include: hubspot
string
*nullable
HubSpot contact id of the participant
participants
observed_join_time
ISO8601 formatted timestamp
2026-01-01T09:30:00Z
*nullable
UTC datetime the participant was observed joining the meeting.

Note: This is based on what Grain's recorder observed and may not reflect the participant's actual join time.
participants
observed_leave_time
ISO8601 formatted timestamp
2026-01-01T10:00:00Z
*nullable
UTC datetime the participant was observed leaving the meeting.

Note: This is based on what Grain's recorder observed and may not reflect the participant's actual leave time.
private_notes
include: private_notes
object
*nullable
private_notes
text
string Markdown text of the user's private notes
screenshares
include: screenshares
object array List of screenshare ranges
screenshares
start
integer Timestamp in ms from the recording of when the screenshare range started
screenshares
end
integer Timestamp in ms from the recording of when the screenshare range ended
screenshares
participant_id
UUID string Id of the participant that was screensharing

AI Template Sections

Field Type
title string Title of the section
data object Fields depend on the type of section.

Highlight (aka Clip)

Field Type
id UUID string id of the highlight
recording_id UUID string id of the recording it was clipped from
text string Small description of the clip, equivalent to a title
transcript string Transcript of the clip formatted as text
speakers string array Names of the speakers of the clip
timestamp integer Timestamp in ms from the recording of when the clip starts
duration integer Duration of the clip in ms
tags string array Tags of the clip
url string URL to the highlight in Grain
thumbnail_url string URL to the highlight's thumbnail
created_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
UTC datetime of when the clip was created

Upload

Field Type
id UUID string Id of the upload
media_type One of:
- video
- audio
- transcript
Media type of the upload
title string Title of the recording and upload
status One of Upload Statuses Status of the upload
auto_promote boolean Whether the upload stops in staged or continues to promoting
recording_id UUID string
*nullable
Id of the resulting recording. Only set once status is success.
created_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
UTC datetime the upload was created
updated_datetime ISO8601 formatted timestamp
2026-01-01T09:30:00Z
UTC datetime the upload was last updated
attributes
include: attributes
include: transcript
object Upload Attributes
media object
*optional
See Upload Media
failure
status: failure
object Present only while status is failure
failure
reason
string Human-readable description of what went wrong

Upload Attributes

Field Type
title string Title of the recording and upload
start_datetime
include: attributes
ISO8601 formatted timestamp
2026-01-01T09:30:00Z
*nullable
When the recording took place
team_id
include: attributes
uuid
*nullable
Team the resulting recording is attached to
recorder_ids
include: attributes
uuid array Users credited as recorders
participants
include: attributes
object array
participants
name
string
*nullable
Name of the participant
participants
email
string
*nullable
Email of the participant
participants
phone
string
*nullable
Phone number of the participant
participants
speaker_key
string
*nullable
Matches a transcript.segments entry to this participant
transcript
include: transcript
object
transcript
language
string Language code, e.g. en
transcript
segments
object array
transcript
segments
speaker_key
string Matches a participants entry, or an Unmatched Speaker if none matches
transcript
segments
start
integer Segment start, in ms from the recording start
transcript
segments
end
integer Segment end, in ms from the recording start
transcript
segments
text
string Segment text
transcript
anonymous_speakers
object array Auto-generated for segment speaker_keys with no matching participant. See Unmatched Speaker
transcript
anonymous_speakers
speaker_key
string The unmatched speaker_key this entry was generated for
transcript
anonymous_speakers
name
string e.g. Unknown Speaker 1

Upload Media

The media object takes a different shape depending on the upload's status, and is always absent on transcript uploads. For any status not listed below, media is absent entirely.

Status: awaiting

Field Type
status One of:
- awaiting
- url_expired
Status of the upload url
upload object Info for uploading the file
upload
url
string URL to PUT the file to
upload
expires_at
ISO8601 formatted timestamp
2026-01-01T09:30:00Z
When the url expires
upload
headers
object Headers required on the PUT request
upload
max_duration_sec
integer Max duration in seconds the upload can be
upload
max_upload_bytes
integer Max size in bytes the upload can be

Status: processing

Field Type
status Always processing

Status: staged

Field Type
status One of:
- uploaded
- media_expired
Status of the uploaded file
expires_at ISO8601 formatted timestamp
2026-01-01T09:30:00Z
When the uploaded file expires

Hook

Field Type
id UUID string id of the hook
enabled boolean Whether the hook is enabled or not
hook_url string URL to which Grain will post to
hook_type One of Hook Types Type of notifications the hook will be sent.
include object The include the hook was created with.
Always an empty object for hook_types with no include support (See Hook Types)
inserted_at ISO8601 formatted timestamp
2026-01-01T09:30:00Z
UTC datetime of when the hook was created

User

Field Type
id UUID string id of the user
name string Name of the user
email string Primary email of the user

Team

Field Type
id UUID string id of the team
name string Name of the team

Meeting Type

Field Type
id UUID string id of the meeting type
name string Name of the meeting type
scope One of:
- internal
- external
Scope of the meeting type