Log in

Docs › Developers

Developers

Build on the memory.

MeetCrew has two developer surfaces, and they point in opposite directions. Your backend agent answers when MeetCrew calls it during a meeting. Your own agent reads the meeting memory back from MeetCrew — over an MCP server or a REST API, whichever suits how it is built — and acts on it. Keep the direction of call straight and the rest is simple.

Agent backend contract

MeetCrew calls you. When the teammate is addressed in a meeting, MeetCrew POSTs to your endpoint and speaks what you return. Front Copilot Studio, Microsoft Foundry Agent Service, an OpenAI-compatible endpoint, or your own webhook.

Memory API — MCP or REST

You call MeetCrew. Your own agent connects over MCP or plain REST and reads structured cross-meeting memory — decisions, open questions, action items, statements, topics — then acts on it in your systems. Same records, same token, either way.

Your agent authenticates to MeetCrew with Microsoft Entra. MeetCrew authenticates to your backend the way that backend expects: a webhook signature, an API key, a Direct Line secret, or a Microsoft Entra service principal for Foundry. You enter that credential once in the admin console; MeetCrew keeps it in a dedicated Azure Key Vault, never shows it again, and sends it only to the endpoint host and backend type it was saved for. Every call is scoped to one tenant, enforced server-side. v1  The MCP surface reads memory and acts on the workflow records — action items, decisions, and open questions; it can’t delete, or alter transcripts, statements, provenance, or the audit log. On the backend side, an OpenAI-compatible endpoint is streamed, and a call that cannot connect or answers 5xx or 429 is retried once; a custom webhook is called once and not streamed.

Memory API — MCP and REST

Your agent reads — and acts on — the memory.

Two endpoints, one contract. https://mcp.meetcrew.ai/v1 speaks MCP over Streamable HTTP; https://api.meetcrew.ai/v1 is the same memory over ordinary REST. They return the same records with the same field names, so the choice is about how your agent is built, not about what it can see. Authenticate either with a Microsoft Entra bearer token for a service principal you grant in the admin console — the same token works on both. The tenant is derived from the token — a client can’t reach another tenant’s memory even by guessing IDs. Each grant names one deployment (one named teammate), and reads and actions are scoped to it. If an administrator has shared another teammate’s memory with that one, on the teammate’s Sharing tab, list, search and topic reads include those records too, each carrying its own deployment_id. Shared records can be read but not changed through this grant, and getMeeting does not reach the other teammate’s meetings. A grant also carries a scope: read serves every read, and the four actions need read_write, which your admin selects when issuing the grant.

Before the first token. Your agent requests its token from your own Microsoft Entra directory, and Entra issues it only after a Global Administrator or Privileged Role Administrator there has authorized MeetCrew — once, for the whole organization. Do it from the admin console (Workspace → Authorize MeetCrew in Microsoft Entra), or have that administrator open https://login.microsoftonline.com/organizations/adminconsent?client_id=569124d5-6864-418d-91b6-8e0f668440ae&redirect_uri=https%3A%2F%2Fadmin.meetcrew.ai%2Fentra-consent signed in to your directory; they don’t need a MeetCrew account. Until then the token request fails with AADSTS500011 before it reaches MeetCrew. The same consent lets MeetCrew read users’ basic profiles, for naming meeting speakers and answering data-subject requests.

The grant and the token. A Tenant Administrator creates the grant in the admin console, naming your agent by its service principal’s Object ID — the Object ID on its Enterprise application in your directory, not the Application (client) ID and not the app registration’s own Object ID; a grant made with either never matches the agent’s token. Your agent then requests an app-only token with the client-credentials flow, from your own tenant’s endpoint https://login.microsoftonline.com/{your-tenant-id}/oauth2/v2.0/token — Entra refuses this flow at /organizations and /common — with scope api://569124d5-6864-418d-91b6-8e0f668440ae/.default. A token issued to a person is refused, even when a grant names that person.

Resources

meetcrew://deployments

List the named teammates the caller may read, with the scope of each grant.

meetcrew://meetings/{meeting_id}?deployment_id={deployment_id}

A single meeting’s canonical record — participants and a memory rollup. A resource template, listed by resources/templates/list; both ids are required.

Tools

listDecisions

Decisions recorded across meetings.

deployment_id · since? · until? · meeting_id? · limit?

listOpenQuestions

