Ответ на запросы к серверному API: 400: Bad request
billing_issue_detected_at_date_comparison_error
Проблема с оплатой возникает при неудачной попытке продления подписки, поэтому она всегда происходит после даты транзакции (purchased_at).
Убедитесь, что дата проблемы с оплатой (billing_issue_detected_at) позже даты транзакции (purchased_at).
Тело ответа
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда billing_issue_detected_at_date_comparison_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Пользователь не может купить подписку, которая уже истекла. Поэтому дата expires_at (когда истекает подписка) всегда должна быть позже даты purchased_at (когда произошла транзакция).
Чтобы исправить ошибку, проверьте эти даты и убедитесь, что expires_at позже purchased_at.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда expires_date_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Запрос завершился ошибкой, потому что параметр is_family_shared установлен в true, то есть уровень доступа предоставляется члену семьи бесплатно. При этом параметр value объекта Price не равен нулю.
Если is_family_shared должен быть true, убедитесь, что параметр value объекта Price установлен в 0.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Короткое название ошибки. Всегда: family_share_price_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
Профиль не найден
{
"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
Запрос завершился ошибкой, поскольку параметр offer_type имеет значение free_trial, но параметр value объекта Price не равен нулю.
Ещё одна возможная причина: параметр offer_id был указан, но оставлен null, хотя он не может быть null. В этом случае либо укажите значение для offer_id, либо удалите параметр полностью.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда: free_trial_price_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
Профиль не найден
{
"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
Льготный период — это дополнительное время, которое вы можете дать пользователям для продления подписки, если они не успели это сделать вовремя, например из-за проблем с оплатой картой. Это позволяет сохранить их настройки, пока они разбираются с ситуацией. Предоставлять льготный период необязательно.
Если льготный период предусмотрен, дата его окончания (grace_period_expires_at) должна быть позже даты окончания подписки (expires_at). В противном случае время окончания льготного периода совпадёт со временем окончания подписки. В любом случае льготный период не может истекать раньше, чем подписка.
Чтобы исправить ошибку, убедитесь, что дата окончания льготного периода (grace_period_expires_at) позже даты окончания подписки (expires_at).
Body
| Parameter | Type | Description |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда grace_period_expires_date_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Начало льготного периода считается проблемой с выставлением счёта. Поэтому если льготный период начался (на это указывает заполненный параметр grace_period_expires_at), его дата начала должна быть записана в параметр billing_issue_detected_at.
Чтобы исправить ошибку, либо укажите дату начала льготного периода в billing_issue_detected_at, либо, если льготный период ещё не начался, удалите параметр grace_period_expires_at.
Body
| Parameter | Type | Description |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда grace_period_billing_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Запрос завершился ошибкой, потому что параметр offer_category имеет значение, отличное от introductory или offer_type, но при этом не содержит offer_id. В таком случае нужно либо указать offer_id, либо убрать offer_category или offer_type из запроса.
Другая возможная причина: параметр offer_id добавлен, но задан как null, хотя он не может быть null. В этом случае нужно либо указать значение для offer_id, либо полностью убрать этот параметр.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Короткое название ошибки. Возможное значение: missing_offer_id. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
Профиль не найден
{
"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
Запрос завершился ошибкой, так как к разовой покупке был привязан пробный период. В отличие от подписок, разовые покупки не поддерживают пробный период. Чтобы исправить это, проверьте значение offer_type в объекте Offer внутри объекта One-Time Purchase. Значение offer_type не может быть free_trial. Измените значение поля offer_type или используйте объект Subscription вместо One-Time Purchase.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда one_time_purchase_trial_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Для продлённых подписок формируется цепочка транзакций. Первая транзакция в этой цепочке называется исходной и связывает все последующие. Каждое продление является расширением этой исходной транзакции. Если транзакция является первой покупкой, она сама выступает своей исходной транзакцией.
Временная метка originally_purchased_at фиксирует момент исходной покупки, а purchased_at — момент текущей транзакции. Поэтому purchased_at никогда не может быть раньше originally_purchased_at; в крайнем случае они совпадают — для самой первой транзакции.
Запрос завершился с ошибкой, потому что originally_purchased_at указан позже, чем purchased_at. Убедитесь, что это значение меньше или равно purchased_at.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда originally_purchased_date_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Запрос завершился ошибкой, потому что указанный в запросе уровень доступа не найден. Проверьте, нет ли опечаток в access_level_id, и убедитесь, что он соответствует нужному приложению.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Возможное значение: paid_access_level_does_not_exist. |
| status_code | Integer | HTTP-статус. Всегда 404. |
Пример ответа
Уровень доступа не найден.
{
"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
Запрос завершился ошибкой, потому что профиль из заголовка запроса не найден. Проверьте, нет ли опечаток в profile_id или customer_user_id, указанных в заголовке запроса, и убедитесь, что они относятся к правильному приложению.
Тело
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Возможное значение: profile_does_not_exist. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
Профиль не найден
{
"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
Запрос завершился с ошибкой, потому что профиль в запросе не соответствует указанному уровню доступа. Убедитесь, что ID профиля в заголовке и ID уровня доступа в теле запроса указаны верно, и проверьте наличие опечаток.
Тело ответа
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда profile_paid_access_level_does_not_exist. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Запрос завершился с ошибкой, поскольку дата покупки (purchased_at) оказалась раньше или равна дате возврата (refunded_at). Возврат всегда происходит после покупки, так как является её отменой.
Чтобы исправить ошибку, проверьте параметры purchased_at и refunded_at и убедитесь, что дата возврата позже даты покупки.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда refund_date_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"errors": [
{
"source": "refunded_at",
"errors": [
"refunded_at must be later than purchased_at."
]
}
],
"error_code": "refund_date_error",
"status_code": 400
}
refund_fields_error
Запрос завершился ошибкой, поскольку в нём указан cancellation_reason без даты refunded_at, либо refunded_at без cancellation_reason.
При установке возврата средств необходимо указать и дату, и причину возврата.
Тело ответа
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда refund_fields_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Продление — это пролонгация подписки. Пользователь может отменить автопродление, а затем снова включить его. Время обоих этих действий сохраняется в параметре renew_status_changed_at и не может быть раньше самой транзакции.
Чтобы исправить ошибку, убедитесь, что renew_status_changed_at позже времени транзакции (purchased_at).
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Короткое название ошибки. Всегда originally_purchased_date_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Запрос завершился ошибкой, потому что указанный в запросе параметр revoke_at позже текущего значения expires_at для данного уровня доступа. Если вы хотите продлить уровень доступа, используйте запрос Предоставление уровня доступа.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Короткое название ошибки. Всегда revocation_date_more_than_expiration_date. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
В случае продлевающихся подписок формируется цепочка транзакций. Исходная транзакция — это самая первая транзакция в этой цепочке, и все остальные транзакции связаны через неё. Остальные транзакции в цепочке являются продлениями. Если транзакция является самой первой покупкой в цепочке подписок, она может быть своей собственной исходной транзакцией.
Другой случай — разовая покупка. Она никогда не создаёт цепочек, так как не может иметь продлений. Для неё store_transaction_id всегда совпадает с store_original_transaction_id.
Ваш запрос завершился с ошибкой, потому что значение store_transaction_id объекта Разовая покупка отличается от его store_original_transaction_id. Чтобы исправить это, либо сделайте их одинаковыми, либо измените объект — используйте Подписку вместо Разовой покупки.
Тело
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда store_transaction_id_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"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
Запрос завершился ошибкой, поскольку указанная дата отзыва находится в прошлом. Установите revoke_at на будущую дату или передайте null, чтобы немедленно отозвать доступ.
Body
| Параметр | Тип | Описание |
|---|---|---|
| errors | Object |
|
| error_code | String | Краткое название ошибки. Всегда value_error. |
| status_code | Integer | HTTP-статус. Всегда 400. |
Пример ответа
{
"errors": [
{
"source": null,
"errors": [
"Must be greater than the current time or null"
]
}
],
"error_code": "value_error",
"status_code": 400
}