See how we built our intranet. Live + Q&A, June 30

Trigger Azure Pipeline build from Sanity Studio webhook

2 repliesLast updated: Dec 1, 2025

I can't seem to find any info on triggering a azure pipeline build when something has been edited in sanity studio. I have done the same thing with netlify and that works like a breeze but the current project require me to use azure.
AI Update

Triggering an Azure Pipeline build from Sanity Studio content changes is definitely achievable! Since you've got this working with Netlify, the Azure approach is similar conceptually but requires using the Azure DevOps REST API since Azure Pipelines doesn't have built-in webhook triggers like Netlify does.

The Correct Approach: Sanity Webhook → Azure DevOps REST API

Unlike Netlify's native webhook support, Azure Pipelines requires you to call its REST API to trigger builds. Here's the proper setup:

1. Create a Personal Access Token (PAT) in Azure DevOps

First, you need authentication credentials:

2. Set Up the Sanity Webhook

Go to your Sanity project settings → API → Webhooks, and create a new webhook with:

URL: Use the Azure DevOps REST API endpoint to trigger a pipeline run:

https://dev.azure.com/{organization}/{project}/_apis/pipelines/{pipelineId}/runs?api-version=7.1

Replace:

HTTP Method: POST

HTTP Headers: Add authentication:

Authorization: Basic {base64-encoded-pat}

To create the base64-encoded PAT, encode :{your-pat} (colon followed by your token). Many online tools can do this, or use:

echo -n ":{your-pat}" | base64

Trigger on: Select Create, Update, and/or Delete based on your needs

Filter: Use a GROQ filter to control which content changes trigger builds. For example:

_type == "post"

Payload: You can customize the JSON payload using GROQ projections, but for Azure Pipelines, you typically just need to trigger the build. The default payload works fine, or use a minimal one:

{
  "resources": {
    "repositories": {
      "self": {
        "refName": "refs/heads/main"
      }
    }
  }
}

If you need more control, security, or custom logic, consider using an Azure Function or other serverless function as middleware:

Sanity Webhook → Azure Function → Azure Pipeline

This approach gives you:

Here's a basic Azure Function example:

module.exports = async function (context, req) {
    const sanitySignature = req.headers['x-sanity-signature'];
    
    // Verify webhook signature (recommended)
    // Use @sanity/webhook package
    
    // Trigger Azure Pipeline
    const pipelineUrl = `https://dev.azure.com/${org}/${project}/_apis/pipelines/${pipelineId}/runs?api-version=7.1`;
    
    const response = await fetch(pipelineUrl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Basic ${Buffer.from(':' + process.env.AZURE_PAT).toString('base64')}`
        },
        body: JSON.stringify({
            resources: {
                repositories: {
                    self: {
                        refName: 'refs/heads/main'
                    }
                }
            }
        })
    });
    
    context.res = {
        status: response.ok ? 200 : 500,
        body: await response.text()
    };
};

4. Consider Sanity Functions (Modern Alternative)

If your use case allows, Sanity Functions provide a serverless compute environment within Sanity itself. You could use a Function to handle the webhook logic and call the Azure DevOps API directly, eliminating the need for external hosting:

// sanity.blueprint.ts
import {defineBlueprint} from 'sanity/blueprint'

export default defineBlueprint({
  functions: [
    {
      name: 'trigger-azure-build',
      on: {
        documentEvent: {
          filter: '_type == "post"',
          events: ['create', 'update']
        }
      },
      handler: async ({event}) => {
        // Call Azure DevOps REST API
        const response = await fetch(/* Azure pipeline URL */, {
          method: 'POST',
          headers: {/* auth headers */}
        });
        return {success: true};
      }
    }
  ]
});

This requires a Growth plan or higher but provides native integration without managing external webhooks.

Debugging Tips

Helpful Headers from Sanity

Sanity automatically includes these headers with webhook requests that you can use for logging or conditional logic:

For more details on configuring webhooks, check out the Sanity webhooks documentation and guides on GROQ-powered webhook filtering.

Show original thread
2 replies

Was this answer helpful?

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Related contributions