API: POST /v1/customers returns 422 when unsetting a Stripe provider_customer_id

Last updated: August 17, 2026

On self-hosted Lago API versions before v1.51.0, when using POST /api/v1/customers to remove a Stripe customer ID, the request returns a 422 third_party_error even though the change has already been saved. This happens because after unsetting the ID, Lago still attempts to sync the customer to Stripe using the old ID, which is no longer valid. The change is committed successfully despite the error response, and can be confirmed with a subsequent GET request.

Applies to

  • Surface: API

  • Deployment: Self-hosted versions before Lago API v1.51.0

  • Object or endpoint: POST /api/v1/customers, billing_configuration.provider_customer_id

  • Condition: Customer has a Stripe provider_customer_id that is no longer valid or belongs to a different Stripe account

Cause

When provider_customer_id is set to null, Lago saves the change immediately but then attempts a Stripe sync using the old customer ID. Because that ID is either invalid or belongs to a different Stripe account, Stripe returns a "No such customer" error, which Lago surfaces as a 422 third_party_error. The underlying record has already been updated at this point, making the 422 a false failure.

How to confirm the cause

After receiving the 422, issue a GET /api/v1/customers/:external_id and inspect the billing_configuration object in the response.

  • Matching signal: provider_customer_id is null or absent — the unset succeeded despite the 422.

  • Non-matching signal: provider_customer_id still contains the old value — the change did not save, and this article does not apply.

How to resolve the issue

Upgrade to Lago API v1.51.0 or later. Beginning with v1.51.0, Lago

reloads the provider customer after clearing the Stripe customer ID and

does not attempt to synchronize the removed ID.

Workaround for versions before v1.51.0

Use the nested form to unset the Stripe customer ID. If the customer should use another Stripe connection, attach the correct connection and customer ID afterward.

  1. Send POST /api/v1/customers with the following payload to unset the ID:

    {
      "customer": {
        "external_id": "<customer_external_id>",
        "billing_configuration": {
          "provider_customer_id": null
        }
      }
    }

    The request may return a 422 even though the ID was removed.

  2. Confirm the change with GET /api/v1/customers/:external_id and verify that provider_customer_id is no longer present.

  3. Re-attach the correct Stripe account by sending POST /api/v1/customers with the correct values:

    {
      "customer": {
        "external_id": "<customer_external_id>",
        "billing_configuration": {
          "payment_provider": "stripe",
          "payment_provider_code": "<correct_connection_code>",
          "provider_customer_id": "cus_<correct_id>"
        }
      }
    }

Expected result: The GET /api/v1/customers/:external_id response shows the correct provider_customer_id linked to the right Stripe account.

How to prevent this from happening again

Always verify the active Stripe connection code and the corresponding Stripe customer ID before attaching a provider_customer_id to a customer. Mismatched IDs (e.g., an ID belonging to a different Stripe account than the one configured on the billing entity) will cause sync failures that are difficult to detect without a follow-up GET.

Field reference

Field, status, or error

Meaning

billing_configuration: null

Passing the entire billing_configuration object as null has no effect. It does not unset any fields.

billing_configuration.provider_customer_id: null

The correct way to unset a Stripe customer ID. The change is saved even if the response is a 422.

422 third_party_error / No such customer

Lago attempted a Stripe sync after unsetting the ID and received an error from Stripe. The local record was already updated before the sync attempt.


This article reflects guidance drawn from customer case resolutions. It is not officially supported documentation and may not apply to all situations.