Questions raised in meetings, whether or not they have been resolved, with status open | resolved.

deployment_id · since? · until? · meeting_id? · limit?

listActionItems

Action items and their assignees, with status open | done.

deployment_id · status? · assignee_entra_id? · since? · until? · meeting_id? · limit?

listStatements

Attributed statements made in a meeting. High volume — scope by date or meeting.

deployment_id · since? · until? · meeting_id? · limit?

listTopics

Topics discussed — accounts, projects and themes — each with its topic_kind, the number of meetings that touched it (meeting_count), and last_referenced_at.

deployment_id · limit?

searchMemory

Semantic + keyword search across decisions, open questions, action items and statements. Each type is searched on its own — limit applies per type — and the results are merged by score, a relevance score that compares results within one response and is not a probability. There is no meeting filter.

deployment_id · query · types? · since? · until? · limit?

getMeeting

One meeting with its identified participants and counts of its decisions, open questions and action items.

meeting_id · deployment_id

Every id — deployment, meeting and record — is a GUID; anything else is refused. Every record — a decision, open question, action item or statement — carries attribution — a Microsoft Entra platform identity, or anonymous — plus created_at, deployment_id and origin. A topic carries neither attribution nor origin. An entra_id is the person’s Entra object ID where MeetCrew knows it and their email address otherwise, so don’t validate it as a GUID. A decision’s status is recorded, confirmed or superseded, and it lists its participants; an action item carries assignee and due_date; a decision or open question with a note carries it as note. origin is extracted when MeetCrew took the record from a meeting, and external when it was created through an Action or the MeetCrew console; an external action item may have no meeting_id. A record an Action or the console has changed also carries externally_updated_at. No voiceprints are ever used for attribution. limit is at most 1000 and defaults to 100. There is no pagination: next_cursor is always null, and was_capped is true when rows were left behind — narrow since, until or meeting_id rather than asking for more.

Actions v1

createActionItem

Create an action item from what the meeting decided.

deployment_id · text · assignee_entra_id? · due_date? · meeting_id?

updateActionItem

Change status open | done, reassign, or set a due date.

deployment_id · action_item_id · status? · assignee_entra_id? · due_date? · clear_due_date?

resolveOpenQuestion

Mark an open question resolved (or reopen it), with an optional note.

deployment_id · open_question_id · status · note? · clear_note?

updateDecision

Move a decision to confirmed or superseded, with an optional note.

deployment_id · decision_id · status · note? · clear_note?

Actions are confined to workflow state on action items, decisions, and open questions. There is no delete, and no action can alter a transcript, a statement, provenance, or the audit log. Every action is authenticated, tenant- and deployment-scoped, and logged. An action returns only { "id", "applied": true } — on a create, the new record’s id — so read the record back to see its new state. An explicit null in an optional argument is the same as leaving it out, here and over REST alike: it never clears anything. To remove a due date or a note, send clear_due_date or clear_note.

REST — the same memory, ordinary HTTP v1

Base https://api.meetcrew.ai/v1. Every route is deployment-scoped, and the tenant is never in the path — it comes from the token. Responses carry the same records as the MCP tools above, field for field.

GET /deployments

The named teammates this principal may reach, with the scope of each grant — read or read_write.

GET /deployments/{deployment_id}/decisions

Decisions recorded across meetings.

since? · until? · meeting_id? · limit?

GET /deployments/{deployment_id}/open-questions

Questions raised in meetings, resolved or not, each with status open | resolved.

since? · until? · meeting_id? · limit?

GET /deployments/{deployment_id}/action-items

Action items and their assignees.

status? · assignee_entra_id? · since? · until? · meeting_id? · limit?

GET /deployments/{deployment_id}/statements

Attributed statements made in a meeting.

since? · until? · meeting_id? · limit?

GET /deployments/{deployment_id}/topics

Topics discussed — accounts, projects and themes.

limit?

GET /deployments/{deployment_id}/search

Semantic and keyword search across decisions, open questions, action items and statements, in relevance order. limit applies per type; there is no meeting filter.

q · types? · since? · until? · limit?

GET /deployments/{deployment_id}/meetings/{meeting_id}

One meeting with its identified participants and counts of its decisions, open questions and action items.

POST /deployments/{deployment_id}/action-items

