# post\_subscription\_buy

`POST /subscriptions/buy`

*Purchase Subscription*

Initiate a subscription purchase for the authenticated user's organization. For paid subscriptions, creates a Stripe checkout session for payment processing. For free subscriptions, immediately activates the subscription without payment processing. Allows subscription changes by automatically handling cancellation of existing subscriptions.

#### Parameters

| Name                 | In   | Type   | Required | Description                                   |
| -------------------- | ---- | ------ | -------- | --------------------------------------------- |
| subscriptionPeriodId | body | string | true     | Unique identifier for the subscription period |

#### TypeScript Client Library

```typescript
public buySubscription = async (data: BuySubscriptionRequest): Promise<BuySubscriptionResponse> => {
  return this.makeRequest<BuySubscriptionResponse>('subscriptions/buy', 'POST', data);
};
```

#### Code Samples

{% tabs %}
{% tab title="Shell" %}

```shell
curl -X POST https://backend.flashback.tech/subscriptions/buy \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer {access-token}' \
  -H 'Content-Type: application/json' \
  -d '{
    "subscriptionPeriodId": "123e4567-e89b-12d3-a456-426614174000"
  }'
```

{% endtab %}

{% tab title="HTTP" %}

```http
POST https://backend.flashback.tech/subscriptions/buy HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Bearer {access-token}
Content-Type: application/json

{
  "subscriptionPeriodId": "123e4567-e89b-12d3-a456-426614174000"
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer {access-token}',
  'Content-Type':'application/json'
};

const body = {
  subscriptionPeriodId: '123e4567-e89b-12d3-a456-426614174000'
};

fetch('https://backend.flashback.tech/subscriptions/buy',
{
  method: 'POST',
  headers: headers,
  body: JSON.stringify(body)
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer {access-token}',
  'Content-Type' => 'application/json'
}

body = {
  subscriptionPeriodId: '123e4567-e89b-12d3-a456-426614174000'
}

result = RestClient.post 'https://backend.flashback.tech/subscriptions/buy',
  body.to_json, headers: headers

p JSON.parse(result)
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
import json

headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer {access-token}',
  'Content-Type': 'application/json'
}

body = {
  'subscriptionPeriodId': '123e4567-e89b-12d3-a456-426614174000'
}

r = requests.post('https://backend.flashback.tech/subscriptions/buy', 
                  headers=headers, 
                  data=json.dumps(body))

print(r.json())
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
    'Authorization' => 'Bearer {access-token}',
    'Content-Type' => 'application/json',
);

$body = array(
    'subscriptionPeriodId' => '123e4567-e89b-12d3-a456-426614174000'
);

$client = new \GuzzleHttp\Client();

try {
    $response = $client->request('POST','https://backend.flashback.tech/subscriptions/buy', array(
        'headers' => $headers,
        'json' => $body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...
```

{% endtab %}

{% tab title="Java" %}

```java
URL obj = new URL("https://backend.flashback.tech/subscriptions/buy");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Authorization", "Bearer {access-token}");

String body = "{\"subscriptionPeriodId\":\"123e4567-e89b-12d3-a456-426614174000\"}";

con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(body);
wr.close();

int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
       "bytes"
       "net/http"
       "encoding/json"
)

func main() {
    headers := map[string][]string{
        "Accept": []string{"application/json"},
        "Authorization": []string{"Bearer {access-token}"},
        "Content-Type": []string{"application/json"},
    }

    body := map[string]string{
        "subscriptionPeriodId": "123e4567-e89b-12d3-a456-426614174000",
    }
    
    jsonBody, _ := json.Marshal(body)
    data := bytes.NewBuffer(jsonBody)
    req, err := http.NewRequest("POST", "https://backend.flashback.tech/subscriptions/buy", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}
```

{% endtab %}
{% endtabs %}

> Example responses

> 200 Response (Paid Subscription)

```json
{
  "success": true,
  "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_1234567890abcdef",
  "sessionId": "cs_test_1234567890abcdef",
  "isSubscriptionChange": false,
  "previousSubscription": null,
  "isFreeSubscription": false
}
```

> 200 Response (Free Subscription)

```json
{
  "success": true,
  "checkoutUrl": null,
  "sessionId": "free_sub_1234567890abcdef_1642248600000",
  "isSubscriptionChange": false,
  "previousSubscription": null,
  "isFreeSubscription": true
}
```

> 200 Response (Subscription Change)

```json
{
  "success": true,
  "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_1234567890abcdef",
  "sessionId": "cs_test_1234567890abcdef",
  "isSubscriptionChange": true,
  "previousSubscription": {
    "id": "sub_old1234567890abcdef",
    "name": "Basic Plan"
  },
  "isFreeSubscription": false
}
```

> 400 Response (No Organization)

```json
{
  "success": false,
  "error_code": "NO_ORGANIZATION",
  "message": "User must belong to an organization"
}
```

> 400 Response (Stripe ID Missing)

```json
{
  "success": false,
  "error_code": "STRIPE_ID_MISSING",
  "message": "Subscription period is not configured for payments"
}
```

> 400 Response (Stripe Price Invalid)

```json
{
  "success": false,
  "error_code": "STRIPE_PRICE_INVALID",
  "message": "Invalid Stripe price configuration"
}
```

> 404 Response

```json
{
  "success": false,
  "error_code": "USER_NOT_FOUND",
  "message": "User not found"
}
```

> 404 Response (Subscription Not Found)

```json
{
  "success": false,
  "error_code": "SUBSCRIPTION_PERIOD_NOT_FOUND",
  "message": "Subscription period not found or not active"
}
```

