POST /api/v1/profile/transaction-event/save/

Save transaction event

Records a store transaction event for a profile. Adapty Mail uses transaction events to place profiles in purchase-based flows — the event_type maps to flows such as renewal cancelled, billing issue, expired, and refunded — and for revenue attribution.

Send these events as you handle purchases, renewals, and cancellations. Only the never purchased flow works without them.

Request body

event_typestringrequired

The kind of transaction event. Purchase-based flows are triggered by these values.

One of: "subscription_started", "subscription_renewed", "subscription_renewal_cancelled", "subscription_renewal_reactivated", "billing_issue_detected", "entered_grace_period", "subscription_refunded", "subscription_expired", "non_subscription_purchase", "non_subscription_purchase_refunded"

event_idstringrequired

Unique identifier for this event, owned by your system. Use it to keep events idempotent.

event_datetimestringrequired

When the event was recorded, in ISO 8601 format.

external_profile_idstringrequired

The same stable external_profile_id you send when saving the profile. Links the transaction to the right profile. You can send a transaction before the profile exists. Adapty Mail stores the event unattached and links it to the profile on the next save that carries the same identifier.

customer_user_idstring

The user's identifier in your own system. Adapty Mail uses it to find the profile when external_profile_id doesn't match one. It isn't stored on the event.

emailstring

The buyer's email address. Adapty Mail uses it to find the profile when neither identifier matches one. It isn't stored on the event.

storestringrequired

The store the transaction came from, for example, app_store, play_store, or stripe.

store_product_idstringrequired

Identifier of the purchased product in the store.

store_transaction_idstringrequired

Identifier of this transaction in the store.

store_original_transaction_idstringrequired

Identifier of the first transaction in the subscription chain. For the first purchase, this equals store_transaction_id.

purchased_atstringrequired

When this transaction occurred, in ISO 8601 format.

originally_purchased_atstringrequired

When the subscription was first purchased, in ISO 8601 format.

price_usdstring

The transaction amount in USD, as a decimal string (for example, "9.99").

expires_atstring

When the subscription expires or expired, in ISO 8601 format. Omit for non-subscription purchases.

offerobject

Details of a promotional or introductory offer applied to the transaction.

categorystringrequired

One of: "introductory", "promotional", "offer_code", "win_back"

offer_typestringrequired

One of: "free_trial", "pay_as_you_go", "pay_up_front"

offer_idstring

Identifier of the offer in the store, if any.

Responses

Transaction event saved successfully. The response body is an empty object.

Schema
object
Example
{}

Validation failed — a required field is missing or invalid. field_name shows which field.

Schema

Standard error response. Every failure returns a 4XX status with this shape.

errorsarray of object
messagestring

Human-readable description of the error.

error_codestring

Machine-readable error identifier.

status_codeinteger

HTTP status code for this error.

field_namestring

The request field that caused the error, or null if the error isn't field-specific.

Example
{
  "errors": [
    {
      "message": "Field required",
      "error_code": "base_error",
      "status_code": 400,
      "field_name": "event_type"
    }
  ]
}

Missing or invalid secret API key.

Schema

Standard error response. Every failure returns a 4XX status with this shape.

errorsarray of object
messagestring

Human-readable description of the error.

error_codestring

Machine-readable error identifier.

status_codeinteger

HTTP status code for this error.

field_namestring

The request field that caused the error, or null if the error isn't field-specific.

Example
{
  "errors": [
    {
      "message": "Secret key doesn't exist",
      "error_code": "secret_key_does_not_exist_error",
      "status_code": 403,
      "field_name": null
    }
  ]
}