Create an action item. Answers 201 with { "id", "applied": true }, where id is the new item’s. There is no single-record read yet: find it with GET …/action-items.

text · assignee_entra_id? · due_date? · meeting_id?

PATCH /deployments/{deployment_id}/action-items/{action_item_id}

Change status open | done, reassign, or set a due date.

status? · assignee_entra_id? · due_date? · clear_due_date?

PATCH /deployments/{deployment_id}/open-questions/{open_question_id}

Mark an open question resolved, or reopen it.

status · note? · clear_note?

PATCH /deployments/{deployment_id}/decisions/{decision_id}

Move a decision to confirmed or superseded.

status · note? · clear_note?

PATCH rather than PUT, because none of these replaces a record: only workflow state can change. On an action item every field is optional, but at least one must be present; on an open question or a decision status is required. Each answers 200 with { "id", "applied": true }. A parameter or body field we don’t recognise is refused, not ignored — a dropped filter would return more than you asked for, and a dropped field would mean a change you believe you made didn’t happen.

Errors, limits and versioning

Over REST, a failure MeetCrew’s own handlers produce is an RFC 9457 problem document. Three answer with an empty body instead: a token that fails validation (401), the rate limit (429), and an id in the path that is not a GUID (404, because no route matches). Over MCP, once the token and the rate limit are past, a failure is a JSON-RPC error inside an HTTP 200: -32602 for invalid arguments, refused access and records that don’t exist, -32603 where REST would answer 502 or 503, -32601 for an unknown tool, resource or method, and -32600 or -32700 for a request that is not a single valid JSON-RPC object. A notification is answered 202 with no body. Match on the status or error code, never on the message text — wording can change without notice. Over MCP that means -32602 cannot tell a refusal from a missing record; if your agent must, use REST.

400

The request is invalid: a parameter or body field is missing, malformed, out of range, or not one this endpoint recognises — or memory refused the change as invalid.

401

The token was refused. An expired token, or one issued for a different audience, answers with an empty body and a WWW-Authenticate challenge. A token with no usable tid is refused the same way. A token that is not app-only (idtyp must be app) or carries no usable oid answers with a problem document, “Token is missing the claims MeetCrew authorizes on”. Request it with the client-credentials flow for a service principal.

403

No active grant for that deployment, or the grant is read-only and the call would change memory. A deployment that doesn’t exist answers identically, on purpose — the status code is not a way to discover what a tenant has. A 403 also means your organization has not accepted the current Terms of Service; a Tenant Administrator accepts them in the admin console.

404

No such record inside the deployment you’re authorized for — or, with an empty body, an id in the path that is not a GUID.

429

Over the rate limit: 600 requests per minute per service principal, across both endpoints. The body is empty; honour Retry-After.

502

A change was not applied — MeetCrew’s own upstream refused the call. Retrying will not help; tell us.

503

On a read, memory was unreachable. This is not an empty result — retry rather than concluding the teammate remembers nothing. On a write, the outcome is unknown and may have been applied: read the record back before repeating it.

Calls on both endpoints are logged with the Entra identity that made them. The audit archive keeps every action as its own event and reads as a daily record of which identity read which teammate’s memory, and the two are retained differently, which matters when you are answering a question about something months old. Trust & Security has the retention periods.

Within v1 we add, we don’t remove: new fields, parameters, endpoints and enum values can appear at any time, so ignore what you don’t recognise rather than failing on it. Nothing is renamed or removed, and no status code changes meaning. A breaking change means a new prefix served alongside this one. Our policy is to give the administrator who issued your grant 90 days’ notice by email before deprecation, and at least 180 days more before v1 stops answering.

Example — search memory

