Custom endpoint tabs
A custom endpoint tab gets its locations from an HTTP endpoint you build, for example an Azure Logic App. MailConnect calls it as the person using it, with their delegated tokens, so the endpoint can look things up in SharePoint or Microsoft Graph as them.
Only you and Pinksky set these tabs up, on the customer’s Settings tab: Tabs in the add-in → Add tab → Custom endpoint… (🤝). The address and the tokens can carry keys, so the customer’s Admins can rename, move and star an endpoint tab, but not change or remove it. See Setting up customers for the card.
What goes in the dialog
| Field | What to enter |
|---|---|
| Name in Outlook | The tab’s name. Required, and under 60 characters. |
| Address | The endpoint’s full https:// address, called with GET. For a Logic App, that’s its invoke URL including its signature (sp, sv, sig). Anyone with the address can call the endpoint, so treat it as a secret. Once saved, it’s shown shortened: type a new one to replace it. |
| App ID | The app registration in the customer’s Microsoft 365 that MailConnect gets each person’s tokens from. See The app registration. |
| Tokens sent | A SharePoint token, in X-SP-Access-Token (MailConnect’s default), or Choose the tokens. See Tokens. |
| Hide locations people can’t open | MailConnect checks each location’s site for the person, and leaves out the ones they can’t open. Usually unnecessary: the endpoint already runs as the person. |
Tokens
An access token is only valid for one API: a SharePoint token can’t be used against Microsoft Graph, or the other way round. An endpoint that calls both needs a token for each. With Choose the tokens, select Add token for each:
| Field | What to enter |
|---|---|
| Type | SharePoint (the customer’s SharePoint, found automatically), Graph (Microsoft Graph), or Custom (your own API). |
| Header | The request header the token is sent in, for example X-SP-Access-Token or X-Graph-Access-Token. Not Authorization. |
| Prefix | Optional: text in front of the token, for example Bearer . Without it, the bare token is sent. |
| Scopes | For Custom only: the scopes to ask for, separated by spaces, for example api://contoso-projects/.default. |
- Each token goes in its own header, never
Authorization. A Logic App refuses a request that carries both its signature and anAuthorizationheader. - A token that’s set up wrongly isn’t sent: no header,
Authorizationas the header, or a Custom token without scopes. The others still are, and the card warns about it. - One app registration for all of them. Every token comes through the App ID, so its delegated permissions are the limit of what your endpoint can do as the person. For SharePoint and Graph tokens, those are Microsoft Graph delegated permissions, for example
Sites.Read.All. - At most one sign-in prompt. MailConnect gets the tokens one at a time: after the first, the rest come silently.
Using the tokens in a Logic App
- Read each token from its trigger header, and call the matching API with
Authorization: Bearer <token>. For example,X-SP-Access-Tokenforhttps://{tenant}.sharepoint.com/_api/search/postquery, andX-Graph-Access-Tokenforhttps://graph.microsoft.com/v1.0/search/query. - Keep the Logic App protected by the signature in its address. Don’t add a
Microsoft Entra authorization policy: SharePoint tokens fail standard JWT
validation, and only SharePoint itself accepts them. A token that isn’t valid
simply gets a
401from the API you call. - Getting a
401from Graph? You’re probably sending the SharePoint token. Add a Graph token under Tokens sent, and use its header.
Calls from the browser
MailConnect calls the endpoint from the browser, with the token headers, so the
endpoint must accept cross-origin requests (CORS) from MailConnect’s origin,
https://mailconnect.tenantapps.cloud, including the preflight request. Until
MailConnect’s old address retires, also allow https://mailconnect.pinksky.dk:
customers who haven’t installed the new manifest still run from there.
What the endpoint returns
A JSON array, one entry per location:
[
{
"id": "1",
"parentId": null,
"title": "Project A",
"subTitle": "Consulting",
"webUrl": "https://tenant.sharepoint.com/sites/ProjectA",
"filterValues": ["2024", "Active", "High Priority"]
}
]
| Field | Description |
|---|---|
id | Unique ID of the location. |
parentId | Accepted, but not used: MailConnect shows every location at the top level. |
title / subTitle | Shown on the location’s card. |
webUrl | The SharePoint site the location opens, for browsing and archiving. |
filterValues | Optional. More text the tab’s search box matches, besides title and subTitle. |
A response that isn’t an array, or an error status, shows the tab’s This tab couldn’t load message with Retry.
Checking it
In Outlook: save, then open MailConnect as someone at the customer and pick the tab. Its locations come straight from the endpoint. No locations means the endpoint refused the tokens, or didn’t answer with a list.
In the Admin Center: Check the endpoint…, in the pane next to the tabs, shows what the endpoint returns, without opening Outlook. It’s there when you’re signed in to the customer’s Microsoft 365.
- It asks first: it sends a SharePoint token for your account to the endpoint’s host, and with it the endpoint can read SharePoint as you for up to an hour.
- It’s logged before anything is sent: your account and the host, never the address or the token.
- Only SharePoint tokens are sent, in the headers of the tab’s SharePoint tokens (or
X-SP-Access-Token). Graph and Custom tokens aren’t sent from the Admin Center. - The token comes from MailConnect’s own app, not from the tab’s App ID. An endpoint that only accepts tokens from its own app refuses the check (
401or403), even when the tab works in Outlook. - The endpoint must accept calls from any site (
Access-Control-Allow-Origin: *): the check runs from a sandboxed page.
The pane then shows the first 50 locations returned. What the customer’s IT sees of this is under What the Admin Center can do in your tenant.
The app registration
The app registration behind App ID, in the customer’s Microsoft Entra ID:
Authentication: add these Single-page application (SPA) redirect URIs:
brk-multihub://mailconnect.tenantapps.cloudhttps://mailconnect.tenantapps.cloud
Keep brk-multihub://mailconnect.pinksky.dk and https://mailconnect.pinksky.dk
as well until the old address retires.
API permissions: Microsoft Graph delegated permissions (for example
Sites.Read.All), not the SharePoint API’s AllSites.* permissions.
Expose an API: under Authorized client applications, add the client ID
ea5a67f6-b6f3-4338-b240-c655ddc3cc8e.
That’s Microsoft’s well-known client ID that lets Office call your API on the signed-in person’s behalf. It’s the same for every add-in and every tenant, not something specific to MailConnect or to your app registration. See Microsoft’s Register an Office Add-in that uses SSO for background.
Authorize it for the access_as_user scope. In the app’s manifest:
"oauth2PermissionScopes": [
{
"adminConsentDescription": "App can act as the user",
"adminConsentDisplayName": "App can act as the user",
"id": "c92ac36c-da0c-4812-a119-592394406fde",
"isEnabled": true,
"type": "User",
"userConsentDescription": null,
"userConsentDisplayName": "App can act as the user",
"value": "access_as_user"
}
],
"preAuthorizedApplications": [
{
"appId": "ea5a67f6-b6f3-4338-b240-c655ddc3cc8e",
"delegatedPermissionIds": [
"c92ac36c-da0c-4812-a119-592394406fde"
]
}
]