Private preview
Integrate the Provisioning API into your platform Private preview
Use the Provisioning API from your platform backend to connect Providers, provision Resources, and manage paid services for authorized tenants.
Private preview
The Provisioning API is allowlisted during private preview. Contact your Stripe representative or email for access.
During private preview, send the preview API version 2026-09-16.preview in the Stripe-Version header. The API contract can change during the preview. Confirm the enabled request and response contract for your cohort before deployment, tolerate new response fields, and use returned enum values instead of assuming wire spellings.
In this flow, you authenticate with your platform’s Stripe key and use Stripe-Context to act on behalf of an authorized connected account. This guide doesn’t cover direct account integrations.
Before you begin
Before you write code, identify which account makes each request, understand how Stripe scopes Provisioning objects, and confirm which features Stripe has enabled for you. The following sections explain the account model, object scopes and relationships, and the checks to complete before your first write request.
Use the correct account model
Before you register payment methods or provision paid resources for users, complete these setup steps.
| Actor or object | Responsibility |
|---|---|
| Platform account | Authenticates API calls with an approved restricted key or, where required, its platform secret key. |
| Platform tenant | Your durable authorization boundary, such as a workspace or organization. |
| Connected account | The Stripe account that owns projects, provider connections, resources, the payment profile, credentials, and usage. |
| Application environment | Your deployment boundary, such as preview or production. |
| Platform backend | Resolves the authenticated user to a tenant and connected account, calls Stripe, persists state, and handles secrets. |
| Provider | A third party that advertises Services and owns the underlying infrastructure. |
Store a verified mapping from each tenant_id to its connected_account_id, and use that mapping to resolve the connected account. Don’t pass a connected account ID from a browser request, model prompt, URL parameter, or generated application directly to Stripe.
Include the following values in every authenticated request to the Provisioning API:
Authorization: Bearer {{PLATFORM_SECRET_OR_RESTRICTED_KEY}}
Stripe-Context: {{CONNECTED_ACCOUNT_ID}}
Stripe-Version: 2026-09-16.preview
Content-Type: application/json
Before your backend adds Stripe-Context, verify that the user is authorized to access the tenant and connected account. Don’t allow a browser, generated application, or coding agent to call the Provisioning API directly.
Map scope and topology
Provisioning objects have different scopes. A service’s scope determines where you can share it:
- Provisioning projects differ from CLI environments. A CLI environment stores local CLI configuration and output, while a project defines a Provisioning grouping and credential boundary.
- Create provider connections at the account scope. One connection supports every project in the connected account, so don’t create a separate connection for each application.
- Use the scope returned for each service. Don’t infer the scope from the provider, service name, or intended use.
- You can associate an account-scoped resource, including a plan, with a project. The association doesn’t change the resource’s scope.
- You can use one plan for dependent resources across multiple projects and applications only if the catalog response allows it through the returned scope and dependency contract. Confirm both values in the response.
Enroll in the private preview
Before you build a production integration, confirm the following items with the preview owner:
- The platform and test connected accounts are enrolled in the cohort.
- The preview API version is enabled for the cohort, for both the Provisioning API and the Accounts API.
- The approved connected account configuration and onboarding path are defined.
- Eligible providers and catalog partitions are defined.
- Paid test provisioning and platform-owned payment sources are enabled, if applicable.
The Provisioning API doesn’t self-enroll a platform or create a connected account relationship. Private preview enrollment is a Stripe-assisted allowlist step. Use the Accounts API configuration and hosted onboarding flow that your cohort explicitly approves.
Complete the preflight checklist
Run these steps in order before your first Provisioning write. If you can’t complete a step, stop and resolve it with your preview owner rather than working around it.
- Confirm that the platform account, the target connected accounts, and the catalog and payment cohort are allowlisted.
- Record the enabled Stripe-Version , and separately record the Accounts API configuration that your cohort requires. These are two independent contracts, and enabling one doesn’t enable the other.
- Confirm which environments support catalog reads, free provisioning, and paid provisioning for your cohort.
- Check eligibility in the connected account context.
- Provision one free resource end to end before you configure a paid service.
Eligibility, catalog availability, and connected account onboarding are three separate gates. A successful catalog read proves only that the catalog is readable. It doesn’t prove that the connected account is onboarded, that the account is eligible, or that any write path works.
Build your backend
Before you make your first API request, implement the following two components. Route every request in the numbered steps through both components.
Create a backend adapter
Every call runs through the platform backend. The adapter must do the following:
- Use a network timeout of 45 seconds or less.
- Follow returned next _ page _ url and previous _ page _ url . Never construct an opaque page value.
- Read list results from data , not deprecated aliases such as providers , services , or resources .
- Persist the intended write before sending it.
- Store non-secret request IDs, object IDs, status transitions, endpoint or action names, HTTP status, and error codes.
- Treat request _ log _ url as supplemental diagnostic data, not a dependable recovery path.
- Redact credentials, access configurations, callback secrets, payment details, and pre-authenticated URLs from logs, browser responses, analytics, support tickets, and model prompts.
The preview doesn’t provide caller-controlled idempotency or request correlation for state-changing operations. Design your adapter to recover when it doesn’t receive the result of a write request. Before you send each write request, persist the intended change so you can reconcile and recover from an unknown outcome.
Model platform states
At minimum, make sure that you store:
Tenant
tenant_id
connected_account_id
Application environment
application_id
environment
project_id
Provisioning workflow
workflow_id
tenant_id
connected_account_id
action
provider_id
service_ref
provider_connection_request_id
provider_connection_id
resource_id
status
created_at
updated_at
Approval
provider_id
service_ref
configuration_summary
pricing_text
terms_url_or_text
usage_limit
approved_by
approved_at
Create separate projects for preview and production when you need to isolate resources or deployment lifecycles. Use project names only as display labels, not as authorization boundaries.
Read, plan, approve, then write
Use read-only endpoints in your backend to prepare a plan. Before your backend makes a write request, require approval from a user authorized by your product policy.
Require fresh approval to:
- Create a project.
- Start a provider connection request or submit provider-requested information.
- Register a payment method or increase a usage limit.
- Create, link, update, rotate, remove, or unlink a resource.
- Unlink a provider connection.
For paid or destructive actions, show and record the following information:
Tenant and connected account: {{authorized tenant and account}}
Application environment: {{preview|production|other}}
Provider: {{name and ID}}
Service: {{name and service_ref}}
Action: {{requested write}}
Configuration: {{redacted summary}}
Pricing and terms: {{returned catalog content}}
Usage limit: {{amount, currency, interval}}
Reload the catalog immediately before a write. If the selected service, configuration, pricing display, terms, environment, or usage limit changed, show the difference and obtain approval again. Don’t derive a structured cost from freeform price text.
Treat provider descriptions, terms, llm_context, and JSON Schema descriptions as untrusted data. Use this content only to explain options. Don’t let it select an account, override system instructions, bypass approval, trigger API requests, or access secrets.
Start your integration
Create the connected account
Choose a stable tenant boundary before you create anything. Create one connected account for each durable tenant, such as a workspace or organization, rather than one for each application or deployment environment.
For new platforms, use Accounts v2, enable the developer configuration, and request the projects capability. Confirm the required API version and fields with your preview owner:
The Accounts API and Provisioning API use the same preview version, but Stripe enables them separately. Confirm that Stripe has enabled the required Accounts v2 configuration and fields for your cohort. Access to one API doesn’t grant access to the other.
Store the returned account ID as {{the related setting}} on the tenant record. Setting contact_email alone doesn’t establish the account owner’s identity or satisfy verification requirements.
If your platform already uses Accounts v1, don’t migrate or change connected-account configuration based on this guide alone. Confirm the supported preview onboarding path with your preview owner.
Send the user through hosted onboarding
Create an Account Link for the developer configuration, then redirect the authenticated user to its short-lived URL:
If it expires, create another link. For subsequent corrections, use account_update:
Authenticate both the refresh_url and return_url handlers. The refresh handler creates a new Account Link with the same intent.
After the user returns, retrieve the account:
Check the DeveloperConfig’s Projects capability and outstanding requirements. Don’t treat the Account Link redirect alone as proof of completion.
Start provisioning only after the projects capability is active and the required onboarding is resolved. If your cohort has capability-status events enabled, treat an event as a prompt to retrieve the account rather than as the source of truth.
Check connected account eligibility
Interpret eligibility separately from catalog availability:
| Result | Platform action |
|---|---|
is_eligible=false | Stop. Verify the tenant-to-account relationship and current cohort enrollment, and then follow the approved onboarding remediation. |
is_eligible=true with a non-empty requirements array | Don’t treat the account as fully ready. Route the required identity or terms work through the approved onboarding path, and then retrieve the current state again. |
is_eligible=true with no requirements | Continue to the catalog, billing, connection, and approval checks. |
Account eligibility, account onboarding requirements, service availability, and your own product policy are four separate gates. A true eligibility response doesn’t make an unavailable service usable, and it doesn’t authorize a paid write.
Discover a provisionable service
Read the connected account’s catalog when you plan and again immediately before provisioning:
A restricted key needs rak_provisioning_project_read for both calls above.
Select a service
For each candidate provider, list services by using that provider’s exact provider_name and the same catalog and development selection. If the services response has an empty data array, that provider isn’t provisionable for this plan. Don’t create a provider connection request for it.
The API has no generic full-text or category search parameter. Don’t create one. Follow all pages, build a local index from returned data, apply deterministic product policy, and then present only eligible returned services for model-assisted explanation or ranking.
| Catalog field | Use |
|---|---|
Provider id | Send in request fields named provider. |
Provider name | Display to users and send only to endpoints that explicitly accept provider_name. |
Provider configuration_schema | Validate connection configuration before creating a Provider connection request. |
Service service_id | Send this value as service_ref when you create, link, or update a Resource. |
Service configuration_schema | Use this schema to validate the configuration when you create or update a Resource. |
availability | Exclude unavailable Services. |
pricing.paid_pricing | Display paid pricing from this field. Don’t use the deprecated pricing.paid field. |
kind and component parent_services | Identify plans, deployables, components, and prerequisites. |
scope | Decide Project placement and association. |
constraints, allowed_updates | Prevent unsupported creates and changes. |
Provider capabilities | Enable optional behavior only when the Provider advertises it. |
Use the same catalog partition for catalog requests and any Project or Resource requests that support it. Set development=true only when the user selects development-only entries.
Plan dependencies before connection or provisioning
A Provider can expose a plan Service and dependent deployable Services, or component Services with parent_services. Treat required plans and parents as separate Resources in the plan:
Plan prerequisite
→ user approves prerequisite and dependent action
→ create prerequisite Resource
→ wait for complete
→ refresh catalog and approval-sensitive fields
→ create dependent Resource
If dependency information is unclear, stop instead of testing different Providers or Services. Don’t treat raw HTTP status codes from a Provider as part of your client contract. Use the Provisioning API states, error codes, and safe error messages instead.
Configure billing for paid Services
Retrieve the effective connected account’s profile first:
Set livemode as a query parameter on every read. It doesn’t inherit from the mode the payment method was created in, and the endpoint ignores the Stripe-Livemode header. Send livemode=false to read a test-mode profile: a test-mode profile that exists returns 404 when you omit the query parameter or set it from the header alone, so a successful write looks like it silently failed.
A 404 not_found with “No payment method linked yet” is the normal starting state for an account, not an error. Treat it as “no payment method yet” and continue with one of the payment paths.
Use one of the payment paths explicitly enabled for your cohort:
| Path | Request |
|---|---|
| Connected-account hosted collection | Create a Payment method request with usage_limits; omit payment_method_owner and all source_* fields. Send the authorized user to the short-lived returned checkout_session_url, then poll the payment profile with the matching livemode query parameter. |
| Platform-owned source | Use this flow only when Stripe explicitly enables it for your preview cohort. Before you send the write request, verify that the Customer and PaymentMethod belong to the same source account. Include payment_method_owner: "platform", source_account, source_customer, source_payment_method, and usage_limits in the request. |
For connected-account hosted collection, send only usage_limits:
The response returns checkout_session_url and status.
For the platform-owned source path, send the owner and source fields on the same endpoint:
max_amount uses the smallest currency unit, and you send it as a string. The API represents int64 fields as strings, so an unquoted number fails with invalid_fields. Apply the same convention to every large-number field. Valid intervals are week, month, and year. Use POST /the relevant part of the product, which takes the amount as a string too, for account-wide limits or Provider-specific overrides.
Treat payment mode, catalog partition, and app environment as independent settings. Access to the dev or testing catalog doesn’t guarantee that the Provider won’t create infrastructure or authorize a payment. A preview deployment also doesn’t change the payment mode. Treat paid validation as potentially chargeable unless your enrolled cohort and the Provider explicitly confirm otherwise.
Completing payment setup doesn’t approve a Provider connection, paid Resource, tier change, or spending increase. Require separate user approval for each action.
Treat a Provisioning usage limit as an authorization limit, not a lifecycle policy. Don’t assume that reaching the limit deletes a Resource, preserves service availability, or triggers the same notification across Providers. Review the Service and Provider contracts, keep the limit visible to the user, and provide a user-approved way to change it.
Map existing platform customers to Provisioning tenants
If your users already have Customer objects and stored payment methods on your platform, you don’t migrate or replace them. One user can be both a platform Customer and a connected account:
Platform user
├── Platform Customer: stores the payment method for your platform's own charges
└── Connected account: owns Provisioning Projects, Provider connections,
Resources, usage, and the payment profile
- The Provisioning payment profile, not your platform Customer, authorizes Provider services.
- The platform-owned source path lets you charge a payment method that you already store, but it’s available only when it’s explicitly enabled for your cohort.
- The Provisioning API doesn’t make your platform the merchant of record for Provider services, and it doesn’t implement a Connect transfers or marketplace model. Design those separately with Connect if you need them.
Create a Project
After approval, create a Project for the application environment:
Save the Project ID with the platform’s application-environment record. Use separate preview and production Projects when their Resources or credentials must remain isolated.
Connect a Provider
List Provider connections before creating a new request:
If multiple active connections make the outcome ambiguous, show safe returned Provider-account details where available and stop for review. If no usable active connection exists, validate the Provider’s configuration_schema, then create a Provider connection request after approval:
Use {} only when the Provider schema has no required fields. Store the returned Provider connection request ID before you redirect the user or collect additional information.
Before you provision a Resource, confirm that the Provider has exactly one active connection. Resource create and link requests identify the Provider, not a specific Provider connection. Don’t display a connection picker because the write API can’t use the selected connection.
| Provider-connection-request status | Platform action |
|---|---|
requested | Retrieve the Provider connection request until it advances or a bounded deadline expires. |
pending_auth | Present redirect_url only to the authenticated user, persist state, and poll from the backend. |
needs_information | Render supported needs_information_schema shapes, collect only user-supplied values, then submit { "information": {{the related setting}} }. Include confirmation_secret only if the Provider flow returns it; treat it as a secret. |
complete | Read the resulting connection from provider_connection and verify an unambiguous active connection before continuing. The request stays complete even after that connection is unlinked, in which case provider_connection is absent. |
error | Stop and show only a safe error. |
Handle the immediate-connect path on the create response itself. Some Providers finish during the create request and return complete with an active provider_connection and no redirect_url, so don’t wait for a redirect or keep polling a request that already finished.
A Provider might require verified KYC information, such as a verified email address, even if your product treats that information as optional. Check the Provider’s configuration_schema and any returned needs_information_schema for required fields. Collect and submit all required information, including email when specified.
If Provider authentication requires a browser redirect, pause the workflow and store the Provider connection request ID. After the browser step, resume the workflow using that ID. Don’t bypass or simulate authentication.
The current flow doesn’t accept a platform callback URL. Stripe handles the Provider callback and token exchange. Provide optional the related setting fields only when Stripe explicitly enables and requires them for your preview flow.
Create or link a Resource
Before you send the write request, verify the following:
- Required onboarding is complete.
- The Service is still available in the selected catalog.
- All prerequisite plan or parent Resources are complete.
- The Provider has exactly one active connection.
- The Resource configuration satisfies the current Service configuration _ schema .
- A payment profile exists for each paid Service.
- The Resource’s scope , constraints , allowed updates, and Project association are valid.
- The user has approved the current plan.
Always set livemode explicitly in create and link requests. If you omit it, Stripe defaults to true, which can create live mode Provider infrastructure and incur real charges. Set livemode to false for test provisioning.
The Resource environment field accepts only dev or prod. Map your application environment, such as preview or production, to one of these values. The environment and livemode fields are independent: environment=dev doesn’t mean the Resource runs in a sandbox.
For a project-scoped Service, include project. For an account-scoped Service, omit project unless you need to associate the Resource with a Project. Including project creates the association but doesn’t change the Provider Resource’s scope.
Adopt existing infrastructure only when the Provider advertises resources:link and the user approved it:
Resume asynchronous work safely
A Resource is usable only when status=complete.
| Resource status | Platform action |
|---|---|
pending | Poll GET /the relevant part of the product/{id} with bounded exponential backoff and jitter. |
needs_information | Collect schema-valid user input, submit { "submitted_information": {{the related setting}} }, then continue polling. |
complete | Record the Resource against the application environment and continue the workflow. |
errored | Stop and expose error_message only if safe. |
removed | Treat as terminal. |
During the preview, poll after 1, 2, 4, 8, 16, and 30 seconds, then every 30 seconds for up to 15 minutes. Add a small random offset, called jitter, to each wait so that workflows that started at the same time don’t send their polls at the same moments. The API doesn’t define polling intervals, webhooks, or final rate limits. If polling times out, retain the object IDs and set the status to requires_review. Don’t resend the write request automatically.
Manage Resources
Update
Before an update, refresh the Service and verify allowed_updates, constraints, current catalog, and approval.
Omit service_ref for a configuration-only update. The response is an operation result: pending, complete, or errored. Do not rely on deprecated resource_id in the response.
Rotate credentials
POST /the relevant part of the product/{id}/rotate_credentials returns pending, complete, or errored.
- complete : Record the rotation on the Resource, and invalidate any credentials that the Provider issued before the rotation.
- errored : Stop the workflow and leave the Resource unchanged.
- pending : Don’t resend the rotation request. Set the status to requires _ review . The preview API doesn’t provide a durable way to retrieve the rotation operation, and reading the Resource later doesn’t confirm that the rotation completed.
Remove, unlink, and connection unlink
Require distinct approval for each action.
| Action | Endpoint | Effect |
|---|---|---|
| Deprovision infrastructure | POST /the relevant part of the product/{id}/remove | Requests removal of Provider infrastructure. |
| Stop managing a Resource | POST /the relevant part of the product/{id}/unlink | Removes the Provisioning association; it doesn’t delete Provider infrastructure. |
| Forget Provider connection | POST /the relevant part of the product/{id}/unlink | Removes Stripe’s stored connection; it doesn’t remove Resources or guarantee Provider-side token revocation. |
After you remove or unlink a Resource, don’t assume that the Provider has invalidated previously issued credentials. Confirm their status with the Provider.
Handle errors
Use the Provisioning API error.code, returned state, and safe messages to handle errors. Don’t branch on assumed raw provider HTTP statuses.
| Error code | Platform action |
|---|---|
payment_method_required | Complete payment setup, obtain approval, then retry deliberately. |
payment_method_and_customer_required | For an enabled platform-source flow, provide matching source Customer and PaymentMethod. |
payment_method_owner_required | For an enabled platform-source flow, set payment_method_owner=platform. |
unsupported_payment_method_owner | Stop; use only a currently enabled owner mode. |
connect_relationship_required | Verify the platform-to-connected account relationship and the Stripe-Context value. |
provider_reauth_required | Create a new Provider connection request and ask the user to reconnect. |
invalid_resource_configuration | Refresh the schema and collect corrected user input. |
resource_count_constraint_exceeded | Explain the constraint and offer an allowed update, association, or existing Resource. |
provider_failure | Show a safe message. Identify a returned prerequisite when possible; retry only after approval and only if safe. |
api_error or unknown code | Stop, record safe diagnostics, retrieve known objects, mark requires_review, and don’t replay the write automatically. |
not_found | Verify object ID and Stripe-Context; don’t probe another account. |
rate_limited or HTTP 429 | Back off with exponential delay and jitter, honoring a returned Retry-After if present. Don’t tighten polling intervals, fan out retries across resources, or bypass the limit by adding parallel callers. |
For an api_error, unavailable request logs, or an unknown write outcome, store the endpoint, action, non-secret request ID, object IDs, HTTP status, error code and message, and current workflow state. If request_log_url is missing, unavailable, or unhelpful, record that result as evidence. Don’t ask the user to retry the URL repeatedly.
After a write request times out or returns an unknown outcome, set the workflow status to requires_review. In the same connected account context, retrieve the known Provider connection requests and Resources. Reconcile the observed state with an authorized user, and get their approval before you send another write request. Don’t replay the original request automatically.
Test your integration
Before deployment, test with accounts and services that your cohort explicitly enrolls:
- Verify authorization from user to tenant to connected account. Confirm that untrusted account IDs can’t change context.
- Complete connected account onboarding and confirm that the account is ready with both empty and non-empty requirements.
- Test pagination, catalog and development partition consistency, empty service lists, availability, pricing, scope, constraints, and schema validation.
- Test plan and deployable dependencies and component-parent dependencies without branching on raw provider 422 responses.
- Test immediate provider connection, browser redirect, and needs _ information . Verify workflow recovery after browser or session loss.
- Test a free resource through pending , needs _ information , and completion.
- Test paid provisioning only when the cohort confirms it, with an explicit low limit and fresh approval.
- Test update, reauthentication, and resource remove versus unlink separately.
- Test synchronous credential rotation, and require review for pending rotation.
- Test provider _ failure , api _ error , polling timeout, unknown writes, and unavailable request log links.
Preview limitations
- Credential retrieval isn’t available in this preview. You can provision and manage Resources, but don’t build a deployment path that depends on reading Resource credentials yet. Confirm availability with your preview owner.
- There’s no documented Provisioning webhook support, so use bounded polling.
- There’s no documented caller idempotency or correlation contract for writes.
- There’s no documented client polling interval or final rate limit policy. Some Providers rate limit heavily; a caller that fans out requests across many Resources or Projects can hit this even at moderate per-user volume, so back off centrally rather than per-workflow.
- Provider upstream failures aren’t a stable client interface, so use the Provisioning API codes and safe messages.
- Pending credential rotation has no durable operation retrieval flow.
- Paid test provisioning and platform-owned payment sources depend on the cohort.
- Preview fields and enums can change, so avoid deprecated fields when a current replacement exists.
