Revoke access level with server-side API
Removes an access level from an end user of your app in Adapty.
Method and endpoint
POST https://api.adapty.io/api/v2/server-side-api/purchase/profile/revoke/access-level/
Example request
- cURL
- Python
- JavaScript
curl --location 'https://api.adapty.io/api/v2/server-side-api/purchase/profile/revoke/access-level/' \
--header 'Authorization: Api-Key <YOUR_SECRET_API_KEY>' \
--header 'adapty-customer-user-id: <YOUR_CUSTOMER_USER_ID>' \
--header 'Content-Type: application/json' \
--data '{
"access_level_id": "premium",
"revoke_at": "2024-10-12T09:42:50.000000+0000"
}'
import requests
url = "https://api.adapty.io/api/v2/server-side-api/purchase/profile/revoke/access-level/"
payload = {
"access_level_id": "premium",
"revoke_at": "2024-10-12T09:42:50.000000+0000"
}
headers = {
"Authorization": "Api-Key <YOUR_SECRET_API_KEY>",
"adapty-customer-user-id": "<YOUR_CUSTOMER_USER_ID>",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, json=payload)
print(response.text)
const myHeaders = new Headers();
myHeaders.append("Authorization", "Api-Key <YOUR_SECRET_API_KEY>");
myHeaders.append("adapty-customer-user-id", "<YOUR_CUSTOMER_USER_ID>");
myHeaders.append("Content-Type", "application/json");
const raw = JSON.stringify({
"access_level_id": "premium",
"revoke_at": "2024-10-12T09:42:50.000000+0000"
});
const requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow"
};
fetch("https://api.adapty.io/api/v2/server-side-api/purchase/profile/revoke/access-level/", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
Placeholders:
<YOUR_CUSTOMER_USER_ID>
: The unique ID of the customer in your system.<YOUR_SECRET_API_KEY>
: Your secret API key for authorization.
Parameters
Parameter | Type | Required in request | Nullable in request | Description |
---|---|---|---|---|
access_level_id | String | ➕ | ➖ | Paid access level ID configured by you in the Access Levels page of the Adapty Dashboard. |
revoke_at | ISO 8601 date | ➖ | ➕ | Specifies when the access level will expire. To revoke access immediately, either omit this field or set it to null . The default value is null . |
Successful response: 200: OK
The request is successful. The response body contains the data
field, which encapsulates the user's profile and associated information.
Parameter | Type | Nullable | Description |
---|---|---|---|
data | Object | ➖ | Contains the Profile object with user details and metadata. |
data object structure
The data
field is the primary container for the user profile. It includes several fields:
Parameter | Type | Nullable | Description |
---|---|---|---|
app_id | String | ➖ | The internal ID of your app. You can see in the the Adapty Dashboard: App Settings -> General tab. |
profile_id | UUID | ➖ | Adapty profile ID. You can see it in the Adapty ID field on the Adapty Dashboard -> Profiles -> specific profile page. |
customer_user_id | String | ➕ | The ID of your user in your system. You can see it in the Customer user ID field on the Adapty Dashboard -> Profiles -> specific profile page. It will work only if you identify the users in your mobile app code via Adapty SDK. |
total_revenue_usd | Float | ➖ | A float value representing the total revenue in USD earned in the profile. |
segment_hash | String | ➖ | Internal parameter. |
timestamp | Integer | ➖ | Response time in milliseconds, needs for resolve a race condition. |
custom_attributes | Dictionary | ➖ | A maximum of 30 custom attributes to the profile are allowed to be set. If you provide the Key: The key must be a string with no more than 30 characters. Only letters, numbers, dashes, points, and underscores allowed Value: The attribute value must be no more than 30 characters. Only strings and floats are allowed as values, booleans will be converted to floats. Send an empty value or null to delete the attribute. |
access_levels | Dictionary | ➕ | Profile Paid Access Level objects. Dictionary where the keys are paid access level identifiers configured by a developer in the Adapty Dashboard. Values are Access level objects. Can be null if the customer has no access levels. |
subscriptions | Dictionary | ➕ | Dictionary where the keys are vendor product IDs. Values are Subscription objects. Can be null if the customer has no subscriptions. |
non_subscriptions | Dictionary | ➕ | Dictionary where the keys are vendor product ids. Values are an array of Non-Subscription objects. Can be null if the customer has no purchases. |
Successful response example
{
"data": {
"app_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"profile_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"customer_user_id": "8612ED7C-3477-466D-93AE-1854B8E5FDD5",
"total_revenue_usd": 109.88999999999999,
"segment_hash": "string",
"timestamp": 0,
"custom_attributes": [
{
"key": "string",
"value": "string"
}
],
"access_levels": [
{
"access_level_id": "premium",
"store": "app_store",
"store_product_id": "weekly_8.99",
"store_base_plan_id": "",
"store_transaction_id": "530001802720333",
"store_original_transaction_id": "530001724306018",
"offer": {
"category": "introductory",
"type": "free_trial",
"id": "offer12"
},
"environment": "Production",
"starts_at": "2022-10-12T09:42:50.000000+0000",
"purchased_at": "2022-10-12T09:42:50.000000+0000",
"originally_purchased_at": "2021-10-12T09:42:50.000000+0000",
"expires_at": "2022-10-12T09:42:50.000000+0000",
"renewal_cancelled_at": "2022-10-12T09:42:50.000000+0000",
"billing_issue_detected_at": "2022-10-12T09:42:50.000000+0000",
"is_in_grace_period": true,
"cancellation_reason": "voluntarily_cancelled"
}
],
"subscriptions": [
{
"store": "app_store",
"store_product_id": "weekly_8.99",
"store_base_plan_id": "",
"store_transaction_id": "530001802720333",
"store_original_transaction_id": "530001724306018",
"offer": {
"offer_category": "introductory",
"offer_type": "free_trial",
"offer_id": "offer12"
},
"environment": "Production",
"purchased_at": "2022-10-12T09:42:50.000000+0000",
"originally_purchased_at": "2021-10-12T09:42:50.000000+0000",
"expires_at": "2022-10-12T09:42:50.000000+0000",
"renewal_cancelled_at": "2022-10-12T09:42:50.000000+0000",
"billing_issue_detected_at": "2022-10-12T09:42:50.000000+0000",
"is_in_grace_period": true,
"cancellation_reason": "voluntarily_cancelled"
}
],
"non_subscriptions": [
{
"purchase_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"store": "app_store",
"store_product_id": "weekly_8.99",
"store_base_plan_id": "",
"store_transaction_id": "530001724306018",
"store_original_transaction_id": "530001724306018",
"purchased_at": "2022-10-12T09:42:50.000000+0000",
"environment": "Production",
"is_refund": true,
"is_consumable": true
}
]
}
}
Errors
400: Bad request
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 |
|
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.
{
"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
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 |
|
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
{
"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 |
|
error_code | String | Short error name. Always profile_paid_access_level_does_not_exist . |
status_code | Integer | HTTP status. Always 400 . |
Response example
{
"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
}
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 request.
Body
Parameter | Type | Description |
---|---|---|
errors | Object |
|
error_code | String | Short error name. Always revocation_date_more_than_expiration_date . |
status_code | Integer | HTTP status. Always 400 . |
Response example
{
"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
}
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 |
|
error_code | String | Short error name. Always value_error . |
status_code | Integer | HTTP status. Always 400 . |
Response example
{
"errors": [
{
"source": null,
"errors": [
"Must be greater than the current time or null"
]
}
],
"error_code": "value_error",
"status_code": 400
}
401: Unauthorized
The request failed due to missing or incorrect authorization. Check the Authorization page, paying close attention to the Authorization header.
The request also failed because the specified profile wasn’t found.
Body
Parameter | Type | Description |
---|---|---|
errors | Object |
|
error_code | String | Short error name. Always not_authenticated . |
status_code | Integer | HTTP status. Always 401. |
Response example
{
"errors": [
{
"source": "non_field_errors",
"errors": [
"Authentication credentials were not provided."
]
}
],
"error_code": "not_authenticated",
"status_code": 401
}
404: Not found
The request failed because the specified profile wasn’t found. Double-check the customer_user_id
or profile_id
for any typos.
Body
Parameter | Type | Description |
---|---|---|
errors | Object |
|
error_code | String | Short error name. Always profile_does_not_exist . |
status_code | Integer | HTTP status. Always 404 . |
Response example
{
"errors": [
{
"source": null,
"errors": [
"Profile not found"
]
}
],
"error_code": "profile_does_not_exist",
"status_code": 404
}
See also: