Skip to content
Docs
Email & messaging

Outlook (Microsoft 365)

Let hires read, search, reply to and send email in a Microsoft 365 or Outlook mailbox.

Explore 10 actions and their permissionsExact inputs, sign-in scopes, access limits and approval rules.

With Outlook connected, a hire can list and search mail in the folders you allow, read a message or a whole conversation, draft a reply for someone to check, reply and send new mail, and move or mark messages. Replies stay in their conversation in Outlook and everyone else's mail app. It works the same way as Email and Gmail.

Use this rather than Email (IMAP and SMTP) for Microsoft 365: many organisations have turned off password sign-in for IMAP and SMTP, and this works without it.

Every email ends with your business's name, like "Bayt Studio Accounts", as its signature. Mail is sent from the mailbox itself, so the sender's name people see is the mailbox's own name in Microsoft 365. We suggest a mailbox just for the hire's work, named for your business or team, like accounts@yourbusiness.com called "Bayt Studio Accounts".

1. Register an app in Microsoft Entra

Roster connects as an app you own, so you choose what it can reach and can revoke it at any time. One app can serve both Outlook mail and Outlook Calendar.

  1. Open entra.microsoft.com → App registrations → New registration.
  2. Name: Roster. Supported account types: Accounts in this organizational directory only for your own organisation. (Choose the multitenant option with personal accounts to connect Outlook.com mailboxes too.)
  3. Redirect URI: platform Web, the address Roster shows on the Outlook connection. It ends in /api/integrations/outlook/oauth/callback. Click Register.
  4. On the app's Overview, copy the Application (client) ID and the Directory (tenant) ID.
  5. API permissions → Add a permission → Microsoft Graph → Delegated permissions: add User.Read, Mail.ReadWrite, Mail.Send and offline_access. If Microsoft says your organisation must approve the app, ask whoever manages your Microsoft 365 to grant consent on this page.
  6. Certificates & secrets → New client secret. Copy its Value (shown only once).

2. Connect it in Roster

  1. Open Integrations → Tools → Add a tool, search for Outlook and choose it.
  2. OAuth app client ID: the Application (client) ID. OAuth app client secret: the secret's value.
  3. Tenant: your Directory (tenant) ID or your domain, like yourbusiness.com. Leave it as common if the app accepts any organisation or personal accounts.
  4. From name: your business or team name, used in the signature.
  5. Click Connect, then Connect with Outlook on the new connection, sign in with the mailbox hires should use, and click Accept.

What Roster asks Microsoft for

PermissionWhy
User.ReadKnow the mailbox's own address
Mail.ReadWriteRead mail; draft, move and mark it (only hires allowed to)
Mail.SendSend replies and new mail (only hires allowed to)
offline_accessStay connected without signing in again

3. Give hires access

On the hire's Tools tab, click Give access on Outlook:

  • Read only: it can list folders, list, search and read messages and conversations, and nothing else.
  • Read and write: it can also draft replies, reply, send new mail, and move and mark messages.
  • Folders: the folders it may use, like Inbox or Inbox/Invoices for a folder inside the inbox. Leave it empty for every folder. Anything outside the list is refused.
  • Who it may email: domains it may send to, like yourclient.com. Leave it empty to let it email anyone.

If you'd like to check emails before they go, give the hire Read and write and ask it to draft replies: they wait in the mailbox's Drafts folder, in their conversation, for someone to send.

First emails to new people

A first email to someone outside your team that this mailbox has never written to waits for a person's approval: the hire asks in the thread with the recipient and the message, and when the approver says yes, Roster sends exactly that email. After that, writing to them again doesn't ask, and replies never do. People at your team's domains never count as new. To change this for a hire, use When it asks first on its Tools tab.

Saying it's an AI assistant

A hire never pretends to be a person, and always says it's AI when asked. If you also want every email to say so up front, turn on Say it's an AI assistant in first messages to outsiders under Settings → Workspace (more). Each email's signature then adds a line saying an AI assistant wrote it for your business.

Waking a hire when mail arrives

A hire's responsibility can watch Outlook: when new mail lands in its folders (or the inbox, if it has none listed), the hire is woken with a line for each new email. Checking costs nothing when nothing arrived.

If something goes wrong

  • "Isn't connected yet": press Connect with Outlook on the connection.
  • Microsoft says the redirect URI doesn't match: the Web redirect URI in Entra must be exactly the one Roster shows.
  • Microsoft says the app needs approval: whoever manages your Microsoft 365 grants consent on the app's API permissions page.
  • A folder isn't found: Roster sees top-level folders and the folders directly inside them. Write a folder inside another as Parent/Child.

