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 token.

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

ParamTypeRequiredNullableDescription
profile_id_or_customer_user_idstrAdapty profile ID or developer's internal ID
access_levelstrID (slug) of a paid access level. Find it in Adapty Dashboard

Request params

ParamTypeRequiredNullableDescription
expires_atISO 8601 date❌* see belowSubscription deadline
duration_daysint❌* see belowAdditional days to a current subscription**
is_lifetimebool❌* see belowIf set true, then a user will forever have a paid access level forever
starts_atISO 8601 dateIf 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_idstrVendor product ID which initiates subscription prolongation. The default value is adapty_promotion
vendor_transaction_idstrTransaction ID in a vendor environment
storestrA store where users purchased a product, such as app_store and play_store, can be custom. Default is adapty
introductory_offer_typestrA type of introduction offer. Available values are free_trial, pay_as_you_go, and pay_up_front.
pricefloatPrice of the subscription/purchase to save in transaction
proceedsfloatProceeds (price that is reduced due to stores' fee) of the subscription/purchase to save in transaction
price_localestrThe currency of the price and proceeds. Default is USD

Paid access level

There are three ways to grant users a subscription. So, at least one of is_lifetime, expires_at, duration_days, ** must be set. If more than one param is sent, 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

ParamTypeRequiredNullableDescription
profile_id_or_customer_user_idstrAdapty profile ID or developer's internal ID
access_levelstrID (slug) of a paid access level. Find it in Adapty Dashboard

Request parameters

ParamTypeRequiredNullableDescription
is_refundboolWhether 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

ParamTypeRequiredNullableDescription
profile_id_or_customer_user_idstrAdapty 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.

PropertyTypeRequiredNullableDescription
created_atISO 8601 dateThe date when the profile got created, usually equals the installation date
emailstrUser email
phone_numberstrUser phone number
att_statusstr
first_namestrUser first name
last_namestrUser last name
usernamestrUsername
genderstrUser gender
birthdayISO 8601 dateUser birthday
idfastrThe Identifier for Advertisers, assigned by Apple to a user's device.
idfvstrThe 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_idstrThe Advertising ID is a unique identifier offered by the Android Operating System that advertisers might use to uniquely identify you.
appsflyer_idstrAn AppsFlyer ID, automatically created id by AppsFlyer for every new install of an app.
amplitude_user_idstrThe 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_idstrThe Amplitude Device ID, directly comes from your users' devices.
mixpanel_user_idstrUser ID from Mixpanel.
appmetrica_profile_idstrUser profile ID from AppMetrica.
appmetrica_device_idstrAppMetrica Device Id.
facebook_anonymous_idstrFacebook Anonymous ID.

Create a user

POST: /profiles/

Request params

ParamTypeRequiredNullableDescription
customer_user_idstr

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

ParamTypeRequiredNullableDescription
profile_id_or_customer_user_idstrAdapty profile ID or developer's internal ID

Request params

Param Type Required Nullable Description
email str
phone_number str
first_name str
last_name str
gender str

f|m|o

f - female

m - male

o - other

birthday date 1990-10-31

If you'd like to set custom attributes, you can pass them in custom_attributes dictionary. Maximum of 10 custom attributes for the profile allowed to be set. Only strings and floats allowed as values, booleans will be converted to floats.

ParamTypeRequiredNullableDescription
attribute_keystrOnly letters, numbers, dashes, points, and underscores allowed. The attribute key must be no more than 30 characters.
attribute_valuestr|floatThe attribute value must be no more than 30 characters. Send 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}/delete

The DELETE endpoint is a simple HTTP request that allows you to delete a user's profile and all associated data, making it inaccessible to the client. Please note that this endpoint does not support bulk deletion, so you will have to make the needed requests individually. If you have a large number of users, we recommend making the DELETE requests concurrently.