API specs
Learn how to get and manipulate with user's data, including subscription status, from your server
Base URL: https://api.adapty.io/api/v1/sdk
Authorization
Each API request must be signed with the Secret Key.
When calling API:
- You must set Authorization header with value "Api-Key {secret_token}" (without quotes) to each request, for example
Api-Key secret_live_BEHrYLTr.ce5zuDEWz06lFRNiaJC8mrLtL8fUwswD
- Use JSON payload in request body for POST and PATCH requests
- All request must set header Content-Type: application/json
Requests
Prolong/grant a subscription for a user
POST: /profiles/{profile_id_or_customer_user_id}/paid-access-levels/{access_level}/grant/
Path params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
profile_id_or_customer_user_id | str | ✅ | ❌ | Adapty profile ID or developer's internal ID |
access_level | str | ✅ | ❌ | ID (slug) of a paid access level. Find it in Adapty Dashboard |
Request params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
expires_at | ISO 8601 date | ✅* see below | ❌ | Subscription deadline |
duration_days | int | ✅* see below | ❌ | Additional days to a current subscription** |
is_lifetime | bool | ✅* see below | ❌ | If set true, then a user will forever have a paid access level forever |
starts_at | ISO 8601 date | ❌ | ❌ | If the start time of the action is in the future, then you can transfer it. If the start time and the period are indicated, the period will be counted from the indicated time |
vendor_product_id | str | ❌ | ❌ | Vendor product ID which initiates subscription prolongation. The default value is adapty_promotion |
vendor_transaction_id | str | ❌ | ❌ | Transaction ID in a vendor environment |
store | str | ❌ | ❌ | A store where users purchased a product, such as app_store and play_store, can be custom. Default is adapty |
introductory_offer_type | str | ❌ | ❌ | A type of introduction offer. Available values are free_trial, pay_as_you_go, and pay_up_front. |
price | float | ❌ | ❌ | Price of the subscription/purchase to save in transaction. |
proceeds | float | ❌ | ❌ | Proceeds (price that is reduced due to stores' fee) of the subscription/purchase to save in transaction. |
price_locale | str | ❌ | ❌ | The currency of the transaction in the three-letter format. Default is USD. |
is_sandbox | bool | ❌ | ❌ | Boolean indicating whether the product was purchased in the sandbox or production environment. |
Paid access level
There are three ways to grant users a subscription. So, at least one of is_lifetime, expires_at, or duration_days must be set. If more than one param is set, then is_lifetime=true has a maximum priority, then expires_at, and lastly duration_days.
As all payment processing is done by Apple/Google, Adapty can not control or affect it. So, when using duration_days to a current subscription, remember that a user still will be charged on a needed day. For example, the user has a monthly subscription and the next charge date will be 5th or April. You grant a user additional 7 days, but the user still is charged on the 5th of April!. It's best using duration_days with never subscribed users or churned. In that case reference day is a day of granting.
Transaction
If all vendor_product_id, vendor_transaction_id, and store are specified, Adapty creates and saves transaction entry so this grant is accounted in Charts (Revenue, MRR, Subscriptions) unless the transaction with these parameters already exists (e.g. it was generated by iOS purchase). If price is specified, it is associated with this transaction.
Currently, this type of transaction does not generate any profile events and does not affect users' subscription status.
Also, be aware that these transactions affect billing since they are counted towards MTR.
Sample request:
{
"starts_at": "2020-01-15T15:10:36.517975+0000",
"expires_at": "2020-02-15T15:10:36.517975+0000",
"vendor_product_id": "basic_subscription_1_month",
"vendor_transaction_id": "123456789",
"store": "app_store",
"introductory_offer_type": null
}
Sample response:
{
"data": {
"app_id": "ff90dd2e-e7f2-454b-9d86-071036a284fe",
"profile_id": "77112400-89f1-4465-b9c9-5437e58c6688",
"customer_user_id": "[email protected]",
"paid_access_levels": {
"premium": {
"id": "premium",
"is_active": true,
"is_lifetime": false,
"expires_at": "2023-03-29T15:30:34.000000+0000",
"starts_at": null,
"will_renew": false,
"vendor_product_id": "adapty_promotion",
"store": "adapty",
"activated_at": "2020-03-26T16:24:19.497674+0000",
"renewed_at": "2020-03-26T16:24:19.497674+0000",
"unsubscribed_at": null,
"billing_issue_detected_at": null,
"is_in_grace_period": false,
"active_introductory_offer_type": "free_trial",
"active_promotional_offer_type": null,
"active_promotional_offer_id": null,
"cancellation_reason": null
}
},
"subscriptions": {
"com.adapty.premium.monthly": {
"is_active": false,
"is_lifetime": false,
"expires_at": "2020-02-21T16:30:34.000000+0000",
"starts_at": null,
"will_renew": false,
"vendor_product_id": "com.adapty.premium.monthly",
"vendor_transaction_id": "1000000630116569",
"vendor_original_transaction_id": "1000000625263604",
"store": "app_store",
"activated_at": "2020-02-10T19:14:02.000000+0000",
"renewed_at": "2020-02-21T16:25:34.000000+0000",
"unsubscribed_at": "2020-02-21T16:30:34.000000+0000",
"billing_issue_detected_at": "2020-02-21T16:30:34.000000+0000",
"is_in_grace_period": false,
"active_introductory_offer_type": null,
"active_promotional_offer_type": null,
"active_promotional_offer_id": null,
"cancellation_reason": "voluntarily_cancelled",
"is_sandbox": true
},
"com.adapty.premium.weekly": {
"is_active": false,
"is_lifetime": false,
"expires_at": "2020-02-10T19:32:00.000000+0000",
"starts_at": null,
"will_renew": true,
"vendor_product_id": "com.adapty.premium.weekly",
"vendor_transaction_id": "1000000625265713",
"vendor_original_transaction_id": "1000000625263604",
"store": "app_store",
"activated_at": "2020-02-10T19:14:02.000000+0000",
"renewed_at": "2020-02-10T19:29:00.000000+0000",
"unsubscribed_at": null,
"billing_issue_detected_at": null,
"is_in_grace_period": false,
"active_introductory_offer_type": null,
"active_promotional_offer_type": null,
"active_promotional_offer_id": null,
"cancellation_reason": null,
"is_sandbox": true
},
"basic_subscription_unlimited": {
"is_active": true,
"is_lifetime": false,
"expires_at": "2021-02-27T11:00:30.000000+0000",
"starts_at": null,
"will_renew": false,
"vendor_product_id": "basic_subscription_unlimited",
"vendor_transaction_id": "1000000632277988",
"vendor_original_transaction_id": "1000000632277988",
"store": "app_store",
"activated_at": "2020-02-27T11:00:30.000000+0000",
"renewed_at": null,
"unsubscribed_at": null,
"billing_issue_detected_at": null,
"is_in_grace_period": false,
"active_introductory_offer_type": null,
"active_promotional_offer_type": null,
"active_promotional_offer_id": null,
"cancellation_reason": null,
"is_sandbox": true
}
},
"non_subscriptions": null
}
}
Learn more about responses in the API Objects section.
Revoke subscription from a user
POST: /profiles/{profile_id_or_customer_user_id}/paid-access-levels/{access_level}/revoke/
Path parameters
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
profile_id_or_customer_user_id | str | ✅ | ❌ | Adapty profile ID or developer's internal ID |
access_level | str | ✅ | ❌ | ID (slug) of a paid access level. Find it in Adapty Dashboard |
Request parameters
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
is_refund | bool | ✅ | ❌ | Whether this subscription is revoked due to a refund |
Revokes user's subscription by setting unsubscribed_at to current datetime, and expires_at to a maximum of current starts_at and current datetime (to avoid expires_at being less than starts_at). If there is a transaction associated with this paid access level, this transaction expiration is also set to the new expires_at value. If is_refund is true, the transaction is marked as a refund, and revenue is set to zero.
Get info about a user
GET: /profiles/{profile_id_or_customer_user_id}/
Path params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
profile_id_or_customer_user_id | str | ✅ | ❌ | Adapty profile ID or developer's internal ID |
Response example is the same as for Prolong/grant a subscription for a user.
To get extended response, add Key "extended" with any value to Query Params. It works only for GET request.
Property | Type | Required | Nullable | Description |
---|---|---|---|---|
created_at | ISO 8601 date | ✅ | ❌ | The date when the profile got created, usually equals the installation date |
str | ✅ | ✅ | User email | |
phone_number | str | ✅ | ✅ | User phone number |
att_status | str | ✅ | ✅ | |
first_name | str | ✅ | ✅ | User first name |
last_name | str | ✅ | ✅ | User last name |
username | str | ✅ | ✅ | Username |
gender | str | ✅ | ✅ | User gender |
birthday | ISO 8601 date | ✅ | ✅ | User birthday |
idfa | str | ✅ | ✅ | The Identifier for Advertisers, assigned by Apple to a user's device. |
idfv | str | ✅ | ✅ | The Identifier for Vendors (IDFV) is a code assigned to all apps by one developer and is shared across all apps by that developer on your device. |
advertising_id | str | ✅ | ✅ | The Advertising ID is a unique identifier offered by the Android Operating System that advertisers might use to uniquely identify you. |
appsflyer_id | str | ✅ | ✅ | An AppsFlyer ID, automatically created id by AppsFlyer for every new install of an app. |
amplitude_user_id | str | ✅ | ✅ | The Amplitude User Id property specified and OneSignal's External User Id property needs to be set for message data of that device to be tracked. |
amplitude_device_id | str | ✅ | ✅ | The Amplitude Device ID, directly comes from your users' devices. |
mixpanel_user_id | str | ✅ | ✅ | User ID from Mixpanel. |
appmetrica_profile_id | str | ✅ | ✅ | User profile ID from AppMetrica. |
appmetrica_device_id | str | ✅ | ✅ | AppMetrica Device Id. |
facebook_anonymous_id | str | ✅ | ✅ | Facebook Anonymous ID. |
Create a user
POST: /profiles/
Request params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
customer_user_id | str | ✅ | ❌ |
Sample request
{
"customer_user_id": "123456"
}
Response is same with GET request (extended parameter does not work here).
You can also set user's attributes the same way as in the PATCH method.
Set the user's attribute
PATCH: /profiles/{profile_id_or_customer_user_id}/
Path params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
profile_id_or_customer_user_id | str | ✅ | ❌ | Adapty profile ID or developer's internal ID |
Request params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
ip_country | str | ❌ | ✅ | Country code in the two-letter format, eg. US. |
str | ❌ | ✅ | ||
phone_number | str | ❌ | ✅ | |
first_name | str | ❌ | ✅ | |
last_name | str | ❌ | ✅ | |
gender | str | ❌ | ✅ | Available values are f,m,o. f - female m - male o - other |
birthday | date | ❌ | ✅ | Date in YYYY-MM-DD format, eg. 1990-10-31. |
If you'd like to set custom attributes, you can pass them in custom_attributes
dictionary. A maximum of 10 custom attributes for the profile are allowed to be set. Only strings and floats are allowed as values, booleans will be converted to floats.
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
attribute_key | str | ✅ | ❌ | Only letters, numbers, dashes, points, and underscores are allowed. The attribute key must be no more than 30 characters. |
attribute_value | str|float | ✅ | ✅ | The attribute value must be no more than 30 characters. Send an empty value or null to delete the attribute. |
Sample request
{
"phone_number": "+18003330000",
"custom_attributes": {
"grade": 10,
"favorite_topic": "sports"
}
}
The response is the same as the GET request (extended parameter does not work here).
Delete user's data
DELETE /profiles/{profile_id_or_customer_user_id}/delete
Path params
Param | Type | Required | Nullable | Description |
---|---|---|---|---|
profile_id_or_customer_user_id | str | ✅ | ❌ | Adapty profile ID or developer's internal ID |
Calling this endpoint enables the deletion of a user's profile and all related data, rendering it inaccessible to the client. Any profile history linked to the deleted profile will be detached, and integration events previously sent to integrations will be deleted from the event feed.
Should another profile make a purchase from the device with the same Apple ID (or when subscription is restored), the profile history will be reassigned to the new profile, and integration events will be reissued.
Please be aware that this endpoint does not support bulk deletion, therefore each request must be handled individually. For managing a substantial number of users, it is advisable to execute requests concurrently.
Updated 15 days ago