pex

apex-spec v1.3.0

The Apex Spec

The canonical event vocabulary your app and Apex's platform speak. Templates, journeys, audiences, and conversion goals all read field names from this catalog \u2014 so naming a payload the spec way means everything you wire up afterward just snaps together.

Customer SDK

App events

112 declared

What your customer-facing app fires through the snippet or SDK. Commerce, identity, engagement, communication \u2014 the canonical vocabulary you stand up day one.

apex.track('add_to_cart', { product_id, value, currency })

Apex platform

Platform events

65 declared

What Apex's dashboard fires as merchants use it. Invitations, integrations, experiments, portfolio access, billing transitions. Templates and journeys wire up these out of the box.

trackApexInternal({ eventName: 'user_invitation_accepted', \u2026 })

Three nouns, one vocabulary

  • The Apex Spec — the global contract on this page: every canonical event + attribute, shared by all merchants.
  • Schema — your workspace's slice of the Spec: the events + attributes you've wired, plus any you define yourself.
  • PLG event catalog — a convenience set of lifecycle events the SDK helps you fire; each one maps to a canonical Spec event.

Which revenue event do I use?

Several events carry a money value. Pick by where the truth lives, not by what's easiest to fire:

  • Web / server commerce → order_placed (the money-truth lane; fire it from your server). This is the dollar source of record.
  • Mobile in-app purchase → in_app_purchase (store-verified).
  • checkout_completed is the client-side mirror — great for funnel/UX analysis, but it can duplicate or be blocked, so don't use it as the revenue source of record when order_placed exists.

App events

What your customer-facing app fires. Field names are flat snake_case (e.g. product_id, order_id).

Commerce

Cart, checkout, and revenue. Drives attribution + abandonment journeys.

add_to_cart

Primary metric

User added a product to their cart.

product_id*
string
prod_atlas_runner_blue_42
product_name
string
Atlas Trail Runner
value
number
129.99
cart_value
number
currency
string
USD
quantity
number
1
item_count
number
cart_id
string
cart_9f2e1a

remove_from_cart

User removed a product from their cart.

product_id*
string
prod_atlas_runner_blue_42
product_name
string
Atlas Trail Runner
value
number
129.99
currency
string
USD
quantity
number
1
cart_id
string
cart_9f2e1a

product_view

User viewed a product detail screen.

product_id*
string
prod_atlas_runner_blue_42
product_name
string
Atlas Trail Runner
category
string
Footwear / Running
value
number
129.99
currency
string
USD

add_to_wishlist

User added a product to a wishlist or saved-for-later list.

product_id*
string
prod_atlas_runner_blue_42
product_name
string
Atlas Trail Runner
value
number
129.99
currency
string
USD

cart_view