Tools and permissions reference

This reference is built from the same definitions Roster uses to connect Outlook (Microsoft 365) and give hires access. It updates with each release.

Authentication and requested permissions

The account or app you connect sets the outer limit. Each hire's access can narrow it further. Connecting a tool gives it to no hire until you give access on that hire's Tools tab.

OAuth 2.0

The Application (client) ID of the app you registered for Roster in Microsoft Entra.

Requested scopes:

  • offline_access
  • User.Read
  • Mail.ReadWrite
  • Mail.Send

Connection fields

Outlook (Microsoft 365) connection fields
FieldWhat to provide
OAuth app client ID
clientId
Optional
The Application (client) ID of the app you registered for Roster in Microsoft Entra.
OAuth app client secret
clientSecret
Optional · sealed secret
Use the value for your account or connection.
Tenant
tenant
Optional
Your Microsoft 365 organisation's tenant ID or domain (in Microsoft Entra → Overview). Leave it as common to let any work, school or personal account sign in.

Starts with: common.

From name
fromName
Required
Your business or team name, used in the signature of every email. Never a made-up person's name.

Per-hire limits

Read-only hires receive only actions that read. Read-and-write access also allows actions that change things, where the connection itself permits them. An empty resource allowlist usually means everything the connected account can reach; each field below explains its meaning.

Outlook (Microsoft 365) per-hire limits
FieldWhat to provide
Folders
folders
Optional
Folders the hire may read and change, like INBOX or Inbox/Invoices. Leave empty for every folder. A watch checks these (or INBOX).
Who it may email
recipientDomains
Optional
Domains the hire may send to, like example.com. Leave empty to let it email anyone.

Actions

10 actions: 5 only read and 5 change something. A read action may still need approval when your workspace or hire is set to ask. A locked approval requirement always applies.

10 of 10 actions. Open an action for its arguments and full input schema.

list_foldersRead only

The mail folders this hire can use, with how many messages and unread ones each has.

Approval: Uses your workspace and hire approval settings.

This action takes no arguments.

Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {}
}
list_messagesRead only

The newest messages in a folder, newest first: id, date, sender, subject, and whether read.

Approval: Uses your workspace and hire approval settings.

Arguments for list_messages
ArgumentTypeDetails
folderOptionalstringfolder, e.g. INBOXDefault: "INBOX"
unread_onlyOptionalbooleanSee input schema below.Default: false
limitOptionalintegerSee input schema below.Default: 20
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "folder": {
      "default": "INBOX",
      "description": "folder, e.g. INBOX",
      "type": "string",
      "minLength": 1
    },
    "unread_only": {
      "default": false,
      "type": "boolean"
    },
    "limit": {
      "default": 20,
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  }
}
searchRead only

Search a folder by words (in the subject or text), sender, subject or date. Newest matches first.

Approval: Uses your workspace and hire approval settings.

Arguments for search
ArgumentTypeDetails
folderOptionalstringfolder, e.g. INBOXDefault: "INBOX"
textOptionalstringwords anywhere in the message
fromOptionalstringpart of the sender's address or name
subjectOptionalstringSee input schema below.
sinceOptionalstringonly messages on or after this day, YYYY-MM-DD
unread_onlyOptionalbooleanSee input schema below.Default: false
limitOptionalintegerSee input schema below.Default: 20
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "folder": {
      "default": "INBOX",
      "description": "folder, e.g. INBOX",
      "type": "string",
      "minLength": 1
    },
    "text": {
      "description": "words anywhere in the message",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "from": {
      "description": "part of the sender's address or name",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "subject": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "since": {
      "description": "only messages on or after this day, YYYY-MM-DD",
      "type": "string",
      "format": "date",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
    },
    "unread_only": {
      "default": false,
      "type": "boolean"
    },
    "limit": {
      "default": 20,
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    }
  }
}
read_messageRead only

Read one message: who it's from and to, its date, subject and Message-ID, its text and its attachments' names. Doesn't mark it read.

Approval: Uses your workspace and hire approval settings.

Arguments for read_message
ArgumentTypeDetails
idRequiredstringthe message's id, from list_messages or search
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 400,
      "description": "the message's id, from list_messages or search"
    }
  },
  "required": [
    "id"
  ]
}
read_threadRead only

