Skip to content

Case Study

Microsoft Teams Auto-Archive

How a finished Microsoft Teams meeting became a video in the right Vimeo folder, and how the integration recovered when notifications repeated, files arrived late, or access changed.

4 min read
Enterprise Integrations · OAuth · Webhooks · Async Processing · Microsoft Teams
A Microsoft Graph recording notification moving through verification, processing, and folder placement in Vimeo.
Company
Vimeo
Role
Senior Software Engineer
Team
Integrations
Period
2023 to 2026
Scope
Technical lead from product requirements through production support
Stack
Microsoft Graph · Kafka · OAuth 2.0 · Webhooks
On this page (10)

What the customer experiences

A customer connects a Microsoft 365 tenant, which is the account boundary for their organization, and chooses a folder in their Vimeo video library. After an allowed person finishes a Teams meeting, the recording appears in that folder. Nobody has to download the file, wait for it, and upload it again.

That is also how Vimeo describes the public product: Teams recordings are sent to a designated folder after the meeting ends. This case study follows the story behind that quiet hand-off: Microsoft announces that a recording exists, the integration discovers and transfers it, and Vimeo places it where the customer asked.

Why the hand-off is difficult

Microsoft Graph is Microsoft's programmatic interface, or API, for Microsoft 365. It does not send a video file when a meeting ends. It sends a small HTTP message called a change notification when a recording becomes available. The standing request for those messages is called a subscription. Subscriptions expire, notifications may contain encrypted recording details, and the video file may still need time before it can be fetched.

The system therefore has to keep three promises at once:

  • maintain the tenant's authorization, or granted permission, and subscription over time;
  • accept a notification quickly, even when the recording is not ready;
  • place one recording in one Vimeo destination when delivery is retried.

The dangerous failures are quiet. An expired subscription produces no event. An unmapped user gives the system no safe destination. A duplicate notification looks valid unless the recording has a stable identity throughout the flow.

Four ideas used in the rest of the story

Webhook

An HTTP request sent by Microsoft Graph to announce a change. It is a notification, not the recording file itself.

Kafka

A durable event log used for the hand-off. It stores accepted work so a recording can wait for a worker without keeping the webhook request open.

Consumer and offset

A consumer is a worker that reads Kafka records. Its offset is the saved position that says how far it has completed.

Idempotency

Repeating the same logical recording operation converges on the same archive result instead of creating another video.

My role

I led the technical work on Vimeo's integrations team. I took the product requirements into design discussions, wrote the technical design, broke the work into deliverable pieces, implemented it with the team, and stayed responsible through onboarding and production support.

What I owned on this integration

  1. Define the contract

    Worked with product and partner teams to turn ‘archive Teams recordings’ into explicit consent, mapping, folder, and failure behavior.

  2. Design the lifecycle

    Specified subscription renewal, notification intake, recording readiness, identity mapping, and retry boundaries.

  3. Build and release

    Implemented the integration with the team, drove technical decisions, and supported customer onboarding.

  4. Operate it

    Handled production issues, monitoring, and the reliability work that followed real failures.

Follow one recording

How to read the diagrams

  • Microsoft Graph, the customer's tenant, and external identities
  • The integration boundary, validation, and recording identity
  • Durable or recoverable progress, including Kafka and its consumers
  • The external recording file and Vimeo upload path
  • A condition that must stop or delay the run

From recording notification to Vimeo folder

  1. recording readyMicrosoft Graph → Webhook receiver

    Change notification

    subscription proof · encrypted recording details

  2. intakeWebhook receiver

    Validate and decrypt

    reject an invalid client state or payload

  3. before HTTP successWebhook receiver → Kafka

    Publish the recording event

    keyed by the recording identity

  4. after the responseKafka → Recording worker

    Deliver to a worker

    the same record may be delivered again

  5. if neededRecording worker

    Wait and retry until the file is available

    not-ready is expected, not data loss

  6. resolvedRecording worker → Vimeo library

    Transfer and place recording

    mapped Vimeo account and chosen folder

  7. durable resultRecording worker → Kafka

    Commit the consumed offset

    only after the outcome is stored

The webhook response and the Kafka offset are separate acknowledgements. Each is sent only after the next durable boundary is safe.

The subscription request makes the tenant boundary concrete. Microsoft documents communications/onlineMeetings/getAllRecordings for tenant-wide recording notifications. It requires the application permission OnlineMeetingRecording.Read.All, supports encrypted resource data, and needs a lifecycle notification URL when the requested lifetime exceeds one hour. In the public request below, clientState is a secret proof that Graph returns with notifications, the certificate lets the receiver decrypt protected recording details, and the lifecycle URL receives warnings about subscription health.

