Automate deployment with the ARM API
Use the App Service Builder ARM API to create an app resource and deploy from GitHub source or an uploaded ZIP.
Use this guide when your automation needs raw ARM REST requests rather than Portal or Builder CLI.
It uses Microsoft.Web/builderApps with api-version=2026-09-01-preview.
ARM authentication and GitHub repository authorization are separate.
For a first deployment, start with Portal or Builder CLI.
ARM and Bicep infrastructure templates provision resources, unlike the REST deployment action shown here.
Prerequisites
- Preview access, provider availability, an authorized subscription and resource group, and a qualified location confirmed by your preview contact. Use development/test workloads only.
- An Azure Resource Manager bearer token for the authorized Microsoft Entra account and an authenticated ARM client.
- For GitHub deployment: GitHub user access and source integration installation access to your selected repository. ZIP deployment uses an archive instead; see Deploy ZIP source.
Prepare GitHub source
For ZIP deployment, go to Deploy ZIP source.
If you arrived from a quickstart or tutorial, keep its selected fork, branch, and root builder.yaml.
Otherwise prepare source using Node.js, Python, .NET, PHP guidance, or static HTML/Vite, or choose another published app shape from the sample catalog.
Fork the selected published repository to your account.
Clone your fork and push your changes.
Only for an HTML-only app, a root builder.yaml with role: static, output: public, and path: /, plus public/index.html, is sufficient.
Do not replace a web or Vite manifest with that static example.
Keep builder.yaml at the fork's repository root and use rootDirectory: ".".
Ensure the source integration is installed with access to your fork; use its repository ID and branch below.
Obtain the numeric repository ID and a GitHub user credential authorized for it, or a target-bound source authorization token through the supported source connection flow.
Keep credentials out of checked-in request files and logs.
For PHP 8.5, keep default startup with no run.start and use /health.php.
See the PHP web manifest for source-root and document-root details.
Create and connect
Send this request using safe placeholder replacement in your client:
PUT https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/builderApps/<app-name>?api-version=2026-09-01-preview
Authorization: Bearer <arm-access-token>
Content-Type: application/json
{
"location": "<qualified-location>",
"properties": {
"source": {
"provider": "GitHub",
"id": "<numeric-repository-id>",
"displayName": "<owner>/<repository>",
"reference": "<branch>",
"rootDirectory": ".",
"repositoryToken": "<authorized-github-user-token>"
}
}
}
repositoryToken is write-only.
Use the numeric ID, <owner>/<repository>, and <branch> belonging to your selected fork.
Do not supply it together with authorizationToken.
Read the app back and confirm properties.sourceIntegrationState is Configured before deployment.
Creating the resource does not itself deploy it.
Request deployment
POST https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/builderApps/<app-name>/deploy?api-version=2026-09-01-preview
Authorization: Bearer <arm-access-token>
Content-Type: application/json
{ "idempotencyKey": "<unique-request-id>" }
Save the response's deploymentId, Azure-AsyncOperation URL, and Retry-After header.
Reuse the same request ID only for retries of this same deployment intent.
Wait and browse
Perform authenticated GET requests to the returned Azure-AsyncOperation URL, respecting Retry-After.
Continue until the operation reports Succeeded, Failed, or Canceled.
If it fails, inspect the returned failure information rather than treating the initial acceptance as success.
GET the app resource again:
GET https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/builderApps/<app-name>?api-version=2026-09-01-preview
Authorization: Bearer <arm-access-token>
After successful deployment, open properties.runtime.url.
Check properties.runtime.activeAppVersionId and activeDeploymentId to identify what is serving.
Portal Versions and Deployments, or Builder CLI history commands, provide build and deployment details.
Deploy ZIP source
Use ZIP deployment when your source is on your computer or produced by another build workflow. This uploads source for Builder to build; it is not an upload of a ready-to-run application package. The Portal does not provide a ZIP deployment flow. For a terminal walkthrough, use Deploy ZIP source with Builder CLI.
-
Create a Builder app resource using the PUT above with an available
locationand"properties": {}, or use an existing app. ZIP deployment does not require a GitHub connection and does not change one already saved. -
Package an ordinary unencrypted ZIP with
builder.yamlat its root. Include the app files, not a parent directory around them. The ZIP must be no larger than 100 MiB; the manifest must be no larger than 1 MiB. Keep credentials and unrelated files out of the archive. -
Begin an upload session with the exact manifest text, archive byte count, and lowercase SHA-256 digest. Use one UUID as
<request-id>for retries of this upload and deployment.POST https://management.azure.com/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Web/builderApps/<app-name>/beginSourceUpload?api-version=2026-09-01-preview
Authorization: Bearer <arm-access-token>
Content-Type: application/json
{
"idempotencyKey": "<request-id>",
"manifestYaml": "<exact-builder.yaml-text-as-a-JSON-string>",
"contentLength": 12345,
"sha256": "<64-character-lowercase-sha256>"
}Replace
12345with the ZIP's actual byte count. Serialize the actual manifest as a JSON string; do not normalize its line endings or encoding. Save the returnedartifactId,uploadUrl,uploadDeadline, anduncommittedDeadline. -
Before
uploadDeadline, PUT the ZIP bytes to the returneduploadUrl. UseContent-Type: application/zip, the exactContent-Length, andAuthorization: Bearer <arm-access-token>. Use the same signed-in account that began the session. The URL alone does not grant upload access; keep the token out of files and logs. -
After upload succeeds, request deployment with that session's ID, digest, and byte count:
{
"idempotencyKey": "<request-id>",
"source": {
"kind": "uploadedArtifact",
"artifactId": "<artifact-id>",
"sha256": "<64-character-lowercase-sha256>",
"contentLength": 12345
}
}POST this body to the app's
/deploy?api-version=2026-09-01-previewaction beforeuncommittedDeadline. Do not combinesourcewithcommitSha,rebuild, orversionId. -
Follow the returned
Azure-AsyncOperationURL as described in Wait and browse, then verify the app URL. Upload success is not build or deployment success. The manifest inside the ZIP must match the text supplied when beginning the session; a mismatch or invalid ZIP fails deployment withSourceUploadArchiveInvalid.
If an upload response is lost, repeat the begin-session request with the same body and request ID to inspect its state.
If it is uploading, wait and check again rather than sending another PUT.
After a lost deployment response, follow the existing operation or replay the identical request with the same ID; do not start an unrelated deployment to discover the outcome.
See the ZIP API reference for fields, deadlines, and error semantics.
Clean up resources
DELETE the same app URL when you no longer need it.
Track the returned asynchronous deletion operation before treating cleanup as complete.
If resource cleanup is blocked, the app remains in Deleting and Builder retries automatically with increasing delays.
Follow the existing operation rather than repeatedly submitting DELETE requests.
When a retryable response includes Retry-After, wait for the indicated delay before retrying.
Retrying a request does not reset the cleanup cooldown.
Do not delete the resource group or user-assigned identities just to remove the app.
Related content
The ARM reference covers PATCH semantics, actions, authentication configuration, and concurrency. Source control explains repository authorization; deployments distinguishes building from activation. Provision with ARM or Bicep explains infrastructure templates separately from app deployment.