Salesforce Metadata API
Everything you need to retrieve and deploy customizations safely: package.xml, sf CLI, validation-only deploys, test runs, and CI/CD patterns.
Deploy Safety
Validate before deploy
Automation
CI/CD friendly
Coverage
Wide metadata types
Overview: why the Salesforce Metadata API
The Metadata API lets teams treat org configuration as versionable, deployable assets. Itβs the backbone for moving CustomObjects, Apex classes, Flows, Profiles, PermissionSets, Layouts and more across dev/test/prod. With validation-only deploys and test execution, you reduce risk and increase release confidence.
Metadata API vs Tooling API vs REST
| Capability | Metadata API | Tooling API | REST/Composite |
|---|---|---|---|
| Primary use | Deploy/retrieve metadata | Developer tooling & IDEs | Data & some config records |
| Best for | Packages, sandboxes, prod | Live edits, diagnostics | CRUD on records/integration |
| Granularity | Types & members via package.xml | Object-level via tooling objects | Record-level operations |
| CI/CD fit | Excellent | Good for checks | Good for data/ETL |
Authentication & environments
SFDX (sf CLI) login
Authorize orgs
# Web login
sf org login web --alias MySandbox# JWT (CI use)
sf org login jwt --client-id <consumerKey> --jwt-key-file server.key --username user@example.com --alias CI_SBXUse separate aliases for each environment (DEV, INT, UAT, PROD).
package.xml essentials
package.xml lists metadata types and members for the Metadata API. Wildcards (*) include all members of a type; explicit names give you precision. API version should match your target org capabilities.
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>ApexClass</name>
</types>
<types>
<members>Account-Account Layout</members>
<name>Layout</name>
</types>
<types>
<members>*</members>
<name>CustomObject</name>
</types>
<types>
<members>*</members>
<name>PermissionSet</name>
</types>
<version>59.0</version>
</Package>Retrieve with Metadata API
Retrieve to a folder
Using sf CLI
sf project retrieve start --manifest manifest/package.xml --target-org MySandbox --output-dir mdapi_outOutputs MDAPI format by default; convert to SFDX source as needed.
sf project convert mdapi --root-dir mdapi_out --output-dir force-appRetrieve by metadata type
Ad-hoc pulls
sf project retrieve start --metadata ApexClass --target-org MySandboxYou can also specify members, e.g., --metadata ApexClass:MyClass.
Deploy & validate
Validation-only deploy
Safe first
sf project deploy start --manifest manifest/package.xml --target-org UAT --test-level RunLocalTests --dry-runUse --dry-run (validation) to catch issues early and get a deployment ID.
Final deploy
From validated ID (fast)
sf project deploy resume --use-most-recent --target-org PRODOr resume by ID. Keep --test-level consistent with your orgβs policy.
Pre-deploy checklist
- Lint & unit tests passed
- Profiles/PermissionSets diff reviewed
- Flows/Processes versioned and activation state clear
- Validation-only run succeeded (store the ID)
CI/CD workflows
GitHub Actions (example)
JWT auth + validate + deploy
name: deploy-uat
on:
push:
branches: [ "release/*" ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: salesforcecli/action@v1
- name: Auth JWT
run: |
sf org login jwt --client-id $SF_CONSUMER_KEY \
--jwt-key-file server.key \
--username $SF_USERNAME --alias CI_UAT
- name: Validate
run: |
sf project deploy start --manifest manifest/package.xml \
--target-org CI_UAT --test-level RunLocalTests --dry-run
- name: Deploy (resume)
if: success()
run: |
sf project deploy resume --use-most-recent --target-org CI_UATCommon pitfalls
Save hours during releases
- Mismatched API version in
package.xmlvs target org - Profiles too broad β prefer PermissionSets
- Flow version conflicts β deactivate old, deploy new
- Tests relying on org data β seed data or use factories
Images & attachments: quick privacy tip
If your releases include image assets (Experience Cloud, Knowledge, Email templates), remove sensitive EXIF/GPS or authoring traces before uploading files to Salesforce. A quick, browser-only pass helps teams avoid leaking locations or personal data in public content.
FAQ
Keep releases clean & private
Validate metadata, automate deployments, and sanitize image files used in your orgβs content. One last step: remove hidden EXIF/GPS before publishing.