Read the whole conversation a message belongs to, oldest first: each message's sender, date and own words.

Approval: Uses your workspace and hire approval settings.

Arguments for read_thread
ArgumentTypeDetails
idRequiredstringthe message's id, from list_messages or search
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 400,
      "description": "the message's id, from list_messages or search"
    }
  },
  "required": [
    "id"
  ]
}
draft_replyRead and write

Write a reply to a message and keep it as a draft for a person to check and send. It stays in the message's thread. Write the message only: no greeting-card sign-off and never a person's name. Roster adds a signature in the business's name.

Approval: Uses your workspace and hire approval settings.

Arguments for draft_reply
ArgumentTypeDetails
idRequiredstringthe message's id, from list_messages or search
bodyRequiredstringthe reply, plain text
reply_allOptionalbooleanalso to everyone else on the messageDefault: false
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 400,
      "description": "the message's id, from list_messages or search"
    },
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 20000,
      "description": "the reply, plain text"
    },
    "reply_all": {
      "default": false,
      "description": "also to everyone else on the message",
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "body"
  ]
}
replyRead and write

Send a reply to a message, in its thread. Write the message only: no greeting-card sign-off and never a person's name. Roster adds a signature in the business's name.

Approval: Uses your workspace and hire approval settings.

Arguments for reply
ArgumentTypeDetails
idRequiredstringthe message's id, from list_messages or search
bodyRequiredstringthe reply, plain text
reply_allOptionalbooleanalso to everyone else on the messageDefault: false
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 400,
      "description": "the message's id, from list_messages or search"
    },
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 20000,
      "description": "the reply, plain text"
    },
    "reply_all": {
      "default": false,
      "description": "also to everyone else on the message",
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "body"
  ]
}
sendRead and write

Send a new email (not a reply: use reply for that, so it stays in its thread). Write the message only: no greeting-card sign-off and never a person's name. Roster adds a signature in the business's name.

Approval: when it writes to someone outside your team for the first time.

Arguments for send
ArgumentTypeDetails
toRequiredstring[]email addresses
ccOptionalstring[]email addressesDefault: []
subjectRequiredstringSee input schema below.
bodyRequiredstringplain text
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "to": {
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3
      },
      "description": "email addresses"
    },
    "cc": {
      "default": [],
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 3
      },
      "description": "email addresses"
    },
    "subject": {
      "type": "string",
      "minLength": 1,
      "maxLength": 250
    },
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 20000,
      "description": "plain text"
    }
  },
  "required": [
    "to",
    "subject",
    "body"
  ]
}
moveRead and write

Move messages from one folder to another (both must be folders this hire can use).

Approval: Uses your workspace and hire approval settings.

Arguments for move
ArgumentTypeDetails
folderOptionalstringfolder, e.g. INBOXDefault: "INBOX"
idsRequiredstring[]See input schema below.
toRequiredstringthe folder to move them to
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "folder": {
      "default": "INBOX",
      "description": "folder, e.g. INBOX",
      "type": "string",
      "minLength": 1
    },
    "ids": {
      "minItems": 1,
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 400,
        "description": "the message's id, from list_messages or search"
      }
    },
    "to": {
      "type": "string",
      "minLength": 1,
      "description": "the folder to move them to"
    }
  },
  "required": [
    "ids",
    "to"
  ]
}
markRead and write

Mark messages read or unread, or flag and unflag them.

Approval: Uses your workspace and hire approval settings.

Arguments for mark
ArgumentTypeDetails
idsRequiredstring[]See input schema below.
asRequired"read" | "unread" | "flagged" | "unflagged"See input schema below.
Full input schema (JSON)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "ids": {
      "minItems": 1,
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 400,
        "description": "the message's id, from list_messages or search"
      }
    },
    "as": {
      "type": "string",
      "enum": [
        "read",
        "unread",
        "flagged",
        "unflagged"
      ]
    }
  },
  "required": [
    "ids",
    "as"
  ]
}

Watches and incoming events

  • This integration supports a responsibility that watches for changes. The guide above explains what it checks and how to limit it.
  • No incoming webhook handler is declared for this integration.

Limits and troubleshooting

  • Permission errors: check both the connected account's rights and the hire's resource and read/write limits.
  • Expired or revoked access: reconnect or replace the key on the connection.
  • Rate limits and unavailable services can interrupt work. The hire's timecard records the outcome.
  • The action schema describes accepted inputs. It does not grant additional access or bypass approvals.

Service documentation · Integration source reference

On this page