ReferenceReference by module

Meetings API

Every Meetings action (33) and data model (4): endpoints, scopes, input, preconditions, events and examples.

Era joins your meetings — with a notetaker bot or botless from your computer — briefs you before, and after writes the notes, tasks, follow-up email and next steps.

Module code meetings · 33 actions · 4 data models · 16 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: meetings (everything), meetings:read (read only) or meetings:<capability>.

Resources

ResourceTableList and readPOSTPATCHDELETE
meeting_action_itemsmeeting_action_item/api/v1/meeting_action_items
meeting_calendarsmeeting_calendar/api/v1/meeting_calendars
meeting_speaker_aliasesmeeting_speaker_alias/api/v1/meeting_speaker_aliases
meetingsmeeting/api/v1/meetingsmeetings.updatemeetings.delete

Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.

Actions

ActionNeedsWhat it does
meetings.accept_action_itemmeetings:writeTurn an action item into a task
meetings.accept_next_meetingmeetings:writeBook the suggested next meeting
meetings.accept_stagemeetings:writeMove the deal to the suggested stage
meetings.add_action_itemmeetings:writeAdd an action item to a meeting
meetings.approve_follow_upmeetings:writeApprove and send the follow-up email
meetings.connect_calendarmeetings:writeConnect a calendar to meetings
meetings.deletemeetings:deleteDelete a meeting
meetings.discard_follow_upmeetings:writeDiscard the follow-up email
meetings.disconnect_calendarmeetings:writeDisconnect a meeting calendar
meetings.dismiss_action_itemmeetings:writeDismiss an action item
meetings.dismiss_suggestionmeetings:writeDismiss a suggestion
meetings.edit_follow_upmeetings:writeEdit the follow-up email
meetings.expire_audiomeetings:writeDelete a meeting’s recording
meetings.failmeetings:handleA meeting could not be processed
meetings.file_notesmeetings:handleFile a meeting’s notes
meetings.file_transcriptmeetings:handleFile a meeting’s transcript
meetings.forget_speakermeetings:writeForget a remembered speaker name
meetings.link_invitemeetings:handleRecord the calendar invite
meetings.link_taskmeetings:handleLink an action item to its task
meetings.mark_follow_up_sentmeetings:handleRecord the follow-up’s delivery
meetings.record_capturemeetings:handleNote how a recording is going
meetings.record_on_desktopmeetings:writeRecord a meeting on my computer
meetings.rename_speakermeetings:writeSay who a speaker is
meetings.save_briefmeetings:handleSave a meeting brief
meetings.schedulemeetings:writeAdd a meeting
meetings.send_botmeetings:writeSend Era’s notetaker to a meeting
meetings.send_invitemeetings:writeSend the calendar invite
meetings.set_sharingmeetings:writeChoose who sees a meeting
meetings.skipmeetings:writeDon’t record a meeting
meetings.sync_calendarmeetings:handleRead a calendar’s meetings
meetings.updatemeetings:writeChange a meeting
meetings.update_action_itemmeetings:writeChange an action item
meetings.update_calendarmeetings:writeChange a meeting calendar

meetings.accept_action_item

Turn an action item into a task — The commitment becomes a task for its owner (or you), with its due date, linked to the deal or customer.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meeting_action_items/{id}/actions/accept_action_item
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.accept_action_item

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Action item · id of meeting_action_item
assigneeUserIduuidWho · id of app_user
dueAtdate-timeBy when

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
item_not_foundThe item must exist here.
item_closedAn item becomes a task once.
not_memberA task goes to a member.

Events it publishes: meetings.action_item_accepted

What it writes: meeting_action_item (update) — proposed → accepted (the task follows)

curl -X POST https://app.getera.io/api/v1/meeting_action_items/MEETING_ACTION_ITEM_ID/actions/accept_action_item \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"assigneeUserId":"APP_USER_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.action_item_accepted"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingActionItems.acceptActionItem("MEETING_ACTION_ITEM_ID", {
  assigneeUserId: "APP_USER_ID"
})
era meeting_action_items accept_action_item MEETING_ACTION_ITEM_ID \
  --assignee-user-id "APP_USER_ID"
