# Integrate the Provisioning API into your platform

Use the Provisioning API from your platform backend to connect Providers, provision Resources, and manage paid services for authorized tenants.

> The Provisioning API is allowlisted during private preview. Contact your Stripe representative or email [provisioning-preview@stripe.com](mailto:provisioning-preview@stripe.com) 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:

A diagram showing a platform tenant that contains one connected account, which owns an account-scoped provider connection, an account-scoped plan resource, and two projects that each own a project-scoped resource. (See full diagram at https://docs.stripe.com/provisioning)

```text
[Platform tenant or workspace] --> [Connected account]
[Connected account] --> [Provider connection: model gateway (account-scoped)]
[Connected account] --> [Plan resource: database plan (account-scoped)]
[Connected account] --> [Project: App A production]
[Connected account] --> [Project: App B production]
[Project: App A production] --> [Resource: App A database (project-scoped)]
[Project: App B production] --> [Resource: App B database (project-scoped)]
```

- 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.

1. Confirm that the platform account, the target connected accounts, and the catalog and payment cohort are allowlisted.
2. 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.
3. Confirm which environments support catalog reads, free provisioning, and paid provisioning for your cohort.
4. Check eligibility in the connected account context.
5. 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:

```
POST /v2/core/accounts
Stripe-Version: 2026-09-16.preview

{
  "contact_email": "{{OWNER_EMAIL}}",
  "display_name": "{{TENANT_DISPLAY_NAME}}",
  "identity": {
    "country": "{{COUNTRY}}",
    "entity_type": "{{individual|company}}"
  },
  "configuration": {
    "developer": {
      "capabilities": {
        "projects": {"requested": true}
      }
    }
  },
  "include": ["configuration.developer", "requirements", "identity"]
}
```

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 `{{CONNECTED_ACCOUNT_ID}}` 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:

```
POST /v2/core/account_links
Stripe-Version: 2026-09-16.preview

{
  "account": "{{CONNECTED_ACCOUNT_ID}}",
  "use_case": {
    "type": "account_onboarding",
    "account_onboarding": {
      "configurations": ["developer"],
      "refresh_url": "{{PLATFORM_REFRESH_URL}}",
      "return_url": "{{PLATFORM_RETURN_URL}}",
      "collection_options": {"fields": "currently_due"}
    }
  }
}
```

If it expires, create another link. For subsequent corrections, use `account_update`:

```
POST /v2/core/account_links
Stripe-Version: 2026-09-16.preview

{
  "account": "{{CONNECTED_ACCOUNT_ID}}",
  "use_case": {
    "type": "account_update",
    "account_update": {
      "configurations": ["developer"],
      "refresh_url": "{{PLATFORM_REFRESH_URL}}",
      "return_url": "{{PLATFORM_RETURN_URL}}"
    }
  }
}
```

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:

```
GET /v2/core/accounts/{{CONNECTED_ACCOUNT_ID}}?include=configuration.developer&include=requirements
Stripe-Version: 2026-09-16.preview
```

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

```
GET /v2/provisioning/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:

```
GET /v2/provisioning/catalog/providers?limit=100
GET /v2/provisioning/catalog/services?provider_name={{PROVIDER_NAME}}&limit=100
```

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:

```
GET /v2/provisioning/payment_profile?livemode=false
```

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`:

```
POST /v2/provisioning/payment_method_requests

{
  "livemode": false,
  "usage_limits": {
    "max_amount": "5000",
    "currency": "usd",
    "recurring_interval": "month"
  }
}
```

The response returns `checkout_session_url` and `status`.

For the platform-owned source path, send the owner and source fields on the same endpoint:

```
POST /v2/provisioning/payment_method_requests

{
  "livemode": false,
  "payment_method_owner": "platform",
  "source_account": "{{PLATFORM_ACCOUNT_ID}}",
  "source_customer": "{{PLATFORM_CUSTOMER_ID}}",
  "source_payment_method": "{{PAYMENT_METHOD_ID}}",
  "usage_limits": {
    "max_amount": "5000",
    "currency": "usd",
    "recurring_interval": "month"
  }
}
```

`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 /v2/provisioning/payment_profile/update_limit`, 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:

```
POST /v2/provisioning/projects

{
  "name": "{{APPLICATION_NAME}} {{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:

```
GET /v2/provisioning/provider_connections?limit=100
```

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:

```
POST /v2/provisioning/provider_connection_requests

{
  "provider": "{{PROVIDER_ID}}",
  "configuration": {},
  "project": "{{PROJECT_ID}}"
}
```

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": {{VALIDATED_INFORMATION}} }`. 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 PKCE 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.

```
POST /v2/provisioning/resources

{
  "provider": "{{PROVIDER_ID}}",
  "service_ref": "{{SERVICE_ID}}",
  "project": "{{PROJECT_ID}}",
  "livemode": {{true|false}},
  "name": "{{RESOURCE_NAME}}",
  "configuration": {{VALIDATED_SERVICE_CONFIGURATION}}
}
```

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:

```
POST /v2/provisioning/resources/link

{
  "provider": "{{PROVIDER_ID}}",
  "service_ref": "{{SERVICE_ID}}",
  "project": "{{PROJECT_ID}}",
  "environment": "{{dev|prod}}",
  "catalog": "{{CATALOG}}",
  "livemode": {{true|false}}
}
```

## Resume asynchronous work safely

A Resource is usable only when `status=complete`.

| Resource status | Platform action |
| --- | --- |
| `pending` | Poll `GET /v2/provisioning/resources/{id}` with bounded exponential backoff and jitter. |
| `needs_information` | Collect schema-valid user input, submit `{ "submitted_information": {{VALIDATED_INFORMATION}} }`, 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.

```
POST /v2/provisioning/resources/{id}

{
  "configuration": {{VALIDATED_SERVICE_CONFIGURATION}},
  "service_ref": "{{OPTIONAL_NEW_SERVICE_ID}}",
  "catalog": "{{CATALOG}}"
}
```

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 /v2/provisioning/resources/{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 /v2/provisioning/resources/{id}/remove` | Requests removal of Provider infrastructure. |
| Stop managing a Resource | `POST /v2/provisioning/resources/{id}/unlink` | Removes the Provisioning association; it doesn’t delete Provider infrastructure. |
| Forget Provider connection | `POST /v2/provisioning/provider_connections/{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:

1. Verify authorization from user to tenant to connected account. Confirm that untrusted account IDs can’t change context.
2. Complete connected account onboarding and confirm that the account is ready with both empty and non-empty requirements.
3. Test pagination, catalog and development partition consistency, empty service lists, availability, pricing, scope, constraints, and schema validation.
4. Test plan and deployable dependencies and component-parent dependencies without branching on raw provider `422` responses.
5. Test immediate provider connection, browser redirect, and `needs_information`. Verify workflow recovery after browser or session loss.
6. Test a free resource through `pending`, `needs_information`, and completion.
7. Test paid provisioning only when the cohort confirms it, with an explicit low limit and fresh approval.
8. Test update, reauthentication, and resource remove versus unlink separately.
9. Test synchronous credential rotation, and require review for pending rotation.
10. 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.

## See also

- [Stripe Projects CLI](https://docs.stripe.com/projects.md)
- [Available providers](https://docs.stripe.com/projects.md#available-providers)
- [Provider intake for Stripe Projects](https://docs.stripe.com/projects/provider-intake.md)
- [Stripe Connect](https://docs.stripe.com/connect.md)
- [Accounts v2](https://docs.stripe.com/connect/accounts-v2.md)
