cirrus-metadata
Salesforce Metadata API (SOAP) client for the Cirrus SDK.
This project is in no way affiliated with Salesforce.
cirrus-metadata is the SOAP-Metadata-API sibling of
cirrus (REST) and cirrus-auth (OAuth).
It covers the surfaces that don't exist in the Metadata REST API: file-based
retrieve, the CRUD-Based Calls (createMetadata / readMetadata /
updateMetadata / upsertMetadata / deleteMetadata / renameMetadata),
and the utility surface (listMetadata, describeMetadata,
describeValueType).
Why a SOAP crate in 2026?
Salesforce's Metadata REST API only covers four deployRequest
endpoints (initiate, status, cancel, quick-deploy). Everything else —
including retrieve itself — is SOAP-only and is not deprecated. If you
already have cirrus and only need to ship a .zip to an org,
Cirrus::metadata() (REST) is enough. Reach for cirrus-metadata when
you need anything beyond deployRequest.
Relationship to cirrus and cirrus-auth
- Depends only on
cirrus-auth— nocirrusdependency, so callers that use the SOAP API but not the REST client don't pull in the REST surface. - Re-exports the auth crate as
cirrus_metadata::auth::*, so a stand-alonecirrus-metadatauser can writeuse cirrus_metadata::auth::JwtAuth;without an explicitcirrus-authline inCargo.toml. - Shares the
AuthSessiontrait withcirrus: oneArc<dyn AuthSession>drives both clients side-by-side.
What's covered
- File-based deploy/retrieve —
deploy,check_deploy_status,cancel_deploy,deploy_recent_validation,retrieve,check_retrieve_status, pluswait_for_deploy/wait_for_retrievepolling helpers with configurable timeout and backoff. - CRUD-based calls —
create_metadata,read_metadata,update_metadata,upsert_metadata,delete_metadata,rename_metadata. Up to 10 components per call, per the Metadata API contract. - Utility —
list_metadata,describe_metadata,describe_value_type. - Typed
package.xml— [PackageManifest] builder with the fullMetadataTypetaxonomy and round-trippable XML serialization. - Open-ended escape hatch —
MetadataClient::request_builder()for hand-rolling envelopes against operations the typed surface hasn't modeled, withSoapOperationcarrying the typed call path. - Cross-cutting — retry/backoff via [
RetryPolicy], automaticINVALID_SESSION_IDrefresh against the configuredAuthSession, SOAP fault parsing into typed [MetadataError::SoapFault].
Design principles
- No user-facing types. The 200+ concrete metadata types
(
CustomObject,ApexClass,Flow, …) are caller-supplied XML or generic viaserde. Only platform-contract envelopes are typed. - No legacy surface. Operations Salesforce labels deprecated
(pre-API-31
create/update/delete) are intentionally not exposed. - Doc-driven wire shapes. Every handler ships with wiremock coverage whose request/response bodies match Salesforce's documented examples.
Quick start
[]
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
use StaticTokenAuth;
use ;
use Arc;
async
Errors
MetadataError covers transport failures, SOAP faults
(MetadataError::SoapFault { fault_code, fault_string, .. }), per-component
API errors (MetadataError::Api), envelope parsing failures, and auth
errors (#[from] AuthError). Use ? to propagate from any
AuthSession::access_token call alongside SOAP traffic.
MetadataError is #[non_exhaustive] so future variants don't break
downstream match arms.
Integration tests
Live tests against a real sandbox / Developer Edition / scratch org live
under tests/integration/ and are #[ignore]-gated. They share the
workspace's .env and the same URL safety guard as cirrus and
cirrus-auth — see the workspace-root .env.example.
License
Licensed under the MIT license.