> 404 Response (Subscription Not Active)

```json
{
  "success": false,
  "error_code": "SUBSCRIPTION_NOT_ACTIVE",
  "message": "Parent subscription is not active"
}
```

> 404 Response (Organization Not Found)

```json
{
  "success": false,
  "error_code": "ORG_NOT_FOUND",
  "message": "Organization not found"
}
```

> 403 Response (Not Authorized)

```json
{
  "success": false,
  "error_code": "NOT_AUTHORIZED",
  "message": "User does not have permission to buy subscriptions"
}
```

> 409 Response (Already Active)

```json
{
  "success": false,
  "error_code": "SUBSCRIPTION_ALREADY_ACTIVE",
  "message": "You already have an active Professional Plan subscription"
}
```

> 409 Response (Payment In Progress)

```json
{
  "success": false,
  "error_code": "PAYMENT_IN_PROGRESS",
  "message": "A payment is already in progress. Please complete or cancel the current payment before starting a new one."
}
```

> 500 Response

```json
{
  "success": false,
  "error_code": "INTERNAL_ERROR",
  "message": "Failed to process subscription purchase"
}
```

#### Responses <a href="#post_subscription_buy-responses" id="post_subscription_buy-responses"></a>

| Status | Meaning                                                                                             | Description                                       | Schema |
| ------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------ |
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                                             | Subscription purchase initiated or completed      | Inline |
| 400    | [Bad Request](https://www.rfc-editor.org/rfc/rfc9110.html#name-400-bad-request)                     | Invalid request or configuration                  | Inline |
| 403    | [Forbidden](https://www.rfc-editor.org/rfc/rfc9110.html#name-403-forbidden)                         | User lacks permission for billing operations      | Inline |
| 404    | [Not Found](https://www.rfc-editor.org/rfc/rfc9110.html#name-404-not-found)                         | User, organization, or subscription not found     | Inline |
| 409    | [Conflict](https://www.rfc-editor.org/rfc/rfc9110.html#name-409-conflict)                           | Active subscription exists or payment in progress | Inline |
| 500    | [Internal Server Error](https://www.rfc-editor.org/rfc/rfc9110.html#name-500-internal-server-error) | Server error                                      | Inline |

#### Response Schema <a href="#post_subscription_buy-responseschema" id="post_subscription_buy-responseschema"></a>

Status Code **200**

| Name                   | Type    | Required | Restrictions | Description                                                           |
| ---------------------- | ------- | -------- | ------------ | --------------------------------------------------------------------- |
| » success              | boolean | false    | none         | Indicates if the request was successful                               |
| » checkoutUrl          | string  | false    | none         | Stripe hosted checkout URL for redirect (null for free subscriptions) |
| » sessionId            | string  | false    | none         | Stripe checkout session identifier or free payment ID                 |
| » isSubscriptionChange | boolean | false    | none         | Indicates if this is changing from an existing subscription           |
| » previousSubscription | object  | false    | none         | Details of the previous subscription (null if not a change)           |
| »» id                  | string  | false    | none         | Previous subscription identifier                                      |
| »» name                | string  | false    | none         | Previous subscription name                                            |
| » isFreeSubscription   | boolean | false    | none         | Indicates if this is a free subscription (no payment required)        |

Status Code **400**

| Name          | Type    | Required | Restrictions | Description                                                                                 |
| ------------- | ------- | -------- | ------------ | ------------------------------------------------------------------------------------------- |
| » success     | boolean | false    | none         | Will be false for error responses                                                           |
| » error\_code | string  | false    | none         | Machine-readable error code (NO\_ORGANIZATION, STRIPE\_ID\_MISSING, STRIPE\_PRICE\_INVALID) |
| » message     | string  | false    | none         | Human-readable error message                                                                |

Status Code **403**

| Name          | Type    | Required | Restrictions | Description                                   |
| ------------- | ------- | -------- | ------------ | --------------------------------------------- |
| » success     | boolean | false    | none         | Will be false for error responses             |
| » error\_code | string  | false    | none         | Machine-readable error code (NOT\_AUTHORIZED) |
| » message     | string  | false    | none         | Human-readable error message                  |

Status Code **404**

| Name          | Type    | Required | Restrictions | Description                                                                                                                  |
| ------------- | ------- | -------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| » success     | boolean | false    | none         | Will be false for error responses                                                                                            |
| » error\_code | string  | false    | none         | Machine-readable error code (USER\_NOT\_FOUND, SUBSCRIPTION\_PERIOD\_NOT\_FOUND, SUBSCRIPTION\_NOT\_ACTIVE, ORG\_NOT\_FOUND) |
| » message     | string  | false    | none         | Human-readable error message                                                                                                 |

Status Code **409**

| Name          | Type    | Required | Restrictions | Description                                                                        |
| ------------- | ------- | -------- | ------------ | ---------------------------------------------------------------------------------- |
| » success     | boolean | false    | none         | Will be false for error responses                                                  |
| » error\_code | string  | false    | none         | Machine-readable error code (SUBSCRIPTION\_ALREADY\_ACTIVE, PAYMENT\_IN\_PROGRESS) |
| » message     | string  | false    | none         | Human-readable error message                                                       |

Status Code **500**

| Name          | Type    | Required | Restrictions | Description                       |
| ------------- | ------- | -------- | ------------ | --------------------------------- |
| » success     | boolean | false    | none         | Will be false for error responses |
| » error\_code | string  | false    | none         | Machine-readable error code       |
| » message     | string  | false    | none         | Human-readable error message      |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flashback.tech/support-reference/platform-api-reference/subscriptions/post_subscription_buy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