tools/call
{
  "name": "era__meetings__accept_action_item",
  "arguments": {
    "id": "MEETING_ACTION_ITEM_ID",
    "assigneeUserId": "APP_USER_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 item_not_found, item_closed, not_member · 429 slow down

meetings.accept_next_meeting

Book the suggested next meeting — Adds the next meeting Era heard agreed — same people, same deal — so Era joins and prepares for it too.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/accept_next_meeting
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.accept_next_meeting

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
startsAtdate-timeWhen
titlestringName · max 300
joinUrlstringMeeting link · max 2000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_suggestionThere must be a suggestion.
suggestion_closedA suggestion is answered once.
bad_timeThe next meeting needs a time.
bad_join_urlA link must be an https address.

Events it publishes: meetings.scheduled, meetings.next_meeting_booked

What it writes: meeting (insert) — Writes the next meeting; meeting (update) — suggestion → accepted

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/accept_next_meeting \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"startsAt":"2026-11-02T09:00:00Z"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.scheduled",
    "meetings.next_meeting_booked"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.acceptNextMeeting("MEETING_ID", {
  startsAt: "2026-11-02T09:00:00Z"
})
era meetings accept_next_meeting MEETING_ID \
  --starts-at "2026-11-02T09:00:00Z"
tools/call
{
  "name": "era__meetings__accept_next_meeting",
  "arguments": {
    "id": "MEETING_ID",
    "startsAt": "2026-11-02T09:00:00Z"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_suggestion, suggestion_closed, bad_time, bad_join_url · 429 slow down

meetings.accept_stage

Move the deal to the suggested stage — Era read the meeting and suggests the deal’s next stage; this moves it.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/accept_stage
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.accept_stage

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_suggestionThere must be a suggestion.
suggestion_closedA suggestion is answered once.

Events it publishes: meetings.stage_accepted

What it writes: meeting (update) — suggestion → accepted (the stage change follows)

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/accept_stage \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.stage_accepted"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.acceptStage("MEETING_ID")
era meetings accept_stage MEETING_ID
tools/call
{
  "name": "era__meetings__accept_stage",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_suggestion, suggestion_closed · 429 slow down

meetings.add_action_item

Add an action item to a meeting — Something Era missed — who does what, by when.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meeting_action_items/actions/add_action_item
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.add_action_item

Input

FieldTypeRequiredNotes
meetingIduuidyesMeeting · id of meeting
textstringyesWhat · max 1000
assigneeUserIduuidWho · id of app_user
dueAtdate-timeBy when

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
empty_textAn item says what to do.
not_memberThe owner must be a member.

Events it publishes: meetings.action_item_created

What it writes: meeting_action_item (insert) — Writes the item (proposed)

curl -X POST https://app.getera.io/api/v1/meeting_action_items/actions/add_action_item \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"meetingId":"MEETING_ID","text":"What"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.action_item_created"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingActionItems.addActionItem({
  meetingId: "MEETING_ID",
  text: "What"
})
era meeting_action_items add_action_item \
  --meeting-id "MEETING_ID" \
  --text "What"
tools/call
{
  "name": "era__meetings__add_action_item",
  "arguments": {
    "meetingId": "MEETING_ID",
    "text": "What"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, empty_text, not_member · 429 slow down

meetings.approve_follow_up

Approve and send the follow-up email — The email Era drafted goes out from your own Gmail or Outlook when you connected one (as you), otherwise from your business’s sender.

Needs meetings:write · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/approve_follow_up
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.approve_follow_up

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_follow_upThere must be a draft.
follow_up_closedAn email is sent once.
invalid_recipientIt needs a recipient.
send_from_unusableA chosen mailbox must be usable by the approver.

Events it publishes: meetings.follow_up_approved

What it writes: meeting (update) — draft → approved (the send follows)

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/approve_follow_up \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.follow_up_approved"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.approveFollowUp("MEETING_ID")
era meetings approve_follow_up MEETING_ID
tools/call
{
  "name": "era__meetings__approve_follow_up",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_follow_up, follow_up_closed, invalid_recipient, send_from_unusable · 429 slow down

meetings.connect_calendar

Connect a calendar to meetings — Era reads your Google or Outlook calendar, prepares a brief for each meeting and joins the ones your rule picks.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meeting_calendars/actions/connect_calendar
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.connect_calendar

Input

FieldTypeRequiredNotes
providerstring (enum)yesCalendar · Allowed values: google, microsoft
credentialIdstringyesConnected account · max 200
calendarIdstringCalendar id · max 300
labelstringName · max 120
accountEmailstringAccount · max 320
joinRulestring (enum)Era joins · Allowed values: all, external, organised, off
captureModestring (enum)How · Allowed values: auto, bot, desktop
knowledgeBaseIduuidNotes go to

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
calendar_connectedA calendar is connected once per person.

Events it publishes: meetings.calendar_connected

What it writes: meeting_calendar (insert) — Writes the calendar and its rule

curl -X POST https://app.getera.io/api/v1/meeting_calendars/actions/connect_calendar \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"provider":"google","credentialId":"Connected account"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.calendar_connected"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingCalendars.connectCalendar({
  provider: "google",
  credentialId: "Connected account"
})
era meeting_calendars connect_calendar \
  --provider "google" \
  --credential-id "Connected account"
tools/call
{
  "name": "era__meetings__connect_calendar",
  "arguments": {
    "provider": "google",
    "credentialId": "Connected account"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 calendar_connected · 429 slow down

meetings.delete

Delete a meeting — Removes the meeting, its transcript, notes and action items (the right to be forgotten). Tasks already made stay.

Needs meetings:delete · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/delete
API key or OAuth token · meetings:delete
  • REST alias: DELETE /api/v1/meetings/{id}
  • Canonical address: POST /api/v1/actions/meetings.delete

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
meeting_liveA meeting being recorded cannot be deleted.

Events it publishes: meetings.deleted

What it writes: meeting (delete) — Removes the meeting; meeting_action_item (delete) — Its action items go with it

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/delete \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.deleted"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.delete("MEETING_ID")
era meetings delete MEETING_ID
tools/call
{
  "name": "era__meetings__delete",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:delete · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, meeting_live · 429 slow down

meetings.discard_follow_up

Discard the follow-up email — No email for this meeting.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/discard_follow_up
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.discard_follow_up

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_follow_upThere must be a draft.
follow_up_closedOnly a draft.

What it writes: meeting (update) — draft → discarded

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/discard_follow_up \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.discardFollowUp("MEETING_ID")
era meetings discard_follow_up MEETING_ID
tools/call
{
  "name": "era__meetings__discard_follow_up",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_follow_up, follow_up_closed · 429 slow down

meetings.disconnect_calendar

Disconnect a meeting calendar — Era stops reading it; its upcoming meetings are dropped, past notes stay.

Needs meetings:write · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/meeting_calendars/{id}/actions/disconnect_calendar
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.disconnect_calendar

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Calendar · id of meeting_calendar

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
calendar_not_foundThe calendar must be connected here.
not_your_calendarIts owner (or a manager) disconnects it.

What it writes: meeting_calendar (delete) — Removes the calendar; meeting (update) — Its unrecorded upcoming meetings → cancelled

curl -X POST https://app.getera.io/api/v1/meeting_calendars/MEETING_CALENDAR_ID/actions/disconnect_calendar \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingCalendars.disconnectCalendar("MEETING_CALENDAR_ID")
era meeting_calendars disconnect_calendar MEETING_CALENDAR_ID
tools/call
{
  "name": "era__meetings__disconnect_calendar",
  "arguments": {
    "id": "MEETING_CALENDAR_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 calendar_not_found, not_your_calendar · 429 slow down

meetings.dismiss_action_item

Dismiss an action item — Era heard a commitment that was not one.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meeting_action_items/{id}/actions/dismiss_action_item
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.dismiss_action_item

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Action item · id of meeting_action_item

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
item_not_foundThe item must exist here.
item_closedOnly a proposed item.

What it writes: meeting_action_item (update) — → dismissed

curl -X POST https://app.getera.io/api/v1/meeting_action_items/MEETING_ACTION_ITEM_ID/actions/dismiss_action_item \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingActionItems.dismissActionItem("MEETING_ACTION_ITEM_ID")
era meeting_action_items dismiss_action_item MEETING_ACTION_ITEM_ID
tools/call
{
  "name": "era__meetings__dismiss_action_item",
  "arguments": {
    "id": "MEETING_ACTION_ITEM_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 item_not_found, item_closed · 429 slow down

meetings.dismiss_suggestion

Dismiss a suggestion — Keep the deal where it is, or don’t book the next meeting.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/dismiss_suggestion
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.dismiss_suggestion

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
kindstring (enum)yesWhich · Allowed values: stage, next_meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_suggestionThere must be a suggestion.
suggestion_closedA suggestion is answered once.

What it writes: meeting (update) — suggestion → dismissed

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/dismiss_suggestion \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"kind":"stage"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.dismissSuggestion("MEETING_ID", {
  kind: "stage"
})
era meetings dismiss_suggestion MEETING_ID \
  --kind "stage"
tools/call
{
  "name": "era__meetings__dismiss_suggestion",
  "arguments": {
    "id": "MEETING_ID",
    "kind": "stage"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_suggestion, suggestion_closed · 429 slow down

meetings.edit_follow_up

Edit the follow-up email — The recipient, subject or text of the email Era drafted after the meeting.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/edit_follow_up
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.edit_follow_up

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
tostringTo · max 320
subjectstringSubject · max 300
bodystringMessage · max 20000
sendFromstringSend from · max 64

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_follow_upThere must be a draft.
follow_up_closedA sent or discarded email is not edited.
invalid_recipientThe recipient is an email address.
invalid_send_fromSend from auto, era, mine, workspace or a connection.

What it writes: meeting (update) — Rewrites the draft

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/edit_follow_up \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"to":"To"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.editFollowUp("MEETING_ID", {
  to: "To"
})
era meetings edit_follow_up MEETING_ID \
  --to "To"
tools/call
{
  "name": "era__meetings__edit_follow_up",
  "arguments": {
    "id": "MEETING_ID",
    "to": "To"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_follow_up, follow_up_closed, invalid_recipient, invalid_send_from · 429 slow down

meetings.expire_audio

Delete a meeting’s recording — The audio goes now (the owner asked) or after the retention period; the transcript and notes stay.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/expire_audio
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.expire_audio

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_recordingThere must be a recording.

What it writes: meeting (update) — Drops the recording link

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/expire_audio \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.expireAudio("MEETING_ID")
era meetings expire_audio MEETING_ID
tools/call
{
  "name": "era__meetings__expire_audio",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_recording · 429 slow down

meetings.fail

A meeting could not be processed — The recording could not be fetched or read; the reservation is given back. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/fail
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.fail

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
errorstringyesWhy · max 600

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
already_filedA finished meeting is not failed afterwards.

Events it publishes: meetings.capture_failed

What it writes: meeting (update) — → failed, released

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, already_filed · 429 slow down

meetings.file_notes

File a meeting’s notes — Summary, decisions, action items, the follow-up draft and the suggestions — and tells workflows the meeting ended. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/file_notes
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.file_notes

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
summarystringyesSummary · max 4000
decisionsobject / arrayDecisions
actionItemsobject / arrayAction items
followUpobject / arrayFollow-up email
stageSuggestionobject / arrayDeal stage suggestion
nextMeetingobject / arrayNext meeting suggestion
customerIduuidCustomer · id of customer
leadIduuidDeal · id of lead
conversationIduuidInbox conversation · id of conversation
participantsobject / arrayWho took part
brainRefstringBrain source · max 255
notesCostUsdnumberNotes cost · min 0

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_transcriptNotes are written from a transcript.
invalid_payloadA summary and lists.

Events it publishes: meetings.ended, meetings.action_item_created

What it writes: meeting (update) — → ready, with the notes and proposals; meeting_action_item (insert) — One row per commitment (proposed)

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_transcript, invalid_payload · 429 slow down

meetings.file_transcript

File a meeting’s transcript — What was said, the length and the recording; meters the notetaker’s real minutes. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/file_transcript
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.file_transcript

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
transcriptobject / arrayyesTranscript
durationSecnumberyesLength (seconds) · min 0 · max 86400
recordingFileIduuidRecording · id of file
languagestringLanguage · max 8
sttCostUsdnumberSpeech-to-text cost · min 0
sourceKindstring (enum)Who paid · Allowed values: native, byos, byok
modestring (enum)How it arrived · Allowed values: upload
speakersobject / arrayWho spoke
ownNotesstringMy notes during the call · max 20000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
already_filedA finished meeting is re-run, not re-filed.
invalid_payloadThe transcript is a list.
no_transcriptSomething must have been said.

What it writes: meeting (update) — → processing, with transcript, length and cost

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, already_filed, invalid_payload, no_transcript · 429 slow down

meetings.forget_speaker

Forget a remembered speaker name — Era stops putting this name on that voice in later meetings.

Needs meetings:write · removes or cannot be undone

POSThttps://app.getera.io/api/v1/meeting_speaker_aliases/{id}/actions/forget_speaker
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.forget_speaker

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Remembered name · id of meeting_speaker_alias

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
alias_not_foundThe name must be remembered here.

What it writes: meeting_speaker_alias (delete) — Removes it

curl -X POST https://app.getera.io/api/v1/meeting_speaker_aliases/MEETING_SPEAKER_ALIASE_ID/actions/forget_speaker \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingSpeakerAliases.forgetSpeaker("MEETING_SPEAKER_ALIASE_ID")
era meeting_speaker_aliases forget_speaker MEETING_SPEAKER_ALIASE_ID
tools/call
{
  "name": "era__meetings__forget_speaker",
  "arguments": {
    "id": "MEETING_SPEAKER_ALIASE_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 alias_not_found · 429 slow down

Record the calendar invite — The event Google or Outlook made (and its video link), or why it could not. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/link_invite
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.link_invite
FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
externalEventIdstringCalendar event · max 500
joinUrlstringMeeting link · max 2000
errorstringWhy not · max 600

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_inviteThere must be an invite to record.

Events it publishes: meetings.invite_sent

What it writes: meeting (update) — invite → sent / failed, with the event id

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_invite · 429 slow down

Link an action item to its task — Records the task an accepted item became. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meeting_action_items/{id}/actions/link_task
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.link_task
FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Action item · id of meeting_action_item
taskIduuidyesTask · id of ai_task

The action is refused with 409 and one of these codes:

CodeRefused when
item_not_foundThe item must exist here.

What it writes: meeting_action_item (update) — Writes the task id

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 item_not_found · 429 slow down

meetings.mark_follow_up_sent

Record the follow-up’s delivery — Queued with the sender, or refused. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/mark_follow_up_sent
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.mark_follow_up_sent

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
deliveryIduuidDelivery
errorstringWhy not · max 600

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
no_follow_upThere must be a follow-up.

Events it publishes: meetings.follow_up_sent

What it writes: meeting (update) — approved → sent / failed

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, no_follow_up · 429 slow down

meetings.record_capture

Note how a recording is going — Joining, waiting room, recording, ended or failed — from the bot provider or Era Desktop. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/record_capture
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.record_capture

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
statestring (enum)yesState · Allowed values: none, requested, joining, waiting_room, recording, ended, failed
botIdstringBot · max 200
deviceJobIdstringDesktop job · max 100
errorstringWhy it failed · max 600
consentMessagestringNotice posted · max 1000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
invalid_stateA known state, on a meeting not yet filed.

Events it publishes: meetings.started, meetings.capture_failed

What it writes: meeting (update) — Moves the capture state; a failure releases the reservation

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, invalid_state · 429 slow down

meetings.record_on_desktop

Record a meeting on my computer — Era Desktop records the meeting’s sound and your microphone on your own computer — nobody sees a bot. You confirm you told everyone.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/record_on_desktop
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.record_on_desktop

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
deviceIduuidyesEra Desktop
consentConfirmedbooleanI told everyone it is recorded
askOnDevicebooleanAsk on the computer first

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
not_upcomingOnly a meeting that has not finished.
already_capturingOne recording per meeting.
consent_requiredThe recording notice is confirmed first.

What it writes: meeting (update) — capture → requested on the device, consent noted

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/record_on_desktop \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"deviceId":"DEVICE_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.recordOnDesktop("MEETING_ID", {
  deviceId: "DEVICE_ID"
})
era meetings record_on_desktop MEETING_ID \
  --device-id "DEVICE_ID"
tools/call
{
  "name": "era__meetings__record_on_desktop",
  "arguments": {
    "id": "MEETING_ID",
    "deviceId": "DEVICE_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, not_upcoming, already_capturing, consent_required · 429 slow down

meetings.rename_speaker

Say who a speaker is — Names a voice in the transcript (a teammate, the customer, anyone). A name the meeting platform gave is remembered for later meetings.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/rename_speaker
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.rename_speaker

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
speakerKeystringyesSpeaker · max 140
namestringyesWho it is · max 120
emailstringEmail · max 320
userIduuidTeammate · id of app_user
customerIduuidCustomer · id of customer
rememberbooleanRemember for next time

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here and be visible to you.
empty_nameA speaker gets a name.
invalid_recipientAn email must be an email address.
speaker_not_foundThe voice must be in the meeting.
not_memberA teammate is a member.

What it writes: meeting (update) — The speaker and every turn of it get the name; meeting_speaker_alias (insert) — The platform’s name for them is remembered

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/rename_speaker \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"speakerKey":"Speaker","name":"Who it is"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.renameSpeaker("MEETING_ID", {
  speakerKey: "Speaker",
  name: "Who it is"
})
era meetings rename_speaker MEETING_ID \
  --speaker-key "Speaker" \
  --name "Who it is"
tools/call
{
  "name": "era__meetings__rename_speaker",
  "arguments": {
    "id": "MEETING_ID",
    "speakerKey": "Speaker",
    "name": "Who it is"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, empty_name, invalid_recipient, speaker_not_found, not_member · 429 slow down

meetings.save_brief

Save a meeting brief — Who is coming, what they care about, what we promised, what to watch out for, the deal — written before the call. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meetings/{id}/actions/save_brief
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.save_brief

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
briefobject / arrayyesBrief

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
invalid_payloadThe brief’s shape.

Events it publishes: meetings.brief_ready

What it writes: meeting (update) — Writes the brief

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, invalid_payload · 429 slow down

meetings.schedule

Add a meeting — A meeting Era should join or prepare for — paste its Zoom, Meet or Teams link, or leave it empty for a call in person.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/actions/schedule
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.schedule

Input

FieldTypeRequiredNotes
titlestringyesName · max 300
startsAtdate-timeStarts
endsAtdate-timeEnds
joinUrlstringMeeting link · max 2000
captureModestring (enum)How Era takes notes · Allowed values: auto, bot, desktop, none
ownerUserIduuidWhose meeting · id of app_user
customerIduuidCustomer · id of customer
leadIduuidDeal · id of lead
conversationIduuidInbox conversation · id of conversation
knowledgeBaseIduuidKnowledge base for the notes
participantsobject / arrayWho takes part
sourcestring (enum)Added by · Allowed values: manual, era

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
empty_titleA meeting needs a name.
bad_join_urlA link must be an https address.
bad_timeTimes must be real and the end after the start.
not_memberThe owner must be a member.
invalid_payloadParticipants are a list of names and emails.

Events it publishes: meetings.scheduled

What it writes: meeting (insert) — Writes the meeting

curl -X POST https://app.getera.io/api/v1/meetings/actions/schedule \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"title":"Name"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.scheduled"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.schedule({
  title: "Name"
})
era meetings schedule \
  --title "Name"
tools/call
{
  "name": "era__meetings__schedule",
  "arguments": {
    "title": "Name"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 empty_title, bad_join_url, bad_time, not_member, invalid_payload · 429 slow down

meetings.send_bot

Send Era’s notetaker to a meeting — A bot joins the Zoom, Meet, Teams or Webex call, posts the recording notice in the chat, and records on your own notetaker account. Minutes are checked first.

Needs meetings:write · reaches outside (sends, publishes or charges)

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/send_bot
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.send_bot

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
not_upcomingOnly a meeting that has not finished.
already_capturingOne notetaker per meeting.
no_join_linkThe bot needs the meeting link.
unsupported_platformZoom, Meet, Teams, Webex and GoTo only.
no_bot_keyThe bot needs the business’s own notetaker key.
bot_minutes_used_upThe month’s notetaker minutes.

What it writes: meeting (update) — capture → requested

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/send_bot \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.sendBot("MEETING_ID")
era meetings send_bot MEETING_ID
tools/call
{
  "name": "era__meetings__send_bot",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, not_upcoming, already_capturing, no_join_link, unsupported_platform, no_bot_key, bot_minutes_used_up · 429 slow down

meetings.send_invite

Send the calendar invite — Writes the meeting into your Google or Outlook calendar with everyone on it invited (a Meet or Teams link is made when it has none).

Needs meetings:write · reaches outside (sends, publishes or charges)

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/send_invite
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.send_invite

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
not_upcomingAn upcoming meeting with a time.
invite_sentAn invite is written once.
no_attendeesSomeone with an email to invite.
no_calendarA connected calendar to write into.

What it writes: meeting (update) — invite → pending (the calendar write follows)

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/send_invite \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.sendInvite("MEETING_ID")
era meetings send_invite MEETING_ID
tools/call
{
  "name": "era__meetings__send_invite",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, not_upcoming, invite_sent, no_attendees, no_calendar · 429 slow down

meetings.set_sharing

Choose who sees a meeting — Its owner always; also whoever can open its customer or deal (default), only you, or everyone in the workspace.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/set_sharing
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.set_sharing

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
sharingstring (enum)yesWho sees it · Allowed values: record, private, workspace

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
invalid_payloadA known choice.
not_your_meetingIts owner or a manager decides.

What it writes: meeting (update) — Writes who sees it

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/set_sharing \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"sharing":"record"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.setSharing("MEETING_ID", {
  sharing: "record"
})
era meetings set_sharing MEETING_ID \
  --sharing "record"
tools/call
{
  "name": "era__meetings__set_sharing",
  "arguments": {
    "id": "MEETING_ID",
    "sharing": "record"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, invalid_payload, not_your_meeting · 429 slow down

meetings.skip

Don’t record a meeting — Era stays out of this meeting: no bot, no recording. The brief stays.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/skip
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.skip

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
not_upcomingOnly a meeting that has not started can be skipped.

Events it publishes: meetings.skipped

What it writes: meeting (update) — upcoming → skipped

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/skip \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.skipped"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.skip("MEETING_ID")
era meetings skip MEETING_ID
tools/call
{
  "name": "era__meetings__skip",
  "arguments": {
    "id": "MEETING_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, not_upcoming · 429 slow down

meetings.sync_calendar

Read a calendar’s meetings — The next days’ events from Google or Outlook become meetings, each with the calendar’s join rule applied. Machine-only.

Needs meetings:handle · changes data

Run by Era itself (machine-only). Listed so the reference is complete; an API key or a token is refused (403 machine_only).
POSThttps://app.getera.io/api/v1/meeting_calendars/{id}/actions/sync_calendar
API key or OAuth token · meetings:handle
  • Canonical address: POST /api/v1/actions/meetings.sync_calendar

Input

FieldTypeRequiredNotes
calendarIduuidyesFilled from the path {id} · Calendar · id of meeting_calendar
eventsobject / arrayEvents
errorstringWhy it could not be read · max 600
internalDomainsobject / arrayCompany email domains

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
calendar_not_foundThe calendar must be connected here.
invalid_payloadEvents are a list with ids.

Events it publishes: meetings.scheduled

What it writes: meeting (insert) — New events become meetings; meeting (update) — Moved or cancelled events follow; meeting_calendar (update) — Last read time / error

Errors: 401 no or expired credential · 403 the credential does not hold meetings:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 calendar_not_found, invalid_payload · 429 slow down

meetings.update

Change a meeting — Name, time, link, how Era records it, and which customer, deal, conversation and knowledge base it belongs to.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meetings/{id}/actions/update
API key or OAuth token · meetings:write
  • REST alias: PATCH /api/v1/meetings/{id}
  • Canonical address: POST /api/v1/actions/meetings.update

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Meeting · id of meeting
titlestringName · max 300
startsAtdate-timeStarts
endsAtdate-timeEnds
joinUrlstringMeeting link · max 2000
captureModestring (enum)How Era takes notes · Allowed values: auto, bot, desktop, none
ownerUserIduuidWhose meeting · id of app_user
customerIduuidCustomer · id of customer
leadIduuidDeal · id of lead
conversationIduuidInbox conversation · id of conversation
knowledgeBaseIduuidKnowledge base for the notes
participantsobject / arrayWho takes part

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
meeting_not_foundThe meeting must exist here.
empty_titleA meeting needs a name.
bad_join_urlA link must be an https address.
bad_timeTimes must be real and the end after the start.
not_memberThe owner must be a member.
not_upcomingHow Era records changes only before the meeting.
invalid_payloadParticipants are a list of names and emails.

Events it publishes: meetings.updated

What it writes: meeting (update) — Rewrites the meeting’s details and links

curl -X POST https://app.getera.io/api/v1/meetings/MEETING_ID/actions/update \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"title":"Name"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "meetings.updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetings.update("MEETING_ID", {
  title: "Name"
})
era meetings update MEETING_ID \
  --title "Name"
tools/call
{
  "name": "era__meetings__update",
  "arguments": {
    "id": "MEETING_ID",
    "title": "Name"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 meeting_not_found, empty_title, bad_join_url, bad_time, not_member, not_upcoming, invalid_payload · 429 slow down

meetings.update_action_item

Change an action item — Before it becomes a task: the wording, who does it, by when.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meeting_action_items/{id}/actions/update_action_item
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.update_action_item

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Action item · id of meeting_action_item
textstringWhat · max 1000
assigneeUserIduuidWho · id of app_user
dueAtdate-timeBy when

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
item_not_foundThe item must exist here.
item_closedOnly a proposed item changes here.
empty_textAn item says what to do.
not_memberThe owner must be a member.

What it writes: meeting_action_item (update) — Rewrites the item

curl -X POST https://app.getera.io/api/v1/meeting_action_items/MEETING_ACTION_ITEM_ID/actions/update_action_item \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text":"What"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingActionItems.updateActionItem("MEETING_ACTION_ITEM_ID", {
  text: "What"
})
era meeting_action_items update_action_item MEETING_ACTION_ITEM_ID \
  --text "What"
tools/call
{
  "name": "era__meetings__update_action_item",
  "arguments": {
    "id": "MEETING_ACTION_ITEM_ID",
    "text": "What"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 item_not_found, item_closed, empty_text, not_member · 429 slow down

meetings.update_calendar

Change a meeting calendar — Who Era joins, how it records, where the notes go, or pause the calendar.

Needs meetings:write · changes data

POSThttps://app.getera.io/api/v1/meeting_calendars/{id}/actions/update_calendar
API key or OAuth token · meetings:write
  • Canonical address: POST /api/v1/actions/meetings.update_calendar

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Calendar · id of meeting_calendar
joinRulestring (enum)Era joins · Allowed values: all, external, organised, off
captureModestring (enum)How · Allowed values: auto, bot, desktop
knowledgeBaseIduuidNotes go to
enabledbooleanOn
labelstringName · max 120

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
calendar_not_foundThe calendar must be connected here.
not_your_calendarIts owner (or a manager) changes it.

What it writes: meeting_calendar (update) — Rewrites the rule

curl -X POST https://app.getera.io/api/v1/meeting_calendars/MEETING_CALENDAR_ID/actions/update_calendar \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"joinRule":"all"}'
Response
{
  "ok": true,
  "result": "…",
  "events": []
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.meetingCalendars.updateCalendar("MEETING_CALENDAR_ID", {
  joinRule: "all"
})
era meeting_calendars update_calendar MEETING_CALENDAR_ID \
  --join-rule "all"
tools/call
{
  "name": "era__meetings__update_calendar",
  "arguments": {
    "id": "MEETING_CALENDAR_ID",
    "joinRule": "all"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold meetings:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 calendar_not_found, not_your_calendar · 429 slow down

Data models

MeetingActionItem

Table meeting_action_item · Resource meeting_action_items

  • GET /api/v1/meeting_action_items
  • GET /api/v1/meeting_action_items/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
meeting_idstring (uuid) · uuidmeeting
textstring · text
assignee_user_idstring (uuid) · uuidyesapp_user
assignee_namestring · textyes
due_atstring (date-time) · timestamptzyes
statusstring · textproposed, accepted, done, dismissed
task_idstring (uuid) · uuidyesai_task
positioninteger · int4
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK (((assignee_name IS NULL) OR (length(assignee_name) <= 120)))
  • CHECK (((length(text) >= 1) AND (length(text) <= 1000)))

MeetingCalendar

Table meeting_calendar · Resource meeting_calendars

  • GET /api/v1/meeting_calendars
  • GET /api/v1/meeting_calendars/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
user_idstring (uuid) · uuidapp_user
providerstring · textgoogle, microsoft
calendar_idstring · text
labelstring · textyes
account_emailstring · textyes
join_rulestring · textall, external, organised, off
capture_modestring · textauto, bot, desktop
knowledge_base_idstring (uuid) · uuidyes
is_enabledboolean · bool
last_synced_atstring (date-time) · timestamptzyes
sync_errorstring · textyes
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK (((account_email IS NULL) OR (length(account_email) <= 320)))
  • CHECK (((length(calendar_id) >= 1) AND (length(calendar_id) <= 300)))
  • CHECK (((label IS NULL) OR (length(label) <= 120)))
  • CHECK (((sync_error IS NULL) OR (length(sync_error) <= 600)))

MeetingSpeakerAlias

Table meeting_speaker_alias · Resource meeting_speaker_aliases

  • GET /api/v1/meeting_speaker_aliases
  • GET /api/v1/meeting_speaker_aliases/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
label_keystring · text
labelstring · text
namestring · text
emailstring · textyes
user_idstring (uuid) · uuidyesapp_user
customer_idstring (uuid) · uuidyescustomer
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK (((email IS NULL) OR (length(email) <= 320)))
  • CHECK (((length(label) >= 1) AND (length(label) <= 120)))
  • CHECK (((length(label_key) >= 1) AND (length(label_key) <= 120)))
  • CHECK (((length(name) >= 1) AND (length(name) <= 120)))

Meeting

Table meeting · Resource meetings

ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
owner_user_idstring (uuid) · uuidyesapp_user
calendar_idstring (uuid) · uuidyesmeeting_calendar
external_event_idstring · textyes
titlestring · text
starts_atstring (date-time) · timestamptzyes
ends_atstring (date-time) · timestamptzyes
join_urlstring · textyes
platformstring · textzoom, google_meet, teams, webex, goto, in_person, other
sourcestring · textmanual, calendar, upload, desktop, era
statusstring · textupcoming, capturing, processing, ready, failed, cancelled, skipped
capture_modestring · textauto, bot, desktop, upload, none
capture_statestring · textnone, requested, joining, waiting_room, recording, ended, failed
capture_errorstring · textyes
bot_providerstring · textyes
bot_idstring · textyes
bot_payerstring · textyes
device_idstring (uuid) · uuidyes
device_job_idstring · textyes
consentobject · jsonb
participantsobject · jsonb
customer_idstring (uuid) · uuidyescustomer
lead_idstring (uuid) · uuidyeslead
conversation_idstring (uuid) · uuidyesconversation
knowledge_base_idstring (uuid) · uuidyes
recording_file_idstring (uuid) · uuidyesfile
started_atstring (date-time) · timestamptzyes
ended_atstring (date-time) · timestamptzyes
duration_secinteger · int4
languagestring · textyes
transcriptobject · jsonb
summarystring · textyes
decisionsobject · jsonb
briefobject · jsonbyes
brief_atstring (date-time) · timestamptzyes
follow_upobject · jsonbyes
stage_suggestionobject · jsonbyes
next_meetingobject · jsonbyes
brain_refstring · textyes
cost_usdstring (decimal) · numeric
source_kindstring · textyes
errorstring · textyes
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz
speakersobject · jsonb
sharingstring · textrecord, private, workspace
inviteobject · jsonbyes
audio_expires_atstring (date-time) · timestamptzyes
audio_deleted_atstring (date-time) · timestamptzyes
own_notesstring · textyes

Primary key: id

Checks:

  • CHECK (((bot_id IS NULL) OR (length(bot_id) <= 200)))
  • CHECK (((bot_payer IS NULL) OR (bot_payer = 'own_key'::text))) NOT VALID
  • CHECK (((bot_provider IS NULL) OR (bot_provider = ANY (ARRAY['recall'::text, 'meetingbaas'::text, 'skribby'::text, 'mock'::text]))))
  • CHECK (((capture_error IS NULL) OR (length(capture_error) <= 600)))
  • CHECK ((jsonb_typeof(consent) = 'object'::text))
  • CHECK ((jsonb_typeof(decisions) = 'array'::text))
  • CHECK ((duration_sec >= 0))
  • CHECK (((error IS NULL) OR (length(error) <= 600)))
  • CHECK (((external_event_id IS NULL) OR (length(external_event_id) <= 500)))
  • CHECK (((join_url IS NULL) OR ((join_url ~ '^https://'::text) AND (length(join_url) <= 2000))))
  • CHECK (((language IS NULL) OR (language ~ '^[a-z]{2}(-[A-Z]{2})?$'::text)))
  • CHECK (((own_notes IS NULL) OR (length(own_notes) <= 20000)))
  • CHECK ((jsonb_typeof(participants) = 'array'::text))
  • CHECK (((source_kind IS NULL) OR (source_kind = ANY (ARRAY['native'::text, 'byos'::text, 'byok'::text])))) NOT VALID
  • CHECK ((jsonb_typeof(speakers) = 'array'::text))
  • CHECK (((summary IS NULL) OR (length(summary) <= 4000)))
  • CHECK (((ends_at IS NULL) OR (starts_at IS NULL) OR (ends_at >= starts_at)))
  • CHECK (((length(title) >= 1) AND (length(title) <= 300)))
  • CHECK ((jsonb_typeof(transcript) = 'array'::text))

Events

Workflows and webhooks react to these events.

EventWhat happensPayload
meetings.action_item_acceptedAn action item was accepted — it becomes a task.id, meetingId, meetingTitle, text, assigneeUserId, dueAt, recordType, recordId, recipientUserId
meetings.action_item_createdEra (or a person) noted a commitment made in a meeting.id, meetingId, customerId, leadId, text, assigneeUserId, dueAt, recipientUserId
meetings.brief_readyEra wrote the brief for an upcoming meeting.id, title, startsAt, recipientUserId
meetings.calendar_connectedA member connected a calendar to meetings.id, provider, userId
meetings.capture_failedEra could not record or process a meeting.id, title, error, recipientUserId
meetings.deletedA meeting and its notes were deleted.id, recordingFileId
meetings.endedA meeting ended and its notes are ready: summary, decisions, action items, follow-up draft.id, title, ownerUserId, summary, recipientUserId, customerId, leadId, conversationId, actionItems, hasFollowUp
meetings.follow_up_approvedA person approved the follow-up email — it is sent from their mailbox or the business sender.id, to, subject, text, customerId, leadId, fromConnection, approvedBy
meetings.follow_up_sentThe follow-up email went to the sender.id, to, customerId, leadId
meetings.invite_sentEra wrote a meeting into the Google or Outlook calendar and invited its people.id, title, startsAt, attendees, recipientUserId
meetings.next_meeting_bookedThe next meeting Era heard agreed was booked; its calendar invite follows.id, fromMeetingId, title, startsAt, endsAt, ownerUserId, attendees, invite
meetings.scheduledA meeting was added — from a calendar, by a person, or booked as the next meeting.id, title, startsAt, ownerUserId, customerId, leadId
meetings.skippedSomeone told Era not to record a meeting.id, botProvider, botId
meetings.stage_acceptedA person accepted the deal stage Era suggested after a meeting.id, leadId, stageId, stageName
meetings.startedEra started recording a meeting.id, title, ownerUserId, mode
meetings.updatedA meeting’s details or links changed.id