---
title: "Response to server-side API requests:  400: Bad request"
description: ""
---

### billing_issue_detected_at_date_comparison_error

A billing issue happens when there’s a problem during a subscription renewal attempt, so it always occurs after the transaction date (`purchased_at`).

To resolve this, make sure the billing issue date (`billing_issue_detected_at`) is later than the transaction date (`purchased_at`).

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `billing_issue_detected_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `billing_issue_detected_at_date_comparison_error`. |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "billing_issue_detected_at",
      "errors": [
        "billing_issue_detected_at must be later than purchased_at."
      ]
    }
  ],
  "error_code": "billing_issue_detected_at_date_comparison_error",
  "status_code": 400
}
```

---

### expires_date_error

A user can’t buy a subscription that has already expired. So, the `expires_at` date (when the subscription expires) should always be later than the `purchased_at` date (when the transaction occurred).

To fix this, check these dates and ensure that `expires_at` is after `purchased_at`.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `expires_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `expires_date_error`.               |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "expires_at",
      "errors": [
        "expires_at must be later than purchased_at."
      ]
    }
  ],
  "error_code": "expires_date_error",
  "status_code": 400
}
```

---

### family_share_price_error

The request failed because the `is_family_shared` parameter is set to `true`, meaning the access level is shared with a family member for free. However, the `value` parameter of the [Price](server-side-api-objects#price) object isn’t set to zero.

If `is_family_shared` should be `true`, make sure to set the `value` parameter of the [Price](server-side-api-objects#price) object to `0`.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `is_family_shared`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always: `family_share_price_error`.        |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

The profile is not found

```json showLineNumbers
{
  "errors": [
    {
      "source": "is_family_shared",
      "errors": [
        "If is_family_shared is true, price.value must be 0."
      ]
    }
  ],
  "error_code": "family_share_price_error",
  "status_code": 400
}
```

---

### free_trial_price_error

The request failed because the `offer_type` parameter is set to `free_trial`, but the `value` parameter of the [Price](server-side-api-objects#price) object isn’t set to zero.

Another possible reason is that the `offer_id` parameter was included but left `null`, even though it can’t be null. In this case, either provide a value for `offer_id` or remove the parameter entirely.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `offer.type`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always: `free_trial_price_error`.          |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

The profile is not found

```json showLineNumbers
{
  "errors": [
    {
      "source": "offer_type",
      "errors": [
        "If offer_type is 'free_trial', price.value must be 0."
      ]
    }
  ],
  "error_code": "free_trial_price_error",
  "status_code": 400
}
```

---

### grace_period_expires_date_error

A grace period is extra time you can give customers to extend their subscription if they couldn’t renew it on time—for instance, if their credit card didn’t go through. This helps keep their settings intact while they resolve any issues. Offering a grace period is optional.

If you do offer a grace period, the expiration date for it (`grace_period_expires_at`) should be later than the subscription expiration date (`expires_at`). If not, the grace period expiration time will match the subscription expiration time. In any case, the grace period expiration can’t be earlier than the subscription expiration.

To fix this, make sure the grace period expiration date (`grace_period_expires_at`) is later than the subscription expiration date (`expires_at`).

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `grace_period_expires_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `grace_period_expires_date_error`.  |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "grace_period_expires_at",
      "errors": [
        "grace_period_expires_at must be later or equal to expires_at."
      ]
    }
  ],
  "error_code": "grace_period_expires_date_error",
  "status_code": 400
}
```

---

### grace_period_billing_error

The start of a grace period counts as a billing issue. So, if the grace period has started (indicated by the `grace_period_expires_at` parameter being filled in), its start date should be recorded in the `billing_issue_detected_at` parameter.

To fix this, either set the start of the grace period in `billing_issue_detected_at` or, if the grace period hasn’t started yet, remove the `grace_period_expires_at` parameter.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `grace_period_billing_error`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `grace_period_billing_error`.       |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "grace_period_billing_error",
      "errors": [
        "If grace_period_expires_at is specified, billing_issue_detected_at must also be specified."
      ]
    }
  ],
  "error_code": "grace_period_billing_error",
  "status_code": 400
}
```

---

### missing_offer_id

The request failed because the `offer_category` parameter has a value other than `introductory` or `offer_type` but doesn’t include an `offer_id`. In this case, either provide an `offer_id` or remove the `offer_category` or `offer_type` from the request.

Another possible reason is that the `offer_id` parameter was added but left as `null`, even though it can’t be null. If that’s the case, either add a value for `offer_id` or remove the parameter entirely.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `offer.category`</li><li> **errors**: A description of the error. </li></ul> |
| error_code  | String  | Short error name. Possible value: `missing_offer_id`.        |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

The profile is not found

```json showLineNumbers
{
  "errors": [
    {
      "source": "offer_category",
      "errors": [
        "offer_id must be specified for all offer types except 'introductory'."
      ]
    }
  ],
  "error_code": "missing_offer_id",
  "status_code": 400
}
```

---

### one_time_purchase_trial_error

The request failed because a trial was provided with a one-time purchase. Unlike subscriptions, one-time purchases can’t have a trial. To fix this, check the `offer_type` in the [Offer](server-side-api-objects#offer) object within the [One-Time Purchase](server-side-api-objects#one-time-purchase) object. The value for `offer_type` can’t be `free_trial`. Either change the `offer_type` field value or switch to using the [Subscription](server-side-api-objects#subscription) object instead of One-Time Purchase.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always offer.type</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `one_time_purchase_trial_error`.    |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "offer.type",
      "errors": [
        "One-time purchase cannot have a trial."
      ]
    }
  ],
  "error_code": "one_time_purchase_trial_error",
  "status_code": 400
}
```

