diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 5b6e082a..f2a537bc 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 8c24a12b-d2f1-466a-bdaa-6d83a049a679 management: - docChecksum: aa0e8124d4a66a769e20d3dd3f15430c + docChecksum: de1405838dc8c6c096e18a9badd21ac2 docVersion: "2025-04-10" - speakeasyVersion: 1.606.9 - generationVersion: 2.687.13 - releaseVersion: 0.3.0 - configChecksum: 49707dff3f36f9522e0c9e90871d3967 + speakeasyVersion: 1.635.1 + generationVersion: 2.722.2 + releaseVersion: 0.3.1 + configChecksum: 897c7229ce4aa069d783316e79ffe6fb repoURL: https://github.com/clerk/clerk-sdk-php.git installationURL: https://github.com/clerk/clerk-sdk-php published: true @@ -14,11 +14,11 @@ features: php: additionalProperties: 0.1.0 constsAndDefaults: 0.2.0 - core: 3.8.9 + core: 3.8.11 deprecations: 2.81.1 examples: 2.81.6 flattening: 2.81.1 - globalSecurity: 2.81.8 + globalSecurity: 2.81.9 globalSecurityFlattening: 0.1.2 globalServerURLs: 2.82.2 groups: 2.81.2 @@ -26,7 +26,7 @@ features: nameOverrides: 2.81.2 nullables: 1.0.1 responseFormat: 0.1.0 - retries: 0.1.0 + retries: 0.1.1 unions: 0.1.5 generatedFiles: - .gitattributes @@ -89,6 +89,7 @@ generatedFiles: - docs/Models/Components/Error.md - docs/Models/Components/ErrorClerkError.md - docs/Models/Components/ErrorMeta.md + - docs/Models/Components/ExtendFreeTrialRequest.md - docs/Models/Components/ExternalAccount.md - docs/Models/Components/ExternalAccountWithVerification.md - docs/Models/Components/ExternalAccountWithVerificationObject.md @@ -449,10 +450,14 @@ generatedFiles: - docs/Models/Operations/DeleteUserProfileImageResponse.md - docs/Models/Operations/DeleteUserRequest.md - docs/Models/Operations/DeleteUserResponse.md + - docs/Models/Operations/DeleteWaitlistEntryRequest.md + - docs/Models/Operations/DeleteWaitlistEntryResponse.md - docs/Models/Operations/DisableMFARequest.md - docs/Models/Operations/DisableMFAResponse.md - docs/Models/Operations/DisableMFAResponseBody.md - docs/Models/Operations/EnrollmentMode.md + - docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.md + - docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.md - docs/Models/Operations/File.md - docs/Models/Operations/Format.md - docs/Models/Operations/GenerateSvixAuthURLResponse.md @@ -600,6 +605,9 @@ generatedFiles: - docs/Models/Operations/RevokeSessionResponse.md - docs/Models/Operations/RevokeSignInTokenRequest.md - docs/Models/Operations/RevokeSignInTokenResponse.md + - docs/Models/Operations/RotateMachineSecretKeyRequest.md + - docs/Models/Operations/RotateMachineSecretKeyRequestBody.md + - docs/Models/Operations/RotateMachineSecretKeyResponse.md - docs/Models/Operations/RotateOAuthApplicationSecretRequest.md - docs/Models/Operations/RotateOAuthApplicationSecretResponse.md - docs/Models/Operations/SetUserProfileImageRequest.md @@ -849,6 +857,7 @@ generatedFiles: - src/Models/Components/EnrollmentMode.php - src/Models/Components/ErrorClerkError.php - src/Models/Components/ErrorMeta.php + - src/Models/Components/ExtendFreeTrialRequest.php - src/Models/Components/ExternalAccount.php - src/Models/Components/ExternalAccountWithVerification.php - src/Models/Components/ExternalAccountWithVerificationObject.php @@ -1207,10 +1216,14 @@ generatedFiles: - src/Models/Operations/DeleteUserProfileImageResponse.php - src/Models/Operations/DeleteUserRequest.php - src/Models/Operations/DeleteUserResponse.php + - src/Models/Operations/DeleteWaitlistEntryRequest.php + - src/Models/Operations/DeleteWaitlistEntryResponse.php - src/Models/Operations/DisableMFARequest.php - src/Models/Operations/DisableMFAResponse.php - src/Models/Operations/DisableMFAResponseBody.php - src/Models/Operations/EnrollmentMode.php + - src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.php + - src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.php - src/Models/Operations/File.php - src/Models/Operations/Format.php - src/Models/Operations/GenerateSvixAuthURLResponse.php @@ -1358,6 +1371,9 @@ generatedFiles: - src/Models/Operations/RevokeSessionResponse.php - src/Models/Operations/RevokeSignInTokenRequest.php - src/Models/Operations/RevokeSignInTokenResponse.php + - src/Models/Operations/RotateMachineSecretKeyRequest.php + - src/Models/Operations/RotateMachineSecretKeyRequestBody.php + - src/Models/Operations/RotateMachineSecretKeyResponse.php - src/Models/Operations/RotateOAuthApplicationSecretRequest.php - src/Models/Operations/RotateOAuthApplicationSecretResponse.php - src/Models/Operations/SetUserProfileImageRequest.php @@ -3097,6 +3113,47 @@ examples: application/json: {"errors": []} "404": application/json: {"errors": []} + RotateMachineSecretKey: + speakeasy-default-rotate-machine-secret-key: + parameters: + path: + machine_id: "" + requestBody: + application/json: {"previous_token_ttl": 632625} + responses: + "200": + application/json: {"object": "machine_secret_key", "secret": ""} + "400": + application/json: {"errors": [{"message": "", "long_message": "", "code": ""}]} + DeleteWaitlistEntry: + speakeasy-default-delete-waitlist-entry: + parameters: + path: + waitlist_entry_id: "" + responses: + "200": + application/json: {"object": "", "deleted": false} + "400": + application/json: {"errors": []} + ExtendCommerceSubscriptionItemFreeTrial: + speakeasy-default-extend-commerce-subscription-item-free-trial: + parameters: + path: + subscription_item_id: "" + requestBody: + application/json: {"extend_to": "2026-01-08T00:00:00Z"} + responses: + "200": + application/json: {"object": "commerce_subscription_item", "id": "", "instance_id": "", "status": "incomplete", "plan_id": "", "plan": {"object": "commerce_plan", "id": "", "name": "", "fee": {"amount": 246876, "amount_formatted": "", "currency": "Afghani", "currency_symbol": "kr"}, "annual_monthly_fee": {"amount": 802114, "amount_formatted": "", "currency": "Czech Koruna", "currency_symbol": "£"}, "annual_fee": {"amount": 35560, "amount_formatted": "", "currency": "Lek", "currency_symbol": "$U"}, "amount": 547002, "amount_formatted": "", "annual_monthly_amount": 229468, "annual_monthly_amount_formatted": "", "annual_amount": 799095, "annual_amount_formatted": "", "currency_symbol": "₭", "currency": "Cayman Islands Dollar", "description": "under for anenst finally", "product_id": "", "is_default": false, "is_recurring": false, "publicly_visible": false, "has_base_fee": true, "payer_type": ["", ""], "for_payer_type": "", "slug": "", "avatar_url": "https://thorny-monocle.name", "features": [{"object": "feature", "id": "", "name": "", "description": "tiny among all hopelessly sympathetically up scar", "slug": "", "avatar_url": "https://immediate-equal.com/"}]}, "plan_period": "month", "payment_source_id": "", "payer_id": "", "is_free_trial": false, "proration_date": "", "created_at": 518769, "updated_at": 177754} + "400": + application/json: {"errors": []} + "500": + application/json: {"errors": []} examplesVersion: 1.0.2 generatedTests: {} -releaseNotes: "## SDK Changes Detected:\n* `clerkbackend->sessions->createToken()`: \n * `requestBody->expiresInSeconds` **Changed** **Breaking** :warning:\n* `clerkbackend->sessions->createTokenFromTemplate()`: \n * `requestBody->expiresInSeconds` **Changed** **Breaking** :warning:\n* `clerkbackend->users->list()`: `response.[]` **Changed** **Breaking** :warning:\n* `clerkbackend->users->create()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->get()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->samlconnections->update()`: \n * `requestBody->domains` **Added**\n * `response` **Changed** **Breaking** :warning:\n* `clerkbackend->samlconnections->get()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->samlconnections->create()`: \n * `request` **Changed** **Breaking** :warning:\n * `response` **Changed** **Breaking** :warning:\n* `clerkbackend->samlconnections->list()`: `response.data->[]` **Changed** **Breaking** :warning:\n* `clerkbackend->jwttemplates->update()`: `requestBody` **Changed** **Breaking** :warning:\n* `clerkbackend->jwttemplates->create()`: `request` **Changed** **Breaking** :warning:\n* `clerkbackend->instancesettings->updateRestrictions()`: \n * `request` **Changed** **Breaking** :warning:\n * `response` **Changed** **Breaking** :warning:\n* `clerkbackend->organizationinvitations->list()`: \n * `request` **Changed** **Breaking** :warning:\n * `error.status[422]` **Added**\n* `clerkbackend->users->getOAuthAccessToken()`: `response.[]` **Changed** **Breaking** :warning:\n* `clerkbackend->users->updateMetadata()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->deleteProfileImage()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->setProfileImage()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->unlock()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->lock()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->unban()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->ban()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->users->update()`: `response` **Changed** **Breaking** :warning:\n* `clerkbackend->sessions->revoke()`: `response.tasks` **Added**\n* `clerkbackend->machines->get()`: **Added**\n* `clerkbackend->experimentalaccountlessapplications->complete()`: **Added**\n* `clerkbackend->commerce->listPlans()`: **Added**\n* `clerkbackend->commerce->listSubscriptionItems()`: **Added**\n* `clerkbackend->commerce->cancelSubscriptionItem()`: **Added**\n* `clerkbackend->m2m->createToken()`: **Added**\n* `clerkbackend->m2m->listTokens()`: **Added**\n* `clerkbackend->m2m->revokeToken()`: **Added**\n* `clerkbackend->m2m->verifyToken()`: **Added**\n* `clerkbackend->oauthaccesstokens->verify()`: **Added**\n* `clerkbackend->sessions->verify()`: **Deleted** **Breaking** :warning:\n* `clerkbackend->clients->list()`: `response.[]->sessions->[]->tasks` **Added**\n* `clerkbackend->clients->verify()`: `response.sessions->[]->tasks` **Added**\n* `clerkbackend->clients->get()`: `response.sessions->[]->tasks` **Added**\n* `clerkbackend->emailaddresses->create()`: `response.verification` **Changed**\n* `clerkbackend->emailaddresses->get()`: `response.verification` **Changed**\n* `clerkbackend->emailaddresses->update()`: `response.verification` **Changed**\n* `clerkbackend->phonenumbers->create()`: `response.verification` **Changed**\n* `clerkbackend->phonenumbers->get()`: `response.verification` **Changed**\n* `clerkbackend->phonenumbers->update()`: `response.verification` **Changed**\n* `clerkbackend->sessions->list()`: `response.[]->tasks` **Added**\n* `clerkbackend->sessions->create()`: `response.tasks` **Added**\n* `clerkbackend->sessions->get()`: `response.tasks` **Added**\n* `clerkbackend->waitlistentries->reject()`: **Added**\n* `clerkbackend->emailsmstemplates->list()`: `response.[]` **Changed**\n* `clerkbackend->emailsmstemplates->get()`: `response` **Changed**\n* `clerkbackend->waitlistentries->invite()`: **Added**\n* `clerkbackend->organizationdomains->listAll()`: **Added**\n* `clerkbackend->organizations->getBillingSubscription()`: **Added**\n* `clerkbackend->machines->deleteScope()`: **Added**\n* `clerkbackend->machines->createScope()`: **Added**\n* `clerkbackend->machines->getSecretKey()`: **Added**\n* `clerkbackend->machines->delete()`: **Added**\n* `clerkbackend->machines->update()`: **Added**\n* `clerkbackend->experimentalaccountlessapplications->create()`: **Added**\n* `clerkbackend->emailsmstemplates->revert()`: `response` **Changed**\n* `clerkbackend->emailsmstemplates->toggleTemplateDelivery()`: `response` **Changed**\n* `clerkbackend->emailandsmstemplates->upsert()`: `response` **Changed**\n* `clerkbackend->users->getOrganizationMemberships()`: `response.data->[]->organization` **Changed**\n* `clerkbackend->users->getInstanceOrganizationMemberships()`: `response.data->[]->organization` **Changed**\n* `clerkbackend->invitations->list()`: \n * `request->orderBy` **Changed**\n* `clerkbackend->machines->create()`: **Added**\n* `clerkbackend->machines->list()`: **Added**\n* `clerkbackend->instancesettings->updateOrganizationSettings()`: `response.maxAllowedPermissions` **Changed**\n* `clerkbackend->users->getBillingSubscription()`: **Added**\n* `clerkbackend->users->bulkUnban()`: **Added**\n* `clerkbackend->organizations->list()`: `response.data->[]` **Changed**\n* `clerkbackend->organizations->create()`: `response` **Changed**\n* `clerkbackend->organizations->get()`: `response` **Changed**\n* `clerkbackend->organizations->update()`: `response` **Changed**\n* `clerkbackend->organizations->mergeMetadata()`: `response` **Changed**\n* `clerkbackend->organizations->uploadLogo()`: `response.privateMetadata` **Changed**\n* `clerkbackend->organizations->deleteLogo()`: `response` **Changed**\n* `clerkbackend->organizationmemberships->create()`: `response.organization` **Changed**\n* `clerkbackend->organizationmemberships->list()`: `response.data->[]->organization` **Changed**\n* `clerkbackend->organizationmemberships->update()`: `response.organization` **Changed**\n* `clerkbackend->organizationmemberships->delete()`: \n * `response.organization` **Changed**\n * `error.status[422]` **Added**\n* `clerkbackend->organizationmemberships->updateMetadata()`: `response.organization` **Changed**\n* `clerkbackend->organizationdomains->create()`: `response.publicOrganizationData` **Added**\n* `clerkbackend->organizationdomains->list()`: `response.data->[]->publicOrganizationData` **Added**\n* `clerkbackend->organizationdomains->update()`: `response.publicOrganizationData` **Added**\n* `clerkbackend->oauthapplications->list()`: \n * `request` **Changed**\n * `response.data->[]` **Changed**\n* `clerkbackend->oauthapplications->create()`: \n * `request` **Changed**\n * `response` **Changed**\n* `clerkbackend->oauthapplications->get()`: `response` **Changed**\n* `clerkbackend->oauthapplications->update()`: \n * `requestBody` **Changed**\n * `response` **Changed**\n* `clerkbackend->oauthapplications->rotateSecret()`: `response` **Changed**\n* `clerkbackend->users->bulkBan()`: **Added**\n* `clerkbackend->sessions->refresh()`: **Added**\n* `clerkbackend->awscredentials->update()`: **Added**\n* `clerkbackend->awscredentials->delete()`: **Added**\n" +releaseNotes: | + ## Php SDK Changes Detected: + * `clerkbackend->machines->rotateSecretKey()`: **Added** + * `clerkbackend->waitlistentries->delete()`: **Added** + * `clerkbackend->commerce->extendSubscriptionItemFreeTrial()`: **Added** + * `clerkbackend->commerce->listSubscriptionItems()`: `request` **Changed** diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 9240503b..a891fb83 100755 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -16,12 +16,13 @@ generation: auth: oAuth2ClientCredentialsEnabled: false oAuth2PasswordEnabled: false + hoistGlobalSecurity: true tests: generateTests: true generateNewTests: false skipResponseBodyAssertions: false php: - version: 0.3.0 + version: 0.3.1 additionalDependencies: autoload-dev: Clerk\Backend\Tests\: Tests/ diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 834f16f4..582493ca 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,4 +1,4 @@ -speakeasyVersion: 1.606.9 +speakeasyVersion: 1.635.1 sources: backend-php: sourceNamespace: clerk-openapi @@ -14,20 +14,20 @@ sources: - latest clerk-openapi: sourceNamespace: clerk-openapi - sourceRevisionDigest: sha256:50ec69cb208a504bcf1098f28817af6691e8e924eb4349d141989a927680dfe8 - sourceBlobDigest: sha256:f8e89b57ae783aa6cc659bdc7c1d7955947b0c989a2224290169d25eb18c65df + sourceRevisionDigest: sha256:8a0bb9b60d98538847fe03fb23a22241be19f7f0bf3ced7c017bf1172723ad99 + sourceBlobDigest: sha256:dee56d92678973315fec5204a6f0aaad530965513edfbbc97723f50f669977ab tags: - latest - - speakeasy-sdk-regen-1753403775 + - speakeasy-sdk-regen-1756773147 - "2025-04-10" targets: clerk-php: source: clerk-openapi sourceNamespace: clerk-openapi - sourceRevisionDigest: sha256:50ec69cb208a504bcf1098f28817af6691e8e924eb4349d141989a927680dfe8 - sourceBlobDigest: sha256:f8e89b57ae783aa6cc659bdc7c1d7955947b0c989a2224290169d25eb18c65df + sourceRevisionDigest: sha256:8a0bb9b60d98538847fe03fb23a22241be19f7f0bf3ced7c017bf1172723ad99 + sourceBlobDigest: sha256:dee56d92678973315fec5204a6f0aaad530965513edfbbc97723f50f669977ab codeSamplesNamespace: clerk-openapi-php-code-samples - codeSamplesRevisionDigest: sha256:74b86f3a518a30c4c18a7f402e6e723dbf4d73d7c0cb69e78aa99989a75a1192 + codeSamplesRevisionDigest: sha256:e2d98f66450d30687666f4a585950a3c4fe66f00b2cf675776fce76bb5e172ff my-first-target: source: clerk-backend-php sourceNamespace: clerk-openapi diff --git a/README.md b/README.md index a7cd649f..e3c45f1d 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,7 @@ if ($response->statusCode === 200) { * [listPlans](docs/sdks/commerce/README.md#listplans) - List all commerce plans * [listSubscriptionItems](docs/sdks/commerce/README.md#listsubscriptionitems) - List all subscription items * [cancelSubscriptionItem](docs/sdks/commerce/README.md#cancelsubscriptionitem) - Cancel a subscription item +* [extendSubscriptionItemFreeTrial](docs/sdks/commerce/README.md#extendsubscriptionitemfreetrial) - Extend free trial for a subscription item ### [domains](docs/sdks/domains/README.md) @@ -300,6 +301,7 @@ if ($response->statusCode === 200) { * [update](docs/sdks/machines/README.md#update) - Update a machine * [delete](docs/sdks/machines/README.md#delete) - Delete a machine * [getSecretKey](docs/sdks/machines/README.md#getsecretkey) - Retrieve a machine secret key +* [rotateSecretKey](docs/sdks/machines/README.md#rotatesecretkey) - Rotate a machine's secret key * [createScope](docs/sdks/machines/README.md#createscope) - Create a machine scope * [deleteScope](docs/sdks/machines/README.md#deletescope) - Delete a machine scope @@ -447,6 +449,7 @@ if ($response->statusCode === 200) { * [list](docs/sdks/waitlistentries/README.md#list) - List all waitlist entries * [create](docs/sdks/waitlistentries/README.md#create) - Create a waitlist entry +* [delete](docs/sdks/waitlistentries/README.md#delete) - Delete a pending waitlist entry * [invite](docs/sdks/waitlistentries/README.md#invite) - Invite a waitlist entry * [reject](docs/sdks/waitlistentries/README.md#reject) - Reject a waitlist entry diff --git a/RELEASES.md b/RELEASES.md index c8965a51..05030fd4 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -38,4 +38,14 @@ Based on: ### Generated - [php v0.3.0] . ### Releases -- [Composer v0.3.0] https://packagist.org/packages/clerkinc/backend-php#v0.3.0 - . \ No newline at end of file +- [Composer v0.3.0] https://packagist.org/packages/clerkinc/backend-php#v0.3.0 - . + +## 2025-10-07 00:31:17 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.635.1 (2.722.2) https://github.com/speakeasy-api/speakeasy +### Generated +- [php v0.3.1] . +### Releases +- [Composer v0.3.1] https://packagist.org/packages/clerkinc/backend-php#v0.3.1 - . \ No newline at end of file diff --git a/docs/Models/Components/ExtendFreeTrialRequest.md b/docs/Models/Components/ExtendFreeTrialRequest.md new file mode 100644 index 00000000..f1882c89 --- /dev/null +++ b/docs/Models/Components/ExtendFreeTrialRequest.md @@ -0,0 +1,8 @@ +# ExtendFreeTrialRequest + + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `extendTo` | [\DateTime](https://www.php.net/manual/en/class.datetime.php) | :heavy_check_mark: | RFC3339 timestamp to extend the free trial to.
Must be in the future and not more than 365 days from now. | 2026-01-08T00:00:00Z | \ No newline at end of file diff --git a/docs/Models/Operations/DeleteWaitlistEntryRequest.md b/docs/Models/Operations/DeleteWaitlistEntryRequest.md new file mode 100644 index 00000000..b1f4af44 --- /dev/null +++ b/docs/Models/Operations/DeleteWaitlistEntryRequest.md @@ -0,0 +1,8 @@ +# DeleteWaitlistEntryRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------- | -------------------------------------- | -------------------------------------- | -------------------------------------- | +| `waitlistEntryId` | *string* | :heavy_check_mark: | The ID of the waitlist entry to delete | \ No newline at end of file diff --git a/docs/Models/Operations/DeleteWaitlistEntryResponse.md b/docs/Models/Operations/DeleteWaitlistEntryResponse.md new file mode 100644 index 00000000..195b365d --- /dev/null +++ b/docs/Models/Operations/DeleteWaitlistEntryResponse.md @@ -0,0 +1,11 @@ +# DeleteWaitlistEntryResponse + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| `contentType` | *string* | :heavy_check_mark: | HTTP response content type for this operation | +| `statusCode` | *int* | :heavy_check_mark: | HTTP response status code for this operation | +| `rawResponse` | [\Psr\Http\Message\ResponseInterface](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) | :heavy_check_mark: | Raw HTTP response; suitable for custom response parsing | +| `deletedObject` | [?Components\DeletedObject](../../Models/Components/DeletedObject.md) | :heavy_minus_sign: | Deleted Object | \ No newline at end of file diff --git a/docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.md b/docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.md new file mode 100644 index 00000000..f89003b0 --- /dev/null +++ b/docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.md @@ -0,0 +1,9 @@ +# ExtendCommerceSubscriptionItemFreeTrialRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `subscriptionItemId` | *string* | :heavy_check_mark: | The ID of the subscription item to extend the free trial for | +| `extendFreeTrialRequest` | [Components\ExtendFreeTrialRequest](../../Models/Components/ExtendFreeTrialRequest.md) | :heavy_check_mark: | Parameters for extending the free trial | \ No newline at end of file diff --git a/docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.md b/docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.md new file mode 100644 index 00000000..e09e18d1 --- /dev/null +++ b/docs/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.md @@ -0,0 +1,11 @@ +# ExtendCommerceSubscriptionItemFreeTrialResponse + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| `contentType` | *string* | :heavy_check_mark: | HTTP response content type for this operation | +| `statusCode` | *int* | :heavy_check_mark: | HTTP response status code for this operation | +| `rawResponse` | [\Psr\Http\Message\ResponseInterface](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) | :heavy_check_mark: | Raw HTTP response; suitable for custom response parsing | +| `commerceSubscriptionItem` | [?Components\CommerceSubscriptionItem](../../Models/Components/CommerceSubscriptionItem.md) | :heavy_minus_sign: | A commerce subscription item. | \ No newline at end of file diff --git a/docs/Models/Operations/GetCommerceSubscriptionItemListRequest.md b/docs/Models/Operations/GetCommerceSubscriptionItemListRequest.md index ac6cf87e..ff227848 100644 --- a/docs/Models/Operations/GetCommerceSubscriptionItemListRequest.md +++ b/docs/Models/Operations/GetCommerceSubscriptionItemListRequest.md @@ -12,4 +12,6 @@ | `payerType` | [?Operations\QueryParamPayerType](../../Models/Operations/QueryParamPayerType.md) | :heavy_minus_sign: | Filter subscription items by payer type | | `planId` | *?string* | :heavy_minus_sign: | Filter subscription items by plan ID | | `includeFree` | *?bool* | :heavy_minus_sign: | Whether to include free plan subscription items | -| `query` | *?string* | :heavy_minus_sign: | Search query to filter subscription items by email, user first name, user last name, or organization name.
Supports partial matching. | \ No newline at end of file +| `query` | *?string* | :heavy_minus_sign: | Search query to filter subscription items by email, user first name, user last name, or organization name.
Supports partial matching. | +| `userId` | *?string* | :heavy_minus_sign: | Filter subscription items by user ID | +| `organizationId` | *?string* | :heavy_minus_sign: | Filter subscription items by organization ID | \ No newline at end of file diff --git a/docs/Models/Operations/RotateMachineSecretKeyRequest.md b/docs/Models/Operations/RotateMachineSecretKeyRequest.md new file mode 100644 index 00000000..1ade0e87 --- /dev/null +++ b/docs/Models/Operations/RotateMachineSecretKeyRequest.md @@ -0,0 +1,9 @@ +# RotateMachineSecretKeyRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| `machineId` | *string* | :heavy_check_mark: | The ID of the machine to rotate the secret key for | +| `requestBody` | [Operations\RotateMachineSecretKeyRequestBody](../../Models/Operations/RotateMachineSecretKeyRequestBody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/Models/Operations/RotateMachineSecretKeyRequestBody.md b/docs/Models/Operations/RotateMachineSecretKeyRequestBody.md new file mode 100644 index 00000000..6846d0ff --- /dev/null +++ b/docs/Models/Operations/RotateMachineSecretKeyRequestBody.md @@ -0,0 +1,8 @@ +# RotateMachineSecretKeyRequestBody + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `previousTokenTtl` | *int* | :heavy_check_mark: | The time in seconds that the previous secret key will remain valid after rotation.
This ensures a graceful transition period for updating applications with the new secret key.
Set to 0 to immediately expire the previous key. Maximum value is 8 hours (28800 seconds). | \ No newline at end of file diff --git a/docs/Models/Operations/RotateMachineSecretKeyResponse.md b/docs/Models/Operations/RotateMachineSecretKeyResponse.md new file mode 100644 index 00000000..fbd07d80 --- /dev/null +++ b/docs/Models/Operations/RotateMachineSecretKeyResponse.md @@ -0,0 +1,11 @@ +# RotateMachineSecretKeyResponse + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| `contentType` | *string* | :heavy_check_mark: | HTTP response content type for this operation | +| `statusCode` | *int* | :heavy_check_mark: | HTTP response status code for this operation | +| `rawResponse` | [\Psr\Http\Message\ResponseInterface](https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface) | :heavy_check_mark: | Raw HTTP response; suitable for custom response parsing | +| `machineSecretKey` | [?Components\MachineSecretKey](../../Models/Components/MachineSecretKey.md) | :heavy_minus_sign: | Success | \ No newline at end of file diff --git a/docs/sdks/commerce/README.md b/docs/sdks/commerce/README.md index 5a825c46..f60ae57d 100644 --- a/docs/sdks/commerce/README.md +++ b/docs/sdks/commerce/README.md @@ -8,6 +8,7 @@ * [listPlans](#listplans) - List all commerce plans * [listSubscriptionItems](#listsubscriptionitems) - List all subscription items * [cancelSubscriptionItem](#cancelsubscriptionitem) - Cancel a subscription item +* [extendSubscriptionItemFreeTrial](#extendsubscriptionitemfreetrial) - Extend free trial for a subscription item ## listPlans @@ -161,6 +162,65 @@ if ($response->commerceSubscriptionItem !== null) { ### Errors +| Error Type | Status Code | Content Type | +| ----------------------- | ----------------------- | ----------------------- | +| Errors\ClerkErrors | 400, 401, 403, 404, 422 | application/json | +| Errors\ClerkErrors | 500 | application/json | +| Errors\SDKException | 4XX, 5XX | \*/\* | + +## extendSubscriptionItemFreeTrial + +Extends the free trial period for a specific subscription item to the specified timestamp. +The subscription item must be currently in a free trial period, and the plan must support free trials. +The timestamp must be in the future and not more than 365 days from the end of the current trial period +This operation is idempotent - repeated requests with the same timestamp will not change the trial period. + +### Example Usage + + +```php +declare(strict_types=1); + +require 'vendor/autoload.php'; + +use Clerk\Backend; +use Clerk\Backend\Models\Components; +use Clerk\Backend\Utils; + +$sdk = Backend\ClerkBackend::builder() + ->setSecurity( + '' + ) + ->build(); + +$extendFreeTrialRequest = new Components\ExtendFreeTrialRequest( + extendTo: Utils\Utils::parseDateTime('2026-01-08T00:00:00Z'), +); + +$response = $sdk->commerce->extendSubscriptionItemFreeTrial( + subscriptionItemId: '', + extendFreeTrialRequest: $extendFreeTrialRequest + +); + +if ($response->commerceSubscriptionItem !== null) { + // handle response +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `subscriptionItemId` | *string* | :heavy_check_mark: | The ID of the subscription item to extend the free trial for | +| `extendFreeTrialRequest` | [Components\ExtendFreeTrialRequest](../../Models/Components/ExtendFreeTrialRequest.md) | :heavy_check_mark: | Parameters for extending the free trial | + +### Response + +**[?Operations\ExtendCommerceSubscriptionItemFreeTrialResponse](../../Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.md)** + +### Errors + | Error Type | Status Code | Content Type | | ----------------------- | ----------------------- | ----------------------- | | Errors\ClerkErrors | 400, 401, 403, 404, 422 | application/json | diff --git a/docs/sdks/machines/README.md b/docs/sdks/machines/README.md index 3a67598a..3d08febb 100644 --- a/docs/sdks/machines/README.md +++ b/docs/sdks/machines/README.md @@ -11,6 +11,7 @@ * [update](#update) - Update a machine * [delete](#delete) - Delete a machine * [getSecretKey](#getsecretkey) - Retrieve a machine secret key +* [rotateSecretKey](#rotatesecretkey) - Rotate a machine's secret key * [createScope](#createscope) - Create a machine scope * [deleteScope](#deletescope) - Delete a machine scope @@ -314,6 +315,62 @@ if ($response->machineSecretKey !== null) { | Errors\ClerkErrors | 400, 401, 403, 404 | application/json | | Errors\SDKException | 4XX, 5XX | \*/\* | +## rotateSecretKey + +Rotates the machine's secret key. +When the secret key is rotated, make sure to update it in your machine/application. +The previous secret key will remain valid for the duration specified by the previous_token_ttl parameter. + +### Example Usage + + +```php +declare(strict_types=1); + +require 'vendor/autoload.php'; + +use Clerk\Backend; +use Clerk\Backend\Models\Operations; + +$sdk = Backend\ClerkBackend::builder() + ->setSecurity( + '' + ) + ->build(); + +$requestBody = new Operations\RotateMachineSecretKeyRequestBody( + previousTokenTtl: 632625, +); + +$response = $sdk->machines->rotateSecretKey( + machineId: '', + requestBody: $requestBody + +); + +if ($response->machineSecretKey !== null) { + // handle response +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| `machineId` | *string* | :heavy_check_mark: | The ID of the machine to rotate the secret key for | +| `requestBody` | [Operations\RotateMachineSecretKeyRequestBody](../../Models/Operations/RotateMachineSecretKeyRequestBody.md) | :heavy_check_mark: | N/A | + +### Response + +**[?Operations\RotateMachineSecretKeyResponse](../../Models/Operations/RotateMachineSecretKeyResponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| ----------------------- | ----------------------- | ----------------------- | +| Errors\ClerkErrors | 400, 401, 403, 404, 422 | application/json | +| Errors\SDKException | 4XX, 5XX | \*/\* | + ## createScope Creates a new machine scope, allowing the specified machine to access another machine. diff --git a/docs/sdks/waitlistentries/README.md b/docs/sdks/waitlistentries/README.md index b3a32252..c20c4196 100644 --- a/docs/sdks/waitlistentries/README.md +++ b/docs/sdks/waitlistentries/README.md @@ -7,6 +7,7 @@ * [list](#list) - List all waitlist entries * [create](#create) - Create a waitlist entry +* [delete](#delete) - Delete a pending waitlist entry * [invite](#invite) - Invite a waitlist entry * [reject](#reject) - Reject a waitlist entry @@ -109,6 +110,54 @@ if ($response->waitlistEntry !== null) { | Errors\ClerkErrors | 400, 422 | application/json | | Errors\SDKException | 4XX, 5XX | \*/\* | +## delete + +Delete a pending waitlist entry. + +### Example Usage + + +```php +declare(strict_types=1); + +require 'vendor/autoload.php'; + +use Clerk\Backend; + +$sdk = Backend\ClerkBackend::builder() + ->setSecurity( + '' + ) + ->build(); + + + +$response = $sdk->waitlistEntries->delete( + waitlistEntryId: '' +); + +if ($response->deletedObject !== null) { + // handle response +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------- | -------------------------------------- | -------------------------------------- | -------------------------------------- | +| `waitlistEntryId` | *string* | :heavy_check_mark: | The ID of the waitlist entry to delete | + +### Response + +**[?Operations\DeleteWaitlistEntryResponse](../../Models/Operations/DeleteWaitlistEntryResponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| ------------------- | ------------------- | ------------------- | +| Errors\ClerkErrors | 400, 404, 409, 422 | application/json | +| Errors\SDKException | 4XX, 5XX | \*/\* | + ## invite Send an invite to the email address in a waitlist entry. diff --git a/src/Commerce.php b/src/Commerce.php index f577abad..e2ef5eb2 100644 --- a/src/Commerce.php +++ b/src/Commerce.php @@ -9,6 +9,7 @@ namespace Clerk\Backend; use Clerk\Backend\Hooks\HookContext; +use Clerk\Backend\Models\Components; use Clerk\Backend\Models\Operations; use Clerk\Backend\Utils\Options; use Clerk\Backend\Utils\Retry; @@ -161,6 +162,126 @@ public function cancelSubscriptionItem(string $subscriptionItemId, ?bool $endNow } } + /** + * Extend free trial for a subscription item + * + * Extends the free trial period for a specific subscription item to the specified timestamp. + * The subscription item must be currently in a free trial period, and the plan must support free trials. + * The timestamp must be in the future and not more than 365 days from the end of the current trial period + * This operation is idempotent - repeated requests with the same timestamp will not change the trial period. + * + * @param Components\ExtendFreeTrialRequest $extendFreeTrialRequest + * @param string $subscriptionItemId + * @return Operations\ExtendCommerceSubscriptionItemFreeTrialResponse + * @throws \Clerk\Backend\Models\Errors\SDKException + */ + public function extendSubscriptionItemFreeTrial(Components\ExtendFreeTrialRequest $extendFreeTrialRequest, string $subscriptionItemId, ?Options $options = null): Operations\ExtendCommerceSubscriptionItemFreeTrialResponse + { + $retryConfig = null; + if ($options) { + $retryConfig = $options->retryConfig; + } + if ($retryConfig === null && $this->sdkConfiguration->retryConfig) { + $retryConfig = $this->sdkConfiguration->retryConfig; + } else { + $retryConfig = new Retry\RetryConfigBackoff( + initialIntervalMs: 500, + maxIntervalMs: 60000, + exponent: 1.5, + maxElapsedTimeMs: 3600000, + retryConnectionErrors: true, + ); + } + $retryCodes = null; + if ($options) { + $retryCodes = $options->retryCodes; + } + if ($retryCodes === null) { + $retryCodes = [ + '5XX', + ]; + } + $request = new Operations\ExtendCommerceSubscriptionItemFreeTrialRequest( + subscriptionItemId: $subscriptionItemId, + extendFreeTrialRequest: $extendFreeTrialRequest, + ); + $baseUrl = $this->sdkConfiguration->getTemplatedServerUrl(); + $url = Utils\Utils::generateUrl($baseUrl, '/billing/subscription_items/{subscription_item_id}/extend_free_trial', Operations\ExtendCommerceSubscriptionItemFreeTrialRequest::class, $request); + $urlOverride = null; + $httpOptions = ['http_errors' => false]; + $body = Utils\Utils::serializeRequestBody($request, 'extendFreeTrialRequest', 'json'); + if ($body === null) { + throw new \Exception('Request body is required'); + } + $httpOptions = array_merge_recursive($httpOptions, $body); + $httpOptions['headers']['Accept'] = 'application/json'; + $httpOptions['headers']['user-agent'] = $this->sdkConfiguration->userAgent; + $httpRequest = new \GuzzleHttp\Psr7\Request('POST', $url); + $hookContext = new HookContext($this->sdkConfiguration, $baseUrl, 'ExtendCommerceSubscriptionItemFreeTrial', [], $this->sdkConfiguration->securitySource); + $httpRequest = $this->sdkConfiguration->hooks->beforeRequest(new Hooks\BeforeRequestContext($hookContext), $httpRequest); + $httpOptions = Utils\Utils::convertHeadersToOptions($httpRequest, $httpOptions); + $httpRequest = Utils\Utils::removeHeaders($httpRequest); + try { + $httpResponse = RetryUtils::retryWrapper(fn () => $this->sdkConfiguration->client->send($httpRequest, $httpOptions), $retryConfig, $retryCodes); + } catch (\GuzzleHttp\Exception\GuzzleException $error) { + $res = $this->sdkConfiguration->hooks->afterError(new Hooks\AfterErrorContext($hookContext), null, $error); + $httpResponse = $res; + } + $contentType = $httpResponse->getHeader('Content-Type')[0] ?? ''; + + $statusCode = $httpResponse->getStatusCode(); + if (Utils\Utils::matchStatusCodes($statusCode, ['400', '401', '403', '404', '422', '4XX', '500', '5XX'])) { + $res = $this->sdkConfiguration->hooks->afterError(new Hooks\AfterErrorContext($hookContext), $httpResponse, null); + $httpResponse = $res; + } + if (Utils\Utils::matchStatusCodes($statusCode, ['200'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Components\CommerceSubscriptionItem', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + $response = new Operations\ExtendCommerceSubscriptionItemFreeTrialResponse( + statusCode: $statusCode, + contentType: $contentType, + rawResponse: $httpResponse, + commerceSubscriptionItem: $obj); + + return $response; + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['400', '401', '403', '404', '422'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Errors\ClerkErrors', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + throw $obj->toException(); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['500'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Errors\ClerkErrors', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + throw $obj->toException(); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['4XX'])) { + throw new \Clerk\Backend\Models\Errors\SDKException('API error occurred', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['5XX'])) { + throw new \Clerk\Backend\Models\Errors\SDKException('API error occurred', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown status code received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } + /** * List all commerce plans * diff --git a/src/Machines.php b/src/Machines.php index 66c744d4..a08cff6d 100644 --- a/src/Machines.php +++ b/src/Machines.php @@ -760,6 +760,114 @@ public function list(?int $limit = null, ?int $offset = null, ?string $query = n } } + /** + * Rotate a machine's secret key + * + * Rotates the machine's secret key. + * When the secret key is rotated, make sure to update it in your machine/application. + * The previous secret key will remain valid for the duration specified by the previous_token_ttl parameter. + * + * @param Operations\RotateMachineSecretKeyRequestBody $requestBody + * @param string $machineId + * @return Operations\RotateMachineSecretKeyResponse + * @throws \Clerk\Backend\Models\Errors\SDKException + */ + public function rotateSecretKey(Operations\RotateMachineSecretKeyRequestBody $requestBody, string $machineId, ?Options $options = null): Operations\RotateMachineSecretKeyResponse + { + $retryConfig = null; + if ($options) { + $retryConfig = $options->retryConfig; + } + if ($retryConfig === null && $this->sdkConfiguration->retryConfig) { + $retryConfig = $this->sdkConfiguration->retryConfig; + } else { + $retryConfig = new Retry\RetryConfigBackoff( + initialIntervalMs: 500, + maxIntervalMs: 60000, + exponent: 1.5, + maxElapsedTimeMs: 3600000, + retryConnectionErrors: true, + ); + } + $retryCodes = null; + if ($options) { + $retryCodes = $options->retryCodes; + } + if ($retryCodes === null) { + $retryCodes = [ + '5XX', + ]; + } + $request = new Operations\RotateMachineSecretKeyRequest( + machineId: $machineId, + requestBody: $requestBody, + ); + $baseUrl = $this->sdkConfiguration->getTemplatedServerUrl(); + $url = Utils\Utils::generateUrl($baseUrl, '/machines/{machine_id}/secret_key/rotate', Operations\RotateMachineSecretKeyRequest::class, $request); + $urlOverride = null; + $httpOptions = ['http_errors' => false]; + $body = Utils\Utils::serializeRequestBody($request, 'requestBody', 'json'); + if ($body === null) { + throw new \Exception('Request body is required'); + } + $httpOptions = array_merge_recursive($httpOptions, $body); + $httpOptions['headers']['Accept'] = 'application/json'; + $httpOptions['headers']['user-agent'] = $this->sdkConfiguration->userAgent; + $httpRequest = new \GuzzleHttp\Psr7\Request('POST', $url); + $hookContext = new HookContext($this->sdkConfiguration, $baseUrl, 'RotateMachineSecretKey', [], $this->sdkConfiguration->securitySource); + $httpRequest = $this->sdkConfiguration->hooks->beforeRequest(new Hooks\BeforeRequestContext($hookContext), $httpRequest); + $httpOptions = Utils\Utils::convertHeadersToOptions($httpRequest, $httpOptions); + $httpRequest = Utils\Utils::removeHeaders($httpRequest); + try { + $httpResponse = RetryUtils::retryWrapper(fn () => $this->sdkConfiguration->client->send($httpRequest, $httpOptions), $retryConfig, $retryCodes); + } catch (\GuzzleHttp\Exception\GuzzleException $error) { + $res = $this->sdkConfiguration->hooks->afterError(new Hooks\AfterErrorContext($hookContext), null, $error); + $httpResponse = $res; + } + $contentType = $httpResponse->getHeader('Content-Type')[0] ?? ''; + + $statusCode = $httpResponse->getStatusCode(); + if (Utils\Utils::matchStatusCodes($statusCode, ['400', '401', '403', '404', '422', '4XX', '5XX'])) { + $res = $this->sdkConfiguration->hooks->afterError(new Hooks\AfterErrorContext($hookContext), $httpResponse, null); + $httpResponse = $res; + } + if (Utils\Utils::matchStatusCodes($statusCode, ['200'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Components\MachineSecretKey', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + $response = new Operations\RotateMachineSecretKeyResponse( + statusCode: $statusCode, + contentType: $contentType, + rawResponse: $httpResponse, + machineSecretKey: $obj); + + return $response; + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['400', '401', '403', '404', '422'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Errors\ClerkErrors', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + throw $obj->toException(); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['4XX'])) { + throw new \Clerk\Backend\Models\Errors\SDKException('API error occurred', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['5XX'])) { + throw new \Clerk\Backend\Models\Errors\SDKException('API error occurred', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown status code received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } + /** * Update a machine * diff --git a/src/Models/Components/ExtendFreeTrialRequest.php b/src/Models/Components/ExtendFreeTrialRequest.php new file mode 100644 index 00000000..0ee79770 --- /dev/null +++ b/src/Models/Components/ExtendFreeTrialRequest.php @@ -0,0 +1,32 @@ +extendTo = $extendTo; + } +} \ No newline at end of file diff --git a/src/Models/Operations/DeleteWaitlistEntryRequest.php b/src/Models/Operations/DeleteWaitlistEntryRequest.php new file mode 100644 index 00000000..e99be2ea --- /dev/null +++ b/src/Models/Operations/DeleteWaitlistEntryRequest.php @@ -0,0 +1,30 @@ +waitlistEntryId = $waitlistEntryId; + } +} \ No newline at end of file diff --git a/src/Models/Operations/DeleteWaitlistEntryResponse.php b/src/Models/Operations/DeleteWaitlistEntryResponse.php new file mode 100644 index 00000000..5b1168d7 --- /dev/null +++ b/src/Models/Operations/DeleteWaitlistEntryResponse.php @@ -0,0 +1,56 @@ +contentType = $contentType; + $this->statusCode = $statusCode; + $this->rawResponse = $rawResponse; + $this->deletedObject = $deletedObject; + } +} \ No newline at end of file diff --git a/src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.php b/src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.php new file mode 100644 index 00000000..b39d6ada --- /dev/null +++ b/src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialRequest.php @@ -0,0 +1,41 @@ +subscriptionItemId = $subscriptionItemId; + $this->extendFreeTrialRequest = $extendFreeTrialRequest; + } +} \ No newline at end of file diff --git a/src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.php b/src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.php new file mode 100644 index 00000000..158704b9 --- /dev/null +++ b/src/Models/Operations/ExtendCommerceSubscriptionItemFreeTrialResponse.php @@ -0,0 +1,56 @@ +contentType = $contentType; + $this->statusCode = $statusCode; + $this->rawResponse = $rawResponse; + $this->commerceSubscriptionItem = $commerceSubscriptionItem; + } +} \ No newline at end of file diff --git a/src/Models/Operations/GetCommerceSubscriptionItemListRequest.php b/src/Models/Operations/GetCommerceSubscriptionItemListRequest.php index 3403dceb..068b231a 100644 --- a/src/Models/Operations/GetCommerceSubscriptionItemListRequest.php +++ b/src/Models/Operations/GetCommerceSubscriptionItemListRequest.php @@ -56,6 +56,22 @@ class GetCommerceSubscriptionItemListRequest #[SpeakeasyMetadata('queryParam:style=form,explode=true,name=query')] public ?string $query = null; + /** + * Filter subscription items by user ID + * + * @var ?string $userId + */ + #[SpeakeasyMetadata('queryParam:style=form,explode=true,name=user_id')] + public ?string $userId = null; + + /** + * Filter subscription items by organization ID + * + * @var ?string $organizationId + */ + #[SpeakeasyMetadata('queryParam:style=form,explode=true,name=organization_id')] + public ?string $organizationId = null; + /** * Applies a limit to the number of results returned. * @@ -94,15 +110,19 @@ class GetCommerceSubscriptionItemListRequest * @param ?string $planId * @param ?bool $includeFree * @param ?string $query + * @param ?string $userId + * @param ?string $organizationId * @phpstan-pure */ - public function __construct(?bool $paginated = null, ?GetCommerceSubscriptionItemListQueryParamStatus $status = null, ?QueryParamPayerType $payerType = null, ?string $planId = null, ?string $query = null, ?int $limit = 10, ?int $offset = 0, ?bool $includeFree = false) + public function __construct(?bool $paginated = null, ?GetCommerceSubscriptionItemListQueryParamStatus $status = null, ?QueryParamPayerType $payerType = null, ?string $planId = null, ?string $query = null, ?string $userId = null, ?string $organizationId = null, ?int $limit = 10, ?int $offset = 0, ?bool $includeFree = false) { $this->paginated = $paginated; $this->status = $status; $this->payerType = $payerType; $this->planId = $planId; $this->query = $query; + $this->userId = $userId; + $this->organizationId = $organizationId; $this->limit = $limit; $this->offset = $offset; $this->includeFree = $includeFree; diff --git a/src/Models/Operations/RotateMachineSecretKeyRequest.php b/src/Models/Operations/RotateMachineSecretKeyRequest.php new file mode 100644 index 00000000..afdc7e2b --- /dev/null +++ b/src/Models/Operations/RotateMachineSecretKeyRequest.php @@ -0,0 +1,39 @@ +machineId = $machineId; + $this->requestBody = $requestBody; + } +} \ No newline at end of file diff --git a/src/Models/Operations/RotateMachineSecretKeyRequestBody.php b/src/Models/Operations/RotateMachineSecretKeyRequestBody.php new file mode 100644 index 00000000..bad8a349 --- /dev/null +++ b/src/Models/Operations/RotateMachineSecretKeyRequestBody.php @@ -0,0 +1,33 @@ +previousTokenTtl = $previousTokenTtl; + } +} \ No newline at end of file diff --git a/src/Models/Operations/RotateMachineSecretKeyResponse.php b/src/Models/Operations/RotateMachineSecretKeyResponse.php new file mode 100644 index 00000000..d750c9bf --- /dev/null +++ b/src/Models/Operations/RotateMachineSecretKeyResponse.php @@ -0,0 +1,56 @@ +contentType = $contentType; + $this->statusCode = $statusCode; + $this->rawResponse = $rawResponse; + $this->machineSecretKey = $machineSecretKey; + } +} \ No newline at end of file diff --git a/src/SDKConfiguration.php b/src/SDKConfiguration.php index f0e01c0c..885b1e71 100644 --- a/src/SDKConfiguration.php +++ b/src/SDKConfiguration.php @@ -24,11 +24,11 @@ class SDKConfiguration public string $openapiDocVersion = '2025-04-10'; - public string $sdkVersion = '0.3.0'; + public string $sdkVersion = '0.3.1'; - public string $genVersion = '2.687.13'; + public string $genVersion = '2.722.2'; - public string $userAgent = 'speakeasy-sdk/php 0.3.0 2.687.13 2025-04-10 clerkinc/backend-php'; + public string $userAgent = 'speakeasy-sdk/php 0.3.1 2.722.2 2025-04-10 clerkinc/backend-php'; public ?RetryConfig $retryConfig = null; diff --git a/src/Utils/Retry/RetryUtils.php b/src/Utils/Retry/RetryUtils.php index c18ec508..5f93f1cc 100644 --- a/src/Utils/Retry/RetryUtils.php +++ b/src/Utils/Retry/RetryUtils.php @@ -104,9 +104,13 @@ public static function isRetryableResponse(ResponseInterface $response, array $s $final = false; foreach ($statusCodes as $code) { - $matches = []; - if (! preg_match('/^[0-9]xx$/', $code, $matches)) { - return $code === $actual; + if (! preg_match('/^[0-9]xx$/', $code)) { + $final = $code === $actual; + if ($final) { + break; + } + + continue; } $expectFamily = mb_substr($code, 0, 1); @@ -121,6 +125,7 @@ public static function isRetryableResponse(ResponseInterface $response, array $s if ($actualFamily === $expectFamily) { $final = true; + break; } } diff --git a/src/WaitlistEntries.php b/src/WaitlistEntries.php index 45a20fab..0396e231 100644 --- a/src/WaitlistEntries.php +++ b/src/WaitlistEntries.php @@ -147,6 +147,105 @@ public function create(?Operations\CreateWaitlistEntryRequestBody $request = nul } } + /** + * Delete a pending waitlist entry + * + * Delete a pending waitlist entry. + * + * @param string $waitlistEntryId + * @return Operations\DeleteWaitlistEntryResponse + * @throws \Clerk\Backend\Models\Errors\SDKException + */ + public function delete(string $waitlistEntryId, ?Options $options = null): Operations\DeleteWaitlistEntryResponse + { + $retryConfig = null; + if ($options) { + $retryConfig = $options->retryConfig; + } + if ($retryConfig === null && $this->sdkConfiguration->retryConfig) { + $retryConfig = $this->sdkConfiguration->retryConfig; + } else { + $retryConfig = new Retry\RetryConfigBackoff( + initialIntervalMs: 500, + maxIntervalMs: 60000, + exponent: 1.5, + maxElapsedTimeMs: 3600000, + retryConnectionErrors: true, + ); + } + $retryCodes = null; + if ($options) { + $retryCodes = $options->retryCodes; + } + if ($retryCodes === null) { + $retryCodes = [ + '5XX', + ]; + } + $request = new Operations\DeleteWaitlistEntryRequest( + waitlistEntryId: $waitlistEntryId, + ); + $baseUrl = $this->sdkConfiguration->getTemplatedServerUrl(); + $url = Utils\Utils::generateUrl($baseUrl, '/waitlist_entries/{waitlist_entry_id}', Operations\DeleteWaitlistEntryRequest::class, $request); + $urlOverride = null; + $httpOptions = ['http_errors' => false]; + $httpOptions['headers']['Accept'] = 'application/json'; + $httpOptions['headers']['user-agent'] = $this->sdkConfiguration->userAgent; + $httpRequest = new \GuzzleHttp\Psr7\Request('DELETE', $url); + $hookContext = new HookContext($this->sdkConfiguration, $baseUrl, 'DeleteWaitlistEntry', [], $this->sdkConfiguration->securitySource); + $httpRequest = $this->sdkConfiguration->hooks->beforeRequest(new Hooks\BeforeRequestContext($hookContext), $httpRequest); + $httpOptions = Utils\Utils::convertHeadersToOptions($httpRequest, $httpOptions); + $httpRequest = Utils\Utils::removeHeaders($httpRequest); + try { + $httpResponse = RetryUtils::retryWrapper(fn () => $this->sdkConfiguration->client->send($httpRequest, $httpOptions), $retryConfig, $retryCodes); + } catch (\GuzzleHttp\Exception\GuzzleException $error) { + $res = $this->sdkConfiguration->hooks->afterError(new Hooks\AfterErrorContext($hookContext), null, $error); + $httpResponse = $res; + } + $contentType = $httpResponse->getHeader('Content-Type')[0] ?? ''; + + $statusCode = $httpResponse->getStatusCode(); + if (Utils\Utils::matchStatusCodes($statusCode, ['400', '404', '409', '422', '4XX', '5XX'])) { + $res = $this->sdkConfiguration->hooks->afterError(new Hooks\AfterErrorContext($hookContext), $httpResponse, null); + $httpResponse = $res; + } + if (Utils\Utils::matchStatusCodes($statusCode, ['200'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Components\DeletedObject', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + $response = new Operations\DeleteWaitlistEntryResponse( + statusCode: $statusCode, + contentType: $contentType, + rawResponse: $httpResponse, + deletedObject: $obj); + + return $response; + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['400', '404', '409', '422'])) { + if (Utils\Utils::matchContentType($contentType, 'application/json')) { + $httpResponse = $this->sdkConfiguration->hooks->afterSuccess(new Hooks\AfterSuccessContext($hookContext), $httpResponse); + + $serializer = Utils\JSON::createSerializer(); + $responseData = (string) $httpResponse->getBody(); + $obj = $serializer->deserialize($responseData, '\Clerk\Backend\Models\Errors\ClerkErrors', 'json', DeserializationContext::create()->setRequireAllRequiredProperties(true)); + throw $obj->toException(); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown content type received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['4XX'])) { + throw new \Clerk\Backend\Models\Errors\SDKException('API error occurred', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } elseif (Utils\Utils::matchStatusCodes($statusCode, ['5XX'])) { + throw new \Clerk\Backend\Models\Errors\SDKException('API error occurred', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } else { + throw new \Clerk\Backend\Models\Errors\SDKException('Unknown status code received', $statusCode, $httpResponse->getBody()->getContents(), $httpResponse); + } + } + /** * Invite a waitlist entry *