Publish local APIM artifacts to an Azure API Management instance.
apiops publish --resource-group <rg> --service-name <name> [options]apiops publish \
--subscription-id 00000000-0000-0000-0000-000000000000 \
--resource-group my-rg \
--service-name my-apimapiops publish \
--resource-group my-rg \
--service-name my-apim \
--overrides ./configuration.prod.yamlapiops publish \
--resource-group my-rg \
--service-name my-apim \
--dry-runapiops publish \
--resource-group my-rg \
--service-name my-apim \
--commit-id abc123def456apiops publish \
--resource-group my-rg \
--service-name my-apim \
--filter ./configuration.extractor.yamlThe filter uses the same YAML format as apiops extract --filter. Referenced named values,
backends (including backend pool members), policy fragments, and version sets are included by
default; use --no-transitive to publish only exact matches. Product, gateway, and subscription
links do not pull their API or Product targets into the publish set.
apiops publish \
--resource-group my-rg \
--service-name my-apim \
--delete-unmatchedapiops publish \
--resource-group my-rg \
--service-name my-apim \
--dry-run \
--format json| Flag | Type | Default | Required | Description |
|---|---|---|---|---|
--resource-group <rg> |
string | — | Yes | Azure resource group name |
--service-name <name> |
string | — | Yes | APIM service instance name |
--source <dir> |
string | ./apim-artifacts |
No | Source directory containing artifacts |
--overrides <path> |
string | — | No | Override configuration YAML file |
--filter <path> |
string | — | No | Filter YAML file shared with extract |
--no-transitive |
boolean | false |
No | Publish only exact filter matches |
--commit-id <sha> |
string | env: COMMIT_ID |
No | Git commit SHA for incremental publish |
--dry-run |
boolean | false |
No | Preview changes without applying |
--delete-unmatched |
boolean | false |
No | Delete APIM resources absent from source, or removed by an incremental commit |
Note:
--filterand--commit-idcan be combined.--delete-unmatchedcannot be combined with--filter; with--commit-id, it explicitly enables commit-scoped deletions.
| Flag | Type | Default | Description |
|---|---|---|---|
--subscription-id <id> |
string | env: AZURE_SUBSCRIPTION_ID |
Azure subscription ID (required) |
--log-level <level> |
string | info |
Log level: debug, info, warn, error |
--format <type> |
string | text |
Output format: text or json |
--cloud <name> |
string | public |
Sovereign cloud: public, china, usgov, germany |
--client-id <id> |
string | — | Service principal client ID |
--client-secret <secret> |
string | — | Service principal client secret |
--tenant-id <id> |
string | — | Azure AD tenant ID |
apiops publish authenticates using DefaultAzureCredential, which tries credentials in this order:
- Managed Identity
- Workload Identity
- Service Principal (via
--client-id,--client-secret,--tenant-id) - Azure CLI (
az login)
See the authentication guide for details.
Overrides let you replace environment-specific values (URLs, secrets, connection strings) at publish time without modifying the artifact files. This is the key mechanism for promoting artifacts across dev → staging → production.
Pass an override YAML file with --overrides:
# configuration.prod.yaml
namedValues:
- name: api-key
properties:
value: "prod-api-key-value"
- name: secret-from-keyvault
properties:
keyVault:
secretIdentifier: "https://prod-kv.vault.azure.net/secrets/my-secret"
identityClientId: "00000000-0000-0000-0000-000000000000"
backends:
- name: backend-api
properties:
url: "https://prod-api.example.com"
apis:
- name: echo-api
properties:
serviceUrl: "https://prod-echo.example.com"
diagnostics:
- name: applicationinsights
properties:
loggerId: "appinsights-logger-prod"
loggers:
- name: appinsights-logger
properties:
resourceId: "/subscriptions/xxx/resourceGroups/prod-rg/providers/microsoft.insights/components/prod-appinsights"| Resource type | Overridable properties |
|---|---|
namedValues |
value, keyVault.secretIdentifier, keyVault.identityClientId |
backends |
url |
apis |
serviceUrl |
diagnostics |
loggerId |
loggers |
resourceId |
Resource names are matched by each list item's name. Only values in properties are overridden.
Resources are published in dependency order using topological sorting. For example, backends and named values are created before the APIs that reference them. This ensures references are valid at every step.
When --commit-id is provided, apiops publish uses git diff to identify which artifact files changed since that commit. Only the affected resources are published, which speeds up deployments significantly.
In CI/CD pipelines, this is typically set automatically:
# GitHub Actions example
- run: npx apiops publish --commit-id ${{ github.event.before }}Tip: Incremental publish is non-destructive by default. Add
--delete-unmatchedto delete resources removed by the selected commit; omit--commit-idfor a full unmatched-resource cleanup.
Use --dry-run to preview what would happen without making any changes to Azure:
apiops publish \
--resource-group my-rg \
--service-name my-apim \
--dry-runThe output lists each resource and the planned action (create, update, or delete). With --format json, the dry-run report is machine-readable — useful for approval gates in CI/CD pipelines.
For a full publish, --delete-unmatched deletes APIM resources that are not present in the source artifacts. With --commit-id, it deletes only resources and Product associations removed by the selected commit.
Warning: Use with caution. Resources created manually in the Azure portal that are not in your artifact directory will be removed.
| Code | Meaning |
|---|---|
0 |
Success — all resources published |
1 |
Partial — some resources failed to publish |
2 |
Fatal — publish could not proceed |
- apiops extract — extract APIM configuration to local files
- apiops init — scaffold a repository with CI/CD pipelines
- Authentication guide
- Environment overrides guide
- GitHub Actions integration
- Azure DevOps integration