---

### originally_purchased_date_error

For prolonged subscriptions, a chain of transactions is created. The original transaction is the first one in this chain, and it links all the following transactions. Each renewal is simply an extension of this original. If the transaction is the first purchase, it serves as its original transaction.

The `originally_purchased_at` timestamp marks the time of the original purchase, while `purchased_at` is the time of the current transaction. Because of this, `purchased_at` can never be earlier than `originally_purchased_at`; at most, they can be the same for the very first transaction.

The request failed because `originally_purchased_at` is set to a later date than `purchased_at`. Make sure it’s earlier or equal to `purchased_at`.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `originally_purchased_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `originally_purchased_date_error`.  |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "originally_purchased_at",
      "errors": [
        "originally_purchased_at must be earlier than or equal to purchased_at."
      ]
    }
  ],
  "error_code": "originally_purchased_date_error",
  "status_code": 400
}
```

---

### paid_access_level_does_not_exist

The request failed because the access level in the request couldn’t be found. Double-check that there are no typos in the `access_level_id` and that it matches the correct app.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `non_field_errors`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Possible value: `paid_access_level_does_not_exist`. |
| status_code | Integer | HTTP status. Always `404`.                                   |

#### Response example

The access level was not found.

```json showLineNumbers
{
  "errors": [
    {
      "source": "non_field_errors",
      "errors": [
        "Paid access level `premium` does not exist"
      ]
    }
  ],
  "error_code": "paid_access_level_does_not_exist",
  "status_code": 400
}
```

---

### profile_does_not_exist

<p> </p>

The request failed because the profile in the request header wasn’t found. Double-check that there are no typos in the `profile_id` or `customer_user_id` you entered in the request header, and make sure it’s for the correct app.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `non_field_errors`</li><li> **errors**: A description of the error. </li></ul> |
| error_code  | String  | Short error name. Possible value: `profile_does_not_exist`.  |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

The profile is not found

```json showLineNumbers
{
  "errors": [
    {
      "source": "non_field_errors",
      "errors": [
        "Profile not found"
      ]
    }
  ],
  "error_code": "profile_does_not_exist",
  "status_code": 400
}
``` 

---

### profile_paid_access_level_does_not_exist