User viewed their cart. The funnel stage between add_to_cart and checkout_started (GA4's view_cart).

value
number
259.98
currency
string
USD
item_count
number
2
cart_id
string
cart_9f2e1a

cart_snapshot

Full cart state at a point in time — powers abandoned-cart recovery journeys with the exact items to recover.

items*
array
value
number
259.98
currency
string
USD
item_count
number
2
cart_id
string
cart_9f2e1a

checkout_started

Primary metric

User began the checkout flow.

value
number
259.98
currency
string
USD
item_count
number
2
cart_id
string
cart_9f2e1a

checkout_completed

Primary metric

Client-side checkout success. The browser/app-side completion signal — `order_placed` (server) and `in_app_purchase` (IAP) remain the money-truth lanes when both exist.

order_id
string
ord_2024_03_45891
value*
number
259.98
currency*
string
USD
item_count
number
2
items
array
cart_id
string
subtotal
number
244
total
number
259.98
tax
number
15.98
shipping
number
0
handling
number
discount
number
coupon
string
account_id
string

in_app_purchase

Primary metric

Revenue event: user completed a purchase inside the app.

order_id*
string
ord_2024_03_45891
value*
number
259.98
currency*
string
USD
product_id
string
prod_atlas_runner_blue_42
product_name
string
Atlas Trail Runner
transaction_id
string
txn_stripe_3PqXyZ
items
array
is_restored
boolean
false
subtotal
number
total
number
tax
number
shipping
number
handling
number
discount
number
coupon
string
account_id
string

purchase_refunded

Primary metric

A prior purchase was refunded.

order_id*
string
ord_2024_03_45891
value*
number
129.99
currency*
string
USD
reason
string
Customer requested refund within return window
product_id
string
prod_atlas_runner_blue_42
account_id
string

subscription_event

Primary metric

Subscription lifecycle transition (start, renew, cancel, trial conversion, etc).

product_id*
string
atlas_pro_annual
action*
string
start
amount
number
299
currency
string
USD
period_type
string
annual
transaction_id
string
txn_stripe_3PqXyZ
expires_at
string
2027-05-21T00:00:00Z
is_trial
boolean
false
seat_count
number
25
account_id
string

subscription_started

Primary metric

A subscription began (first activation, including trial start). Renewals and plan changes flow through subscription_event.

product_id*
string
atlas_pro_annual
amount
number
299
currency
string
USD
period_type
string
annual
transaction_id
string
is_trial
boolean
false
account_id
string

subscription_canceled

Primary metric

A subscription was canceled by the user or by billing failure. The churn moment win-back journeys trigger on.

product_id*
string
atlas_pro_annual
reason
string
user_canceled
expires_at
string
2027-05-21T00:00:00Z
account_id
string

payment_failed

Primary metric

A subscription/invoice payment attempt failed. Triggers the dunning (payment-recovery) journey.

invoice_id*
string
in_3PqXyZ
amount*
number
299
currency*
string
USD
subscription_id
string
sub_3PqXyZ
transaction_id
string
txn_stripe_3PqXyZ
attempt_number
number
1
next_retry_at
string
2026-06-22T00:00:00Z
update_payment_url
string
https://billing.example.com/update
account_id
string

payment_recovered

Primary metric

A previously-failed payment succeeded on retry or after the customer updated billing. The dunning journey's goal/exit event.

invoice_id*
string
in_3PqXyZ
amount*
number
299
currency*
string
USD
subscription_id
string
sub_3PqXyZ
transaction_id
string
txn_stripe_3PqYZ2
account_id
string

order_placed

Primary metric

An order was placed (server-confirmed purchase). The money-truth lane: this is the dollar source of record for revenue and order-confirmation comms. Fire it from your server, not the browser.

order_id*
string
ord_2024_03_45891
value*
number
129.99
currency
string
USD
item_count
number
2
product_name
string
Atlas Trail Runner
order_url
string
/orders/ord_2024_03_45891
subtotal
number
total
number
tax
number
shipping
number
handling
number
discount
number
coupon
string
account_id
string

Where this is used

first_sale_completed

A marketplace seller's first sale completed. Drives the seller-activation comm.

order_id
string
ord_2024_03_45891
value
number
49.99
currency
string
USD
buyer_name
string
Alex Rivera
product_name
string
Vintage Film Camera
payout_days
number

trial_expired

Primary metric

A trial ended without converting (distinct from trial_expiring, which fires BEFORE).

plan
string
atlas_pro

invoice_paid

Primary metric

An invoice was paid successfully (normal billing success; distinct from payment_recovered).

invoice_id*
string
in_3PqXyZ
amount*
number
299
currency*
string
USD
subscription_id
string
sub_3PqXyZ
next_billing_date
string
2026-07-20

subscription_renewed

Primary metric

A subscription renewed for another period. The renewal moment (was subscription_event action=renew).

product_id
string
atlas_pro_annual
amount
number
299
currency
string
USD
period_type
string
annual
transaction_id
string

subscription_upgraded

Primary metric

A subscription moved to a higher plan or more seats (expansion). Carry the NEW recurring amount so MRR expansion is computable.

product_id
string
atlas_pro_annual
from_plan
string
Starter
to_plan
string
Pro
amount
number
299
currency
string
USD
period_type
string
annual
seat_count
number
25
account_id
string

Where this is used

Templates

subscription_downgraded

Primary metric

A subscription moved to a cheaper plan or fewer seats (contraction). Carry the NEW recurring amount so MRR contraction is computable.

product_id
string
atlas_starter_monthly
from_plan
string
Pro
to_plan
string
Starter
amount
number
49
currency
string
USD
period_type
string
monthly
seat_count
number
5
reason
string
seat_reduction
account_id
string

Where this is used

Identity

Sign-up, sign-in, and identity stitching.

user_signed_up

Primary metric

A new user account was created.

method
string
email
referrer
string
https://google.com/search?q=atlas+running

user_signed_in

User authenticated into the app.

method
string
email

user_signed_out

User signed out of the app.

No payload fields required.

user_identified

Anonymous visitor was linked to a known user identity.

user_id*
string
usr_atlas_8f3a92
traits
object

Lifecycle

Install, open, background, uninstall. Session foundation.

app_install

First install of the app on this device.

No payload fields required.

app_open

Primary metric

App was foregrounded by the user. Foundational session signal.

source
string
push_notification

app_background

App was backgrounded.

No payload fields required.

app_uninstall

App was uninstalled from the device (server-inferred from push silent failure).

No payload fields required.

app_crash

The native app crashed. A harm signal for mobile experiment guardrails.

message
string
NSInvalidArgumentException
stack
string
fatal
boolean
true

app_reinstall

App was reinstalled within the reinstall window.

No payload fields required.

user_churned

Primary metric

A customer churned (lapsed/cancelled past the win-back window). Drives win-back.

reason
string
stopped_using

user_reactivated

Primary metric

A churned customer came back. Drives reactivation-welcome comms.

inactive_days
number
92
changes_summary
string
New mobile app + faster checkout

Session

Explicit session boundaries with duration.

session_start

Beginning of a session (gap from last event > session timeout).

session_id
string
sess_2026_05_21_abc123

session_end

End of a session (background or timeout).

session_id
string
sess_2026_05_21_abc123
duration_ms
number
187320

Engagement

Page views, screens, searches, content interactions.

page_view

User viewed a screen or page. Canonical name across web and mobile.

path
string
/products/atlas-runner
title
string
Atlas Runner — Atlas Athletics
referrer
string
https://google.com/search?q=atlas+running

pageview

Deprecated · use page_view

Legacy web pageview. Prefer `page_view` for new integrations.

path
string
/products/atlas-runner
title
string
Atlas Runner — Atlas Athletics
referrer
string
https://google.com/search?q=atlas+running

screen_view

Mobile screen render. Equivalent to `page_view` for native screens.

screen_name*
string
ProductDetail
previous_screen
string
ProductList

search

User executed a search query.

query*
string
trail running shoes
results_count
number
24

share

User shared content to an external surface.

content_id
string
prod_atlas_runner_blue_42
channel
string
twitter

content_view

User viewed a piece of content (article, video, etc).

content_id*
string
blog_2026_05_running_form_guide
content_type
string
article
duration_ms
number
42500

form_submit

Form was submitted by the user.

form_id
string
newsletter_signup

click

Generic click event.

target
string
button#hero-cta

engagement

Composite engagement signal (web only — replaced by individual events on mobile).

No payload fields required.

heartbeat

Periodic heartbeat indicating the user is still active on a page.

No payload fields required.

rage_click

Multiple rapid clicks on the same element — frustration signal.

target
string
button#submit-disabled

dead_click

Click that produced no observable effect — frustration signal.

target
string
div.banner-image

goal_conversion

Primary metric

User completed a defined conversion goal.

goal_id*
string
signup_completed
value
number
25

Where this is used

onboarding_step_completed

User finished one step of a guided onboarding / activation flow. A proximal funnel signal — emit one per step from the client where the step happens.

step_id
string
connect_data_source
step_index
number
2
step_name
string
Connect a data source

feature_used

User used a specific product feature. Powers expansion + adoption comms.

feature_name*
string
advanced_reports
count
number
1

webinar_registered

Primary metric

User registered for a webinar. A campaign conversion signal.

webinar_topic
string
Scaling growth experiments
webinar_date
string
2026-07-10

survey_started

User began a survey (e.g. NPS).

survey_id
string
nps_2026_q2

survey_completed

Primary metric

User completed a survey. A campaign conversion signal.

survey_id
string
nps_2026_q2
score
number
9

report_viewed

User viewed a report or dashboard. A core SaaS engagement signal.

report_id
string
rpt_8821
report_name
string
Weekly performance

content_viewed

User viewed a piece of content (article, video, screen). A core engagement signal for content + mobile apps.

content_id
string
cnt_4410
content_type
string
video

task_completed

User completed a task / unit of work. A depth-of-use engagement signal.

task_id
string
tsk_5567
task_type
string
onboarding_step

api_request_completed

User's integration made a successful API request. The core active signal for API-first / developer products.

endpoint
string
/v1/messages
count
number
1

Product

Product-led-growth outcomes: onboarding completion and activation.

onboarding_completed

User finished the onboarding flow. Source-of-truth milestone — emit server-side when onboarding state flips to complete.

duration_ms
number
420000
steps_completed
number
4

activated

Primary metric

User reached the activation / 'aha' milestone (the moment they got first value). The PLG north-star outcome. Emit server-side when the activation criterion is met.

criterion
string
connected_first_integration

project_created

User created their first/Nth project or workspace. A common SaaS + agency activation milestone.

project_id
string
prj_2231
project_name
string
Q3 Launch

Marketing

Merchant-fired triggers that prompt a comm (price drop, restock, review request). Not goal-tier events.

price_dropped

Price dropped on a product a customer viewed or saved. Drives price-drop alerts.

product_id
string
prod_atlas_runner_blue_42
product_name*
string
Atlas Trail Runner
old_price
number
129.99
new_price
number
99.99
discount_percent
number
currency
string
USD
product_url
string
/products/atlas-trail-runner

restock_due

A back-in-stock / restock reminder is due for a product. Drives restock comms.

product_id
string
prod_atlas_runner_blue_42
product_name*
string
Atlas Trail Runner
days_since_purchase
number
product_url
string
/products/atlas-trail-runner

review_request_due

A post-purchase review request is due. Drives review-request comms.

product_id
string
prod_atlas_runner_blue_42
product_name*
string
Atlas Trail Runner
order_id
string
ord_2024_03_45891
days_ago
number
review_url
string
/orders/ord_2024_03_45891/review

Fulfillment

Post-purchase shipping + delivery. Drives shipping + review-request comms.

order_shipped

A placed order shipped. Drives shipping-notification comms.

order_id*
string
ord_2024_03_45891
carrier
string
UPS
tracking_url
string
https://ups.com/track?n=1Z999
delivery_estimate
string
2026-06-24
shipped_at
string

order_delivered

A shipped order was delivered. Drives review-request + post-purchase comms.

order_id*
string
ord_2024_03_45891
delivered_at
string
2026-06-24T18:02:00Z

return_requested

A buyer asked to send goods back. Starts the returns story — distinct from purchase_refunded (money back).

order_id*
string
ord_2024_03_45891
product_id
string
prod_atlas_runner_blue_42
reason
string
wrong_size
quantity
number
1

return_completed

Returned goods were received back. The return-rate numerator; fire purchase_refunded separately when money moves.

order_id*
string
ord_2024_03_45891
product_id
string
prod_atlas_runner_blue_42
reason
string
wrong_size
condition
string
resellable
refunded
boolean
true

Marketplace

Seller + buyer lifecycle: signups, listings, payouts, reviews, trust badges.

seller_signup

Primary metric

A seller joined the marketplace. The marketplace-side activation conversion.

seller_id
string
sel_4821
store_name
string
Atlas Outfitters

listing_created

A seller created a listing. Drives first-listing + activation nudges.

listing_id
string
lst_99213
product_name
string
Atlas Trail Runner
price
number
129.99
currency
string
USD

buyer_review_requested

A buyer is due to review a marketplace purchase.

order_id
string
ord_2024_03_45891
product_name
string
Atlas Trail Runner
seller_name
string
Atlas Outfitters

payout_sent

A seller payout was sent. Drives payout-confirmation comms.

amount*
number
482.5
currency*
string
USD
payout_id
string
po_8841
transaction_count
number
12
payment_method
string
bank_transfer
processing_days
number
2

trust_badge_earned

A seller earned a trust badge (e.g. Top Rated).

badge_name*
string
Top Rated Seller

listing_viewed

A buyer viewed a marketplace listing. A demand-side engagement signal.

listing_id
string
lst_99213
product_name
string
Atlas Trail Runner

message_sent

A user sent a message (buyer↔seller). A liquidity + engagement signal for marketplaces.

thread_id
string
thr_7781

offer_submitted

A buyer submitted an offer / bid on a listing. A high-intent demand signal.

listing_id
string
lst_99213
amount
number
110
currency
string
USD

transaction_completed

Primary metric

A marketplace transaction closed (buyer + seller). The two-sided activation/outcome moment.

transaction_id
string
txn_55621
amount
number
129.99
fee_amount
number
15.6
cost_amount
number
4.1
currency
string
USD
buyer_id
string
u_buyer_812
seller_id
string
sel_4821
listing_id
string
lst_99213
category
string
footwear
geo
string
US
price_band
string
100-250

seller_viewed

A buyer viewed a seller's profile/storefront. A demand-side trust signal.

seller_id
string
sel_4821
store_name
string
Atlas Outfitters

item_saved

A buyer saved/favorited a listing. A mid-funnel demand signal.

listing_id
string
lst_99213
product_name
string
Atlas Trail Runner

inquiry_started

A buyer opened an inquiry/conversation about a listing. High-intent demand.

listing_id
string
lst_99213
thread_id
string
thr_7781

match_created

Supply and demand matched (offer accepted / booking confirmed) before payment. The liquidity moment for negotiated marketplaces.

listing_id
string
lst_99213
buyer_id
string
u_buyer_812
seller_id
string
sel_4821
amount
number
110
currency
string
USD

transaction_canceled

A marketplace transaction was canceled before fulfillment. The cancellation-rate numerator.

transaction_id
string
txn_55621
reason
string
out_of_stock
canceled_by
string
seller

review_submitted

A post-transaction review was submitted. Powers average rating + review coverage (trust metrics).

transaction_id
string
txn_55621
listing_id
string
lst_99213
rating
number
5
reviewer_side
string
buyer

dispute_opened

A buyer or seller opened a dispute on a transaction. The dispute-rate numerator (trust metric).

transaction_id
string
txn_55621
reason
string
item_not_as_described
opened_by
string
buyer

Agency

Client lifecycle: onboarding, campaign milestones, renewals, new capabilities.

client_onboarded

Primary metric

An agency onboarded a new client. The agency-side activation conversion.

client_id
string
cli_2231
client_name
string
Northwind Co
manager_name
string
Jordan Lee

campaign_milestone_reached

A client campaign hit a milestone. Drives results/update comms.

campaign_id
string
cmp_5521
campaign_name
string
Spring Launch
milestone
string
100 conversions
business_impact
string
+$24k pipeline

contract_renewal_approaching

A client contract renewal is approaching. Drives renewal comms.

contract_id
string
ct_7781
days_remaining
number
30
renewal_date
string
2026-07-20
contract_period
string
annual

new_capability_launched

The agency launched a new capability/service. Drives announcement comms.

capability_id
string
cap_312
capability_name
string
Paid Social
capability_description
string
Full-funnel paid social management

task_updated

An agency team member updated a task. A core agency activity signal.

task_id
string
tsk_5567
status
string
in_progress

asset_uploaded

A team member uploaded an asset/deliverable. A core agency activity + activation signal.

asset_id
string
ast_3312
asset_type
string
creative

comment_added

A user added a comment / collaboration note. A depth-of-use signal.

target_id
string
ast_3312

time_logged

A team member logged time against a client/project. A core agency activity signal.

minutes
number
90
project_id
string
prj_2231

client_report_viewed

A client viewed an agency results report. A retention + value-delivery signal.

report_id
string
rpt_8821
client_id
string
cli_2231

Loyalty

Loyalty + usage milestones that prompt reward and celebration comms.

loyalty_milestone_reached

A customer hit a loyalty milestone (points/tier). Drives reward comms.

points
number
5000
reward
string
$50 credit
milestone
string
Gold tier

usage_milestone_reached

A customer crossed a usage milestone. Drives celebratory + expansion comms.

milestone
string
1,000 events tracked
percentile
number
95

Communication

Push, email, in-app message delivery + interaction.

push_received

Device received a push notification (delivery confirmation).

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026

push_opened

User tapped/opened a push notification.

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026
deep_link
string
atlas://product/atlas-runner

email_opened

Email open tracked via pixel.

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026

email_clicked

Link in email was clicked.

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026
link
string
https://atlasathletics.com/products/atlas-runner

unsubscribed

Recipient unsubscribed from a message/list. A harm signal for messaging experiment guardrails.

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026
list_id
string

in_app_message_seen

In-app message was rendered to the user.

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026

in_app_message_clicked

User interacted with an in-app message CTA.

message_id
string
msg_2026_05_21_abc
campaign_id
string
cmp_atlas_spring_2026
cta
string
upgrade_now

Attribution

Reattribution and reengagement signals.

reattribution

A re-install was matched to a prior install.

partner_id
string
partner_facebook_ads
original_install_id
string
inst_2025_11_xyz

reengagement

A returning user opened the app after a period of inactivity.

partner_id
string
partner_email_winback
inactive_days
number
30

Smart banner

Apex smart banner impressions, clicks, dismissals.

smart_banner_impression

Apex smart banner was shown on a mobile web page.

No payload fields required.

smart_banner_click

User clicked the smart banner CTA.

No payload fields required.

smart_banner_dismiss

User dismissed the smart banner.

No payload fields required.

System

Custom events and internal lifecycle transitions.

custom

Custom event type. Stored with the original event name preserved in `data.eventName`. Use canonical events when possible.

No payload fields required.

lifecycle_transition

Internal Apex lifecycle/level transition event (not user-generated).

No payload fields required.

js_error

JavaScript runtime error captured by the web SDK.

message
string
ReferenceError: window.atlas is not defined
stack
string
at fn (https://atlasathletics.com/app.js:123:45)

Platform events

What Apex itself fires as merchants use the dashboard. Useful when you build agent automations on top of the platform.

Invitations

Team invite lifecycle from Apex's dashboard.

user_invitation_created

An organization owner/admin invited a new teammate. Drives the invite email + reminder branch.

inviter_name*
string
Sarah Chen
inviter_email
string
sarah@hypernova.inc
org_name*
string
Hypernova Inc
org_id*
string
org_hypernova_8f3a
invitee_email*
string
alex@example.com
role*
string
admin
accept_url*
string
https://app.apex.inc/invite/accept?token=inv_4f8a2b7c9d3e1f6a
invitation_token
string
inv_4f8a2b7c9d3e1f6a
invitation_id
string
inv_4f8a2b7c

Where this is used

user_invitation_accepted

A pending invitation was accepted. Notifies the inviter that their teammate joined.

member_name*
string
Alex Rivera
inviter_name
string
Sarah Chen
inviter_email
string
sarah@hypernova.inc
org_name*
string
Hypernova Inc
role*
string
admin
invitee_email
string
alex@example.com
href
string
/dashboard/settings/organization/team

developer_invite_sent

An operator handed SDK wire-up off to a developer with a private integration-guide link.

inviter_name*
string
Sarah Chen
inviter_role
string
admin
developer_email*
string
dev@hypernova.inc
workspace_name
string
Hypernova Production
note
string
Snippet goes in the global layout please.
handoff_url*
string
https://app.apex.inc/onboarding/developer-handoff?token=hof_4f8a2b7c
signup_url
string
https://app.apex.inc/signup

Where this is used

Integrations

Connector connect / sync / failure events Apex fires per merchant.

integration_sync_failed

A scheduled data import from a connected integration failed.

integration_name*
string
Google Analytics
error_message
string
Authentication expired — please reconnect.
integrations_url
string
/dashboard/integrations

Experiments

Launches, significance, conclusions, promotion to default.

experiment_launched

An A/B experiment was started.

experiment_name*
string
Homepage CTA Copy Test
experiment_url
string
/dashboard/experiments/exp_homepage_cta
hypothesis
string
Changing the CTA from 'Get Started' to 'Start Free' lifts signup rate by 15%.

experiment_created

An experiment was created as a draft. Enrolls the operator's lifecycle journey (1h publish-nudge gate).

experiment_id
string
experiment_name*
string
Homepage CTA Copy Test
surface
string
web
experiment_url
string
/dashboard/experiments/exp_homepage_cta

experiment_first_exposure

The first visitor was bucketed into a running experiment (the 'it's alive' moment). Fires once.

experiment_id
string
experiment_name*
string
Homepage CTA Copy Test
experiment_url
string
/dashboard/experiments/exp_homepage_cta

experiment_daily_recap

Daily digest of all active experiments for a workspace admin. Carries an `experiments` array rendered by the recap comm's repeater block.

count
number
2
experiments
string

experiment_projected_underpowered

A running experiment is projected to reach the end of its window without enough traffic to call a result. Fired while there is still time to extend, unlike experiment_window_closed_underpowered which fires after the deadline has passed.

experiment_id
string
experiment_name*
string
Welcome subject line
projection_reason
string
too_slow
exposure_per_arm
string
18
sample_floor_per_arm
string
50
days_elapsed
string
7
days_remaining
string
7
days_still_needed
string
13
lift_so_far
string
+4.1%
confidence_so_far
string
preview_url
string
experiment_url
string
/dashboard/experiments/exp_welcome_subject

experiment_window_closed_underpowered

An experiment's evaluation window closed while still underpowered (sample floor unmet). The operator can extend once or let it auto-conclude.

experiment_id
string
experiment_name*
string
Homepage CTA Copy Test
exposure_per_arm
string
48
sample_floor_per_arm
string
200
detectable_lift_floor
string
grace_days_remaining
string
5
experiment_url
string
/dashboard/experiments/exp_homepage_cta

experiment_significant

An experiment reached statistical significance.

experiment_name*
string
Homepage CTA Copy Test
winning_arm
string
Start Free
lift
string
+18.3%
confidence
string
97%
exposures
string
12,480
preview_url
string
https://apex-avatars-staging.s3.amazonaws.com/experiment-assets/exp_homepage_cta/variant-1.png
experiment_url
string
/dashboard/experiments/exp_homepage_cta

experiment_concluded

An experiment finished (either by significance or by evaluation-window expiry).

experiment_name*
string
Homepage CTA Copy Test
result
string
winner
lift
string
+18.3%
confidence
string
97%
confidence_interval
string
safety_verdict
string
exposures
string
12,480
preview_url
string
https://apex-avatars-staging.s3.amazonaws.com/experiment-assets/exp_homepage_cta/variant-1.png
experiment_url
string
/dashboard/experiments/exp_homepage_cta
result_label
string
Significant winner

Where this is used

experiment_promoted

An experiment's winning arm was promoted to the default.

experiment_name*
string
Homepage CTA Copy Test
winning_arm
string
Start Free
lift
string
+18.3%
confidence
string
97%
exposures
string
12,480
preview_url
string
https://apex-avatars-staging.s3.amazonaws.com/experiment-assets/exp_homepage_cta/variant-1.png
experiment_url
string
/dashboard/experiments/exp_homepage_cta

experiment_deploying

A gated experiment's PR merged; the variant is deploying. The test starts counting on the first live visitor.

experiment_name*
string
Homepage CTA Copy Test
experiment_url
string
/dashboard/experiments/exp_homepage_cta

experiment_graduated

Apex opened a graduation PR to bake the winning variant into the merchant's code and remove the experiment flag.

experiment_name*
string
Homepage CTA Copy Test
graduation_pr_url*
string
https://github.com/acme/site/pull/482
experiment_url
string
/dashboard/experiments/exp_homepage_cta

guardrail_breached

A running experiment significantly hurt a protected metric (a confirmed critical breach). Promotion is blocked.

experiment_id
string
experiment_name*
string
Free shipping banner
experiment_url
string
/dashboard/experiments/exp_abc
href
string
/dashboard/experiments/exp_abc

guardrail_autopaused

Apex auto-paused an experiment because a variant hurt a protected metric (auto-pause is on).

experiment_id
string
experiment_name*
string
Free shipping banner
experiment_url
string
/dashboard/experiments/exp_abc
href
string
/dashboard/experiments/exp_abc

experiment_invalid

An experiment's traffic split is broken (sample-ratio-mismatch), so its results can't be trusted.

experiment_id
string
experiment_name*
string
Free shipping banner
experiment_url
string
/dashboard/experiments/exp_abc
href
string
/dashboard/experiments/exp_abc

experiment_stale

An experiment is stuck — pending deployment past 30 days, running past its max duration, or live with real traffic but never counting an exposure (a likely broken deploy).

experiment_name*
string
Above-fold CTA
reason
string
pending_deployment_timeout
conclusion
string
Waiting 31 days for its PR to merge.
experiment_url
string
/dashboard/experiments/exp_482

experiment_awaiting_promotion

A manual-promotion experiment reached a confident winner and is waiting for an operator to promote it.

experiment_name*
string
Welcome Email Variant Test
winning_arm
string
Variant B
confidence
string
96%
lift
string
+12.4%
exposures
string
8,210
preview_url
string
https://apex-avatars-staging.s3.amazonaws.com/experiment-assets/exp_welcome/variant-b.png
experiment_url
string
/dashboard/experiments/exp_welcome

Portfolio

Investor / partner access requests and share-link acceptances.

portfolio_access_requested

An investor or partner requested access to a portfolio.

requester_name*
string
Sequoia Capital
requester_email
string
partners@sequoia.com
portfolio_name
string
Atlas Athletics — Series B Data Room
approve_url*
string
https://app.apex.inc/portfolio/requests/req_abc/approve
reject_url
string
https://app.apex.inc/portfolio/requests/req_abc/reject

portfolio_access_rejected

A portfolio access request was rejected by the owner.

granter_name*
string
Atlas Athletics
portfolio_name
string
Atlas Athletics — Series B Data Room
reason
string
Not ready to share yet — let's reconnect after our next board meeting.

portfolio_reconsent_required

A portfolio grant predates the current disclosure and needs re-approval before metrics resume.

viewer_name*
string
Sequoia Capital
disclosure_text
string
Approving shares your business performance with this organization: revenue and recurring revenue, growth, ...
granted_at
string
2026-02-14
expires_at
string
2026-08-27
review_url
string
/dashboard/settings/workspace/data-sharing

portfolio_company_flagged

An at-risk reason appeared on this company's portfolio snapshot for the first time, so the investors with access can now see it.

reasons*
string
Revenue down 34% over the last 30 days; Net revenue retention below 100%
viewer_names
string
Northline Capital, Ridgeway Partners
viewer_count
number
2
review_url
string
/dashboard

portfolio_share_accepted

A recipient accepted a portfolio share link.

viewer_email*
string
partners@sequoia.com
portfolio_name
string
Atlas Athletics — Series B Data Room
portfolio_url
string
/dashboard/portfolio
owner_name
string
Chris at Atlas
shared_at
string
2026-05-21T14:30:00Z

Engagement

Page views, screens, searches, content interactions.

adoption_gap_detected

An end-user has not yet adopted a feature within its milestone gap window. Fired by the Adoption Engine evaluator (directly, never via public ingest) to enroll the user in the feature's nudge journey. Nudge journeys filter on `feature_id`.

name
string
Dana
first_name
string
Dana
feature_id*
string
reporting
feature_name
string
Reporting
nudge_url
string
/dashboard/reports

milestone_adopted

An end-user just ACHIEVED an adoption milestone (its adoptedWhen predicate became true). Fired ONCE per (end-user, milestone) by the Adoption Engine evaluator directly (never via public ingest) to enroll the user in the milestone's celebration journey. This is the presence counterpart to `adoption_gap_detected` (absence). Celebration journeys filter on `milestone_id`.

name
string
Dana
first_name
string
Dana
milestone_id*
string
mile_ran_first_report
feature_id*
string
reporting
milestone_name
string
Ran a report
celebration_url
string
/dashboard/reports

Billing

Subscription upgrades, downgrades, and tier-limit nudges.

shared_pool_suspended

A workspace's shared-pool email sending was suspended by the circuit-breaker because its complaint/bounce rate crossed the SES limit. Drives the transactional suspension notice with the resume path (dedicated IP).

name
string
Chris
first_name
string
Chris
complaint_rate*
string
0.42%
upgrade_url
string
/dashboard/settings/workspace/deliverability

tier_limit_approaching

Workspace is nearing a plan limit; eligible for an upgrade nudge.

name
string
Chris
first_name
string
Chris
current_tier*
string
Starter
next_tier
string
Pro
feature_count
number
8
top_feature
string
CPWU Attribution
usage_percent
number
usage_current
number
usage_limit
number
resource_name
string
recommended_plan
string
upgrade_url
string
/dashboard/billing/upgrade

Where this is used

Templates

usage_threshold_reached

An org-pooled usage meter crossed a billing threshold (80% or 100% of the free allowance). Fires once per (org, meter, period, threshold). Drives the per-meter usage alert + 'Approaching your limit' journey.

name
string
Chris
first_name
string
Chris
billing_class*
string
communications
meter_label*
string
Messages
usage_pct*
number
100
free_limit*
number
10000
usage_current*
number
10000
period*
string
2026-06
cap_kind*
string
hard
overage_rate
number
0.0006
usage_url
string
/dashboard/settings/organization/usage

usage_period_reset

A new calendar-month billing period began; all usage meters reset to zero. Used to exit the 'Approaching your limit' journey.

name
string
Chris
first_name
string
Chris
period*
string
2026-07
usage_url
string
/dashboard/settings/organization/usage

usage_statement_ready

The monthly usage statement for an org is ready — an itemized, per-meter summary of usage and estimated charges. Transparency statement, not a payment.

name
string
Chris
first_name
string
Chris
period*
string
2026-06
est_total
number
336.5
statement_url
string
/dashboard/settings/organization/usage

usage_invoice_estimate

A few days before the period-close cron finalizes an org's usage invoice, this fires for orgs with a nonzero estimated overage that Apex can collect. Drives the pre-charge estimate email so the first invoice is never a surprise.

name
string
Chris
first_name
string
Chris
org_id*
string
org_hypernova_8f3a
org_name
string
Hypernova Inc
period*
string
2026-06
estimate_usd*
number
137
email
string
chris@hypernova.inc

usage_invoice_failed

An org's usage invoice exhausted Stripe's smart retries (or a net-terms invoice went past due). The org is marked delinquent; this drives the dunning notice with a link to the hosted invoice to fix payment.

name
string
Chris
first_name
string
Chris
org_id*
string
org_hypernova_8f3a
org_name
string
Hypernova Inc
amount_due_usd
number
137
hosted_invoice_url
string
https://invoice.stripe.com/i/acct_x/test_y
email
string
chris@hypernova.inc

merchant_payout_shortfall

A merchant's connected Stripe balance was insufficient to cover a scheduled partner payout. Graduated escalation (level 1/2/3) prompts the merchant to top up. Merchant-facing only — never surfaced to the partner.

name
string
Chris
first_name
string
Chris
workspace_key
string
acme-a1b2
escalation_level*
number
1
shortfall_usd*
number
240.5
next_retry_at
string
2026-07-15T02:00:00.000Z
payouts_url
string
/dashboard/settings/organization/payouts

partner_payout_paid

A partner's payout transfer succeeded. Fired synchronously the instant the facilitated Stripe transfer completes, so the partner gets an immediate receipt. Merchant balance/shortfall details are never included.

name
string
Sarah
first_name
string
Sarah
amount_usd*
number
245.5
transfer_id
string
tr_1TswmU
batch_id
string
pay_9f3a
payouts_url
string
https://partners.apex.inc/account#payouts

partner_payout_failed

A partner's payout could not be completed (e.g. their Stripe account is restricted). Prompts the partner to fix their payout setup. Never exposes the merchant's balance or cash position.

name
string
Sarah
first_name
string
Sarah
reason
string
Your Stripe account needs attention
payouts_url
string
https://partners.apex.inc/account#payouts

rate_change_scheduled

A future-dated price change was scheduled for a rate card. Drives the price-change transparency notice to every platform user. Effective dates are month-granular (takes effect the 1st of the period), so no customer is re-priced mid-cycle.

name
string
Chris
first_name
string
Chris
org_name
string
Atlas
rate_card*
string
Pay-as-you-go
effective_period*
string
2026-08
effective_label
string
August 2026
changes_summary*
string
Events: $0.00005 → $0.00006 per event
pricing_url
string
/pricing

Where this is used

billing_limit_approaching

A card-less org is approaching its free monthly allowance. Add a payment method to avoid losing dashboard access and paused sends. Fired once on the ok → approaching transition.

name
string
Chris
first_name
string
Chris
org_name
string
Atlas
usage_pct
number
80
driver_meter
string
web-measurement
billing_url
string
/dashboard/settings/organization/billing

billing_limit_reached

A card-less org hit 100% of its free monthly allowance — analytics views are now locked and non-transactional sends are paused. Add a payment method to restore access instantly. Fired once on the transition into analytics_locked.

name
string
Chris
first_name
string
Chris
org_name
string
Atlas
driver_meter
string
web-measurement
billing_url
string
/dashboard/settings/organization/billing

billing_limit_resolved

A card-less org's billing incident cleared — a payment method was added or usage reset for the new month. Access restored; nothing more to do. Paired resolved confirmation for billing_limit_approaching / billing_limit_reached.

name
string
Chris
first_name
string
Chris
org_name
string
Atlas
billing_url
string
/dashboard/settings/organization/billing

Where this is used

trial_expiring

A workspace trial is approaching expiry. Drives the trial-expiring upgrade nudge.

name
string
Chris
first_name
string
Chris
days_remaining
number
3
plan
string
Pro
value_summary
string
upgrade_url
string
/dashboard/billing/upgrade

Operations

Anomaly alerts, weekly digests, Cognito auth hooks.

account_health_alert

Apex stopped receiving data from a workspace's installed snippet/SDK, or a live experiment isn't rendering. Fired once per health incident (traffic-aware) by the account-health cron.

name
string
Chris
first_name
string
Chris
workspace_name
string
Atlas — Production
issue_summary*
string
your Apex snippet stopped sending data
issue_detail
string
We haven't seen an event or heartbeat from your site in over 24 hours. If you changed your site or removed the snippet, measurement is silently paused.
diagnose_url
string
/dashboard/mobile/health

account_health_resolved

A workspace's data-integrity incident cleared — events/heartbeats are flowing again. Paired resolved confirmation for account_health_alert.

name
string
Chris
first_name
string
Chris
workspace_name
string
Atlas — Production
health_url
string
/dashboard/mobile/health

url_drift_detected

The URL-drift cron detected that a workspace's stored site URL now redirects somewhere new, which can silently break measurement. Fired once per drift incident.

name
string
Chris
first_name
string
Chris
workspace_name
string
Atlas — Production
stored_url*
string
https://atlas.example.com
suggested_url*
string
https://www.atlas.example.com
drift_url
string
/dashboard/settings/workspace/general

url_drift_resolved

A tracked-URL drift cleared (the merchant accepted the new canonical, dismissed it, or the redirect went away). Paired resolved confirmation for url_drift_detected.

name
string
Chris
first_name
string
Chris
workspace_name
string
Atlas — Production
drift_url
string
/dashboard/settings/workspace/general

Where this is used

anomaly_detected

Apex detected a statistically anomalous shift in a tracked metric.

metric_name*
string
Google Ads CPC
scope
string
Atlas Athletics — Production
delta
string
+340% vs. 30-day average
investigate_url*
string
/dashboard/intelligence/anomalies/anom_2026_05_21
anomaly_url
string
/dashboard/intelligence/anomalies

Where this is used

weekly_digest_scheduled

Weekly summary digest was scheduled for delivery.

name
string
Chris
first_name
string
Chris
period*
string
May 14–20, 2026
digest_url
string
/dashboard/digest/2026-05-20
total_imports
string
4,832
active_integrations
string
3
experiments
string
2

Where this is used

Templates

cognito_verification_code

AWS Cognito custom-message hook needs a verification-code email rendered.

code*
string
482915
code_parameter
string
{####}

Where this is used

apex_setup_source_connected

A new Data Source was registered for the workspace (explicitly or lazily on first event).

source_kind*
string
website
source_id
string
ds_website

apex_setup_first_event_detected

The workspace's first real event arrived — the 'Apex is live' activation moment.

platform
string
web
event_name
string
page_view

apex_setup_first_identified_event

The workspace's first contact link was created — a named customer appeared in Apex (the onboarding north-star).

surface
string
web

apex_setup_templates_unlocked

A readiness unlock fired: required traits/events arrived and named templates became Ready to run.

unlock_id
string
unl_8f3a92
track_id
string
identity
template_count
number
3

apex_setup_first_belief_created

The workspace's first belief was authored — the first-insight → first-belief handoff completed.

belief_id
string
blf_2026_06_09
source
string
first-facts

report_generated

A scheduled report finished generating. Drives the agency/report-ready comm.

report_type
string
Monthly performance
report_id
string
period
string
May 2026
highlights
string
Spend down 12%, conversions up 8%.
report_url
string
/dashboard/reports/2026-05

Lifecycle

Install, open, background, uninstall. Session foundation.

user_signup

Apex-internal signup completion event — fires when a new merchant finishes signup in the Apex dashboard. Distinct from the SDK-side `user_signed_up` event which customers fire from their own app.

name
string
Chris Caldwell
first_name
string
Chris
onboarding_url
string
/dashboard
referring_org_id
string
org_atlas_ventures
referral_source
string
portfolio_invite

Where this is used

onboarding_in_progress

A merchant started but hasn't finished onboarding. Drives the onboarding-reminder nudge.

name
string
Chris
first_name
string
Chris
steps_remaining
number
2
onboarding_url
string
/dashboard?setup=welcome

Where this is used

onboarding_unlock_available

Apex closed a workspace's first loop while the operator was away — a pending onboarding unlock is waiting to be revealed. Fired once when a NEW pending unlock is created.

name
string
Chris
first_name
string
Chris
outcome
string
your first paying customer
artifact_count
number
3
reveal_url
string
/dashboard

feature_unused_for_7d

A high-value feature has gone unused for 7 days. Drives the feature-nudge comm.

name
string
Chris
first_name
string
Chris
feature_name*
string
Experiments
cta_url
string
/dashboard/experiments

Where this is used

Templates

password_reset_requested

A user requested a password reset. Recipient-initiated; drives the transactional reset email.

name
string
Chris
reset_url*
string
https://app.apex.inc/auth/reset?token=rst_4f8a2b7c

Where this is used

Attributes

Identity + entity traits you set via identify() and reference in templates as {{first_name}} or {{order.total}}. Generated from the Spec, so this list never drifts.

user

FieldTypeDescriptionExample
idstringStable end-user id passed to apex.identify().u_8c21
emailPIIemailEnd-user email. Required for transactional sends.alex@example.com
email_verifiedbooleanWhether the email has been confirmed.true
first_namestringGiven name. Use in greetings.Alex
last_namestringFamily name.Rivera
full_namestringFull display name.Alex Rivera
usernamestringHandle or login.arivera
phonePIIstringPhone number in E.164 where possible.+14155550100
avatar_urlurlProfile image URL.
titlestringJob title or role.Head of Growth
companystringCompany the user belongs to.Atlas
genderstringSelf-reported gender.
birthdayPIIdateDate of birth.1990-04-12
address_line1PIIstringStreet address line 1.1 Market St
address_line2PIIstringStreet address line 2.Suite 400
citystringCity.San Francisco
regionstringState or province.California
postal_codePIIstringPostal / ZIP code.94105
countrystringCountry display name.United States
country_codestringISO 3166-1 alpha-2 country code.US
latitudePIInumberGeo latitude.37.7749
longitudePIInumberGeo longitude.-122.4194
timezonestringIANA timezone.America/Los_Angeles
localestringLocale or language.en-US
created_atdateWhen the user account was created.2026-01-15
last_seen_atdateMost recent activity timestamp.2026-06-01
planstringSubscription plan or tier.pro
subscription_statusstringBilling/subscription status.active
lifecycle_stagestringMerchant-defined relationship/funnel stage for this user (e.g. lead, trial, active, churned). Maps to the contact's lifecycle field on a verified identify (last-write-wins).active
trial_ends_atdateWhen the user's trial expires.2026-07-01
lifetime_valuenumberTotal revenue from this user.480
marketing_opt_inbooleanMarketing email consent.true
referrerstringAcquisition referrer.google
utm_sourcestringAcquisition UTM source.newsletter
utm_mediumstringAcquisition UTM medium.email
utm_campaignstringAcquisition UTM campaign.spring_launch
utm_termstringAcquisition UTM term.
utm_contentstringAcquisition UTM content.
marketplace_sidestringWhich side(s) of the marketplace this user is on: buyer, seller, or both.seller
is_sellerbooleanTrue when the user sells on the marketplace.true
is_buyerbooleanTrue when the user buys on the marketplace.true
store_namestringThe seller's storefront display name.Atlas Outfitters
seller_idstringThe marketplace's stable seller identifier.sel_4821
payout_methodstringHow the seller receives payouts. One of: stripe, paypal, bank_transfer, other — never account details.stripe

account

FieldTypeDescriptionExample
idstringStable account / org id.acct_42
namestringAccount or company name.Atlas Inc
websiteurlAccount website.https://atlas.example.com
domainstringEmail/company domain.atlas.example.com
planstringAccount plan or tier.enterprise
mrrnumberMonthly recurring revenue.2400
arrnumberAnnual recurring revenue.28800
seat_countnumberNumber of licensed seats.25
employee_countnumberCompany headcount.120
industrystringIndustry or vertical.SaaS
countrystringAccount country.United States
created_atdateWhen the account was created.2025-11-02
trial_ends_atdateWhen the account trial expires.2026-07-01
renewal_datedateNext renewal date.2027-01-01
owner_emailPIIemailAccount owner email.owner@atlas.example.com

order

FieldTypeDescriptionExample
idstringOrder id or number.ord_1009
totalnumberOrder grand total.129.99
subtotalnumberOrder subtotal before tax/shipping.119.99
taxnumberTax amount.10.00
shippingnumberShipping cost.5.00
discountnumberDiscount amount applied.15.00
costnumberOrder-level cost of goods (COGS) — optional. Send when you know the order's total cost but not per-item cost. Apex computes gross profit = net revenue − cost. Opt-in; never inferred.62.00
currencystringISO 4217 currency code.USD
statusstringOrder / fulfillment status.shipped
item_countnumberNumber of line items.3
coupon_codestringCoupon / promo code used.SPRING20
payment_methodstringPayment method.card
created_atdateWhen the order was placed.2026-05-20

product

FieldTypeDescriptionExample
idstringProduct id.prod_77
namestringProduct name.Atlas Trail Runner
skustringStock-keeping unit.ATR-42
brandstringBrand or vendor.Atlas
pricenumberUnit price.129.99
unit_costnumberPer-unit cost of goods (COGS) — optional. When sent on purchase line items, Apex computes true gross profit (net revenue − cost × quantity) and unlocks exact gross-profit LTV:CAC. Opt-in; never inferred or defaulted.48.50
currencystringISO 4217 currency code.USD
categorystringProduct category.footwear
variantstringVariant / option.size-10
quantitynumberQuantity.1
image_urlurlProduct image URL.
product_urlurlProduct page URL.

Extend + build on the Spec

The Spec is the global contract — but you can extend it, get type-safe SDKs from it, and rely on it to validate your data.

Define your own events

When your business has an event the Spec doesn't cover, govern it: Settings → Workspace → Schema → Custom events, or ask your agent (the define_event MCP tool). A governed event is typed and versioned (SchemaVer model-revision-addition), behaves like a canonical event (trigger/goal-selectable, token-resolvable, validated at ingest), and can be scoped to one workspace or shared across your org. A custom name can never shadow a canonical Spec event.

Type-safe tracking

The TypeScript SDK ships a generated payload map so wrong payloads fail to compile:

import type { ApexEventPayloads } from "@apex-inc/sdk/generated/event-payloads";

const order: ApexEventPayloads["order_placed"] = {
  order_id: "ord_123",
  value: 129.99,      // required — the money-truth lane needs the amount
  currency: "USD",
};

Validation rules

Spec fields can declare constraints — allowed-value enums, regex patterns, numeric bounds, and formats (e.g. currency must be ISO-4217). At ingest, payloads that violate a constraint are quarantined (or rejected in strict mode), so bad data is caught at the door instead of corrupting reports downstream.

Already firing events with different names? Map them to canonical in your workspace \u2014 every Apex surface picks up the alias automatically.