Sketch: tenant-wide recording subscription
POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json
 
{
  "changeType": "created",
  "resource": "communications/onlineMeetings/getAllRecordings",
  "notificationUrl": "https://example.invalid/graph/notifications",
  "lifecycleNotificationUrl": "https://example.invalid/graph/lifecycle",
  "includeResourceData": true,
  "encryptionCertificate": "<public certificate>",
  "encryptionCertificateId": "<certificate id>",
  "expirationDateTime": "<next renewal time>",
  "clientState": "<subscription secret>"
}

The first reliability boundary is intentionally small: validate the notification, hand the recording identity to Kafka, and return success after Kafka accepts it. Fetching and transferring a video can take much longer than a webhook sender will wait. Kafka absorbs bursts and lets consumers retry without keeping the webhook request open.

What Kafka guaranteed here

Kafka made the hand-off durable and replayable. It did not guarantee one and only one Vimeo upload. Kafka and Vimeo do not share one all-or-nothing operation, so the consumer still needs saved state around the recording.

Reconciliation means checking the saved recording state and any result already returned by the outside system before deciding whether another upload is safe.

delivery boundaries
boundary
Microsoft Graph → intake
delivery behavior
The request can be retried
rule that prevents loss or duplication
Return success only after the recording event is accepted by Kafka.
boundary
Kafka → recording consumer
delivery behavior
At least once
rule that prevents loss or duplication
Use the recording identity as the idempotency key and commit the offset after the durable outcome.
boundary
Consumer → Vimeo
delivery behavior
An API timeout can hide whether the upload succeeded
rule that prevents loss or duplication
Check stored state and reconcile an uncertain result before creating another video.
boundary
Retry path
delivery behavior
Temporary failures can produce another attempt
rule that prevents loss or duplication
Every attempt resumes the same recording operation rather than starting a new one.

Idempotency here means that processing the same recording event twice converges on one archive result. It does not mean Kafka suppresses duplicates. The consumer earns that property by using a stable recording key, recording progress, and checking the existing outcome before repeating an outside action such as an upload.

Two authorization decisions

This integration needed both organization-level permission and a person-level mapping. They answer different questions.

the two authorization layers
layer
tenant consent
question it answers
May this integration read recordings for this Microsoft tenant?
what it enables
Application access and recording subscriptions
failure the customer sees
The tenant cannot be connected or renewed
layer
user connection
question it answers
Which Microsoft identity belongs to which Vimeo user?
what it enables
Folder choice and safe library placement
failure the customer sees
The recording needs mapping before it can be placed

Treating these as one generic “connected” flag would hide useful states. A tenant can be authorized while a particular organizer is still unmapped. A user can have a mapping while the tenant grant has expired. The product needs to say which action is required, rather than showing a vague connection error.

The subscription has its own lifecycle

Graph validates the notification endpoint when a subscription is created. Subscriptions expire and need renewal. Notifications with resource data use the certificate supplied at creation, while clientState lets the receiver reject a notification that does not belong to the subscription.

One recording subscription over time

Integration
Microsoft Graph
connect

Create subscription

resource · clientState · encryption certificate

validation

Send validation token

validation

Echo token as plain text

during use

Send recording notifications

resource data may be encrypted

before expiry

Renew subscription

Renewal is part of normal operation. Waiting for an error after expiry is too late because the symptom is silence.

Reliability means making missing progress visible

failure handling
condition
Publishing to Kafka fails
system response
Do not acknowledge the webhook
why
Microsoft Graph can retry; returning success here would lose the recording event.
condition
Graph retries after Kafka accepted the event
system response
Reuse the recording's stable key
why
The second event converges on the existing archive attempt.
condition
A consumer crashes before committing its offset
system response
Kafka delivers the record again
why
The consumer checks durable recording state before repeating the upload.
condition
The recording is not ready
system response
Retry later, waiting longer between attempts
why
Availability lag is a normal Microsoft recording state.
condition
Consent or stored access is revoked
system response
Stop retrying and ask for reconnection
why
Waiting and retrying cannot repair missing permission.
condition
The organizer has no Vimeo mapping
system response
Hold for resolution
why
Guessing a destination can expose a recording to the wrong account.
condition
A subscription approaches expiry
system response
Renew and alert on missing progress
why
No incoming error will announce a silent lapse.

The operational lesson was to monitor expected progress as well as explicit errors. Subscription renewal, event age, unresolved mappings, and recordings stuck before placement each reveal a different break in the customer promise.

Sources