The request failed because the profile in the request doesn’t match the specified access level. Double-check that the profile ID in the header and the access level ID in the body are correct, and make sure there are no typos.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `non_field_errors`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `profile_paid_access_level_does_not_exist`. |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "non_field_errors",
      "errors": [
        "Profile `478b2e7f-d557-4b8b-9c5f-cbd46fc2dee2` has no `premium` access level"
      ]
    }
  ],
  "error_code": "profile_paid_access_level_does_not_exist",
  "status_code": 400
}
```

---

### refund_date_error

The request failed because the purchase date (`purchased_at`) is earlier than or equal to the refund date (`refunded_at`). A refund always happens after a purchase, as it reverses the transaction.

To fix this, check the `purchased_at` and `refunded_at` parameters and make sure the refund date is later than the purchase date.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `refunded_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `refund_date_error`.                |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "refunded_at",
      "errors": [
        "refunded_at must be later than purchased_at."
      ]
    }
  ],
  "error_code": "refund_date_error",
  "status_code": 400
}
```

---

### refund_fields_error

The request failed because it either includes `cancellation_reason` without a `refunded_at` date, or it has `refunded_at` without a `cancellation_reason`.

When a refund is set, both the refund date and reason need to be specified.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `refunded_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `refund_fields_error`.              |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "refunded_at",
      "errors": [
        "refunded_at and cancellation_reason=refund must be specified together."
      ]
    }
  ],
  "error_code": "refund_fields_error",
  "status_code": 400
}
```

---

### renew_status_changed_date_error

Renewal is a prolongation of a subscription. The user can cancel the subscription prolongation and then again prolong it. The time of both these actions is stored in the `renew_status_changed_at` parameter. And it can never happen earlier than the transaction itself.

To fix the issue, make sure the `renew_status_changed_at` is later than the time of the transaction (`purchased_at`).

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `originally_purchased_at`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `originally_purchased_date_error`.  |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "renew_status_changed_at",
      "errors": [
        "renew_status_changed_at must be later than purchased_at."
      ]
    }
  ],
  "error_code": "renew_status_changed_date_error",
  "status_code": 400
}
```

---

### revocation_date_more_than_expiration_date

The request failed because the `revoke_at` you defined in the request is later than the current access level `expires_at` parameter. If you want to prolong the access level, use the [Grant access level](ss-grant-access-level) request.

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `non_field_errors`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `revocation_date_more_than_expiration_date`. |
| status_code | Integer | HTTP status. Always `400`.                                   |

#### Response example

```json showLineNumbers
  {
  "errors": [
    {
      "source": "revoke_at",
      "errors": [
        "Revocation date (2029-08-29 09:33:42+00:00) is more than current expiration date (2028-08-29 09:33:42+00:00)"
      ]
    }
  ],
  "error_code": "revocation_date_more_than_expiration_date",
  "status_code": 400
}
```

---

### store_transaction_id_error

In the case of prolonged subscriptions, a chain of subscriptions is generated. The original transaction is the very first transaction in this chain and the chain is linked by it. Other transactions in the chain are prolongations. If the transaction is the very first purchase in the subscription chain, it can be its own original transaction.

Another case is a one-time purchase. It never creates chains as it cannot have prolongations. For it, the `store_transaction_id` is always the same as the `store_original_transaction_id`.

Your request failed because the `store_transaction_id` value for the [One-Time Purchase](server-side-api-objects#one-time-purchase) object differs from its `store_original_transaction_id` . To fix the issue, either make them the same, or change the object - use [Subscription](server-side-api-objects#subscription) instead of the [One-Time Purchase](server-side-api-objects#one-time-purchase).

#### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `store_transaction_id`</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `store_transaction_id_error`.       |
| status_code | Integer | HTTP status. Always `400.`                                   |

#### Response example

```json showLineNumbers
{
  "errors": [
    {
      "source": "store_transaction_id",
      "errors": [
        "store_transaction_id must be equal to store_original_transaction_id for purchase."
      ]
    }
  ],
  "error_code": "store_transaction_id_error",
  "status_code": 400
}
```

#### value_error

The request failed because the specified revocation date is in the past. Set `revoke_at` to a future date or `null` to revoke access immediately.

##### Body

| Parameter   | Type    | Description                                                  |
| ----------- | ------- | ------------------------------------------------------------ |
| errors      | Object  | <ul><li> **source**: (string) Always `revoke_at`.</li><li> **errors**: A description of the error.</li></ul> |
| error_code  | String  | Short error name. Always `value_error`.                      |
| status_code | Integer | HTTP status. Always `400`.                                   |

##### Response example

```json showLineNumbers
{
    "errors": [
        {
            "source": null,
            "errors": [
                "Must be greater than the current time or null"
            ]
        }
    ],
    "error_code": "value_error",
    "status_code": 400
}
```