{"record":{"id":"e23ec890d28f4595","repo":"bitwarden/server","slug":"invalid-billing-sync-key","errorCode":null,"errorMessage":"Invalid Billing Sync Key","messagePattern":"Invalid Billing Sync Key","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Billing/Controllers/LicensesController.cs","lineNumber":85,"sourceCode":"    /// </summary>\n    [HttpGet(\"organization/{id}\")]\n    public async Task<OrganizationLicense> OrganizationSync(string id, [FromBody] SelfHostedOrganizationLicenseRequestModel model)\n    {\n        var organization = await _organizationRepository.GetByIdAsync(new Guid(id));\n        if (organization == null)\n        {\n            throw new NotFoundException(\"Organization not found.\");\n        }\n\n        if (!organization.LicenseKey.Equals(model.LicenseKey))\n        {\n            await Task.Delay(2000);\n            throw new BadRequestException(\"Invalid license key.\");\n        }\n\n        if (!await _validateBillingSyncKeyCommand.ValidateBillingSyncKeyAsync(organization, model.BillingSyncKey))\n        {\n            throw new BadRequestException(\"Invalid Billing Sync Key\");\n        }\n\n        var license = await _getCloudOrganizationLicenseQuery.GetLicenseAsync(organization, _currentContext.InstallationId.Value);\n        return license;\n    }\n}\n","sourceCodeStart":67,"sourceCodeEnd":92,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Billing/Controllers/LicensesController.cs#L67-L92","documentation":"Thrown (HTTP 400) by GET /licenses/organization/{id} when the license key matches but _validateBillingSyncKeyCommand.ValidateBillingSyncKeyAsync returns false. The billing sync key is the shared secret that pairs a self-hosted organization with its cloud billing subscription; a mismatch aborts license retrieval.","triggerScenarios":"Wrong or stale billing sync key; the key was regenerated in the cloud portal; the organization was never configured for billing sync.","commonSituations":"Billing sync key regenerated in cloud org settings but the self-hosted installation still uses the old key; fresh self-hosted install that was never paired.","solutions":["Regenerate the billing sync key in the cloud organization's billing settings and copy it exactly.","Update the self-hosted billing-sync configuration with the new key.","Verify the key was not truncated or altered during copy."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify the billing sync key is configured and well-formed before calling.\nif (!billingSyncKey || billingSyncKey.length === 0) {\n  throw new Error('Billing sync key is not configured for this organization');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const lic = await getOrgLicense(orgId, body);\n} catch (e) {\n  if (e.isBadRequest && /invalid billing sync key/i.test(e.message)) {\n    await regenerateAndStoreBillingSyncKey(); // then retry once\n  } else { throw e; }\n}","preventionTips":["Store the billing sync key in a managed secret store, not inline code.","Rotate keys deliberately and update all dependents atomically.","Copy the key from the cloud portal via clipboard to avoid truncation."],"tags":["billing","license","sync","authentication","secret","organization"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}