// MCP tools/call
{
  "name": "searchMemory",
  "arguments": {
    "deployment_id": "8f14e45f-ceea-467a-9575-8b3d4c2f1a90",
    "query": "pricing decision",
    "types": ["decision", "open_question"],
    "since": "2026-06-01",
    "limit": 2
  }
}
// result.structuredContent
{
  "results": [
    {
      "id": "c3e7a1d4-5b29-4f80-9a6e-1d2c8b7f0e35", "type": "decision",
      "text": "Hold list pricing flat through Q3; revisit at QBR.",
      "created_at": "2026-06-30T16:20:00+00:00", "decided_at": "2026-06-30T16:20:00+00:00",
      "deployment_id": "8f14e45f-ceea-467a-9575-8b3d4c2f1a90",
      "meeting_id": "4823ab90-77c1-4e2f-9d5a-6b0e3f8c1d24",
      "origin": "extracted",
      "attribution": { "kind": "platform_identity", "display_name": "Priya Shah",
                       "entra_id": "3b9e6c21-7d4f-4a08-9e5b-c1f2a7d80e46" },
      "participants": [
        { "kind": "platform_identity", "display_name": "Priya Shah",
          "entra_id": "3b9e6c21-7d4f-4a08-9e5b-c1f2a7d80e46" },
        { "kind": "platform_identity", "display_name": "Dana Ruiz",
          "entra_id": "f4d81b07-62ac-4e95-b3d0-8a7e2c19f564" }
      ],
      "status": "recorded", "score": 8.42
    },
    {
      "id": "6a0b9e12-84d3-4c57-b1f8-03e9d5a2c764", "type": "open_question",
      "text": "Do enterprise renewals get the same flat-pricing treatment?",
      "created_at": "2026-06-30T16:24:00+00:00", "raised_at": "2026-06-30T16:24:00+00:00",
      "deployment_id": "8f14e45f-ceea-467a-9575-8b3d4c2f1a90",
      "meeting_id": "4823ab90-77c1-4e2f-9d5a-6b0e3f8c1d24",
      "origin": "extracted",
      "attribution": { "kind": "platform_identity", "display_name": "Marco Bianchi",
                       "entra_id": "a07c5d92-1e3b-4f6a-8c24-5b9d0e7f3a18" },
      "status": "open", "score": 5.17
    }
  ],
  "was_capped": false,
  "next_cursor": null
}

Example — close an action item

// MCP tools/call
{
  "name": "updateActionItem",
  "arguments": {
    "deployment_id": "8f14e45f-ceea-467a-9575-8b3d4c2f1a90",
    "action_item_id": "e5d2f871-0c4a-4b96-8d13-9f7a2c6b4e08",
    "status": "done"
  }
}
// result.structuredContent — the change applied; read the item back to see its new state
{ "id": "e5d2f871-0c4a-4b96-8d13-9f7a2c6b4e08", "applied": true }

Example — the same two calls over REST

Same token, same records. Only the envelope differs.

# search
curl -H "Authorization: Bearer $TOKEN" \
  "https://api.meetcrew.ai/v1/deployments/8f14e45f-ceea-467a-9575-8b3d4c2f1a90/search?q=pricing+decision&types=decision,open_question&since=2026-06-01&limit=2"

# close an action item
curl -X PATCH -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"status":"done"}' \
  "https://api.meetcrew.ai/v1/deployments/8f14e45f-ceea-467a-9575-8b3d4c2f1a90/action-items/e5d2f871-0c4a-4b96-8d13-9f7a2c6b4e08"
// the search answers 200 with the same body as the MCP result above, field for field
// the PATCH answers 200 with
{ "id": "e5d2f871-0c4a-4b96-8d13-9f7a2c6b4e08", "applied": true }
Agent backend contract

MeetCrew calls your agent.

Register your backend per deployment. This section is the contract for a custom webhook; an OpenAI-compatible endpoint receives a standard chat-completions request instead, and Copilot Studio and Microsoft Foundry are called through their own APIs. When the teammate is addressed, MeetCrew POSTs a neutral request — a system prompt, the question just asked, with up to five earlier exchanges with this teammate in the same meeting (not the meeting transcript), the tools MeetCrew exposes, and correlation metadata — and speaks the content you return. Your budget for the round trip arrives on metadata.timeout_ms: 15s, one platform-wide setting rather than a per-deployment one. A call that follows a tool result gets the same budget again. Aim well under it — the teammate is speaking in real time. If the budget expires it speaks a brief fallback, so the meeting never hangs.

Request — MeetCrew → your backend

{
  "system": "You are Jim, a renewals-focused colleague on this call...",
  "messages": [
    { "role": "user",
      "content": "Jim, did we ever close the pricing decision from last week?" }
  ],
  "tools": [
    { "name": "meetcrew_memory_query_semantic",
      "description": "Search this teammate's structured meeting memory...",
      "parameters_schema": {
        "type": "object",
        "properties": {
          "record_type": { "type": "string",
            "enum": ["statement", "decision", "open_question", "action_item"] },
          "natural_language_query": { "type": "string" },
          "max_results": { "type": ["integer", "null"] }
        },
        "required": ["record_type", "natural_language_query", "max_results"],
        "additionalProperties": false
      } }
  ],
  "metadata": {
    "deployment_id": "8f14e45f-ceea-467a-9575-8b3d4c2f1a90",
    "invocation_id": "9f2c1b7e-3a44-4d18-b0c6-27e5a1d99f31",
    "meeting_id": "4823ab90-77c1-4e2f-9d5a-6b0e3f8c1d24",
    "timeout_ms": 15000
  }
}

Response — your backend → MeetCrew

{
  "content": "Yes — last week you decided to hold list pricing flat through Q3 and revisit at the QBR. Priya owns the follow-up.",
  "tool_calls": null,
  "finish_reason": "stop",
  "metadata": { "latency_ms": 820, "tokens_used": 143 }
}

Auth: an HMAC-SHA256 signature over the raw request body, keyed by a per-deployment shared secret and sent as X-Janus-Signature: sha256=<lowercase-hex>. You enter the secret once in the admin console, and MeetCrew never shows it again. The endpoint must be https. content is what the teammate speaks. To use a tool MeetCrew declared, return tool_calls, each entry { "id", "name", "arguments" } — on a webhook, tool_calls alone starts the round and finish_reason may be left out; an OpenAI-compatible stream must end with finish_reason: "tool_calls". MeetCrew runs the tool and calls you back with two more messages, an assistant message carrying your tool_calls and a tool message carrying the result and its tool_call_id, so you can compose the final reply. Read the tools array on each request rather than hard-coding it: the example shows one tool, and the set offered can vary. Tool names carry the meetcrew_ prefix; a backend still returning a tool name from before October 2026 keeps working until 3 January 2027. A webhook’s response body is capped at 1 MB. MeetCrew calls a webhook once, without streaming and without retrying; an OpenAI-compatible endpoint is streamed, and a call that cannot connect or answers 5xx or 429 is retried once.

Quickstart

First 15 minutes.

Zero to a teammate answering in a test meeting, and your agent reading that meeting’s memory over MCP.

  1. Sign in to the admin console as a MeetCrew Tenant Administrator. There is no region to choose: every tenant is hosted today in Microsoft Azure’s US East region.
  2. Create a deployment — name the teammate (say, “Jim”), set its wake word, and pick a character and voice. The meeting platform comes from the meeting link when you launch the teammate. This provisions memory scoped to Jim’s deployment, identified by a GUID such as 8f14e45f-ceea-467a-9575-8b3d4c2f1a90.
  3. Choose Custom webhook as the backend, and enter its endpoint and webhook signing secret. The secret is write-only: afterwards the console shows at most its last four characters.
  4. Stub the backend: return { "content": "Hi, I'm Jim." } and confirm it answers inside the budget on metadata.timeout_ms.
  5. Admit the teammate into a test meeting. Confirm the disclosure banner shows Jim as AI.
  6. Say “Jim, are you there?” and hear the stubbed reply. The backend contract now works end to end.
  7. Switch the backend to your real agent — Copilot Studio, Microsoft Foundry, an OpenAI-compatible endpoint, or your own webhook — with that backend’s credential. A webhook composes its reply from system + messages.
  8. Authorize MeetCrew in your Microsoft Entra directory: Workspace → Authorize MeetCrew in Microsoft Entra. It takes a Global Administrator or Privileged Role Administrator, once per organization, and the card gives you a link to send one. Skip it and your agent’s token request fails with AADSTS500011.
  9. Grant your agent MCP access — a Tenant Administrator creates a service-principal grant in the console, using the Object ID of your agent’s Enterprise application. Choose read and write if your agent will use the actions; read-only is the default, and the four actions are refused under it.
  10. Request an app-only token from your own tenant’s token endpoint with scope api://569124d5-6864-418d-91b6-8e0f668440ae/.default, and connect your MCP client to https://mcp.meetcrew.ai/v1 with it. List meetcrew://deployments and confirm Jim’s deployment_id appears.
  11. Call listDecisions with that deployment_id, then getMeeting with a meeting_id from one of the decisions. Your agent is now reading cross-meeting memory. Ship from here.

Ready to wire it up?

Start a pilot and we’ll set up a deployment, connect your backend, and issue an MCP grant with you.