Per-object reference for every Personyze REST API endpoint: users, user lists, products, articles, actions, placeholders, interactions, events, forms, sessions archive, user interests, daily summaries, and more. Column lists, method support,…
Updated 8 hours ago22 min read
A
by Admin
Reference for every object exposed by the Personyze REST API. Each section below covers one object: its purpose, supported HTTP methods, columns (with type and indexing notes), and copy-paste-ready curl examples.
Used by the JS tracker, native SDKs, and integrations to self-bootstrap. Not usually called by REST API consumers directly.
tracker_codeReturns the JS snippet to embed in a customer page (HTML output).
users
Customer profiles. Each row is one visitor or customer. Column names are dynamic — beyond the documented housekeeping columns, you can store any custom keys/values your account needs.
GET
POST
PUT
DELETE
✅
✅
✅
✅
Identifying / housekeeping columns
Column
Notes
user_id
Personyze internal primary key. Auto-assigned on insert. Indexed.
internal_id
Your external identifier (CRM ID, account ID, SKU). Indexed.
fb_id
Facebook user ID. Indexed.
email
Visitor email. Indexed.
last_session_time
Unix seconds. Indexed.
data_last_modified
Unix seconds. Indexed.
session_counter
Total sessions seen so far for this user.
Common profile fields (custom)
first_name, middle_name, last_name, sex, birthday, timezone, current_city, current_state, current_country, religion, political, interests, relationship_status, education_year, plus custom_t_1…custom_t_6 (text), custom_i_1…custom_i_4 (integer), custom_f_1…custom_f_2 (float), custom_d_1, custom_d_2 (date) — and any additional fields you’ve configured on your account.
Examples
# Lookup by your external id
curl 'https://api:KEY@app.personyze.com/rest/users/where/internal_id=42'
GET /rest/users without a where requires order_by on an indexed column — user_id, last_session_time, data_last_modified, fb_id, email, or internal_id. Otherwise: 400 Cannot do this operation on whole table.
Throttling
POST /rest/users is serialized per Personyze account: at most one in-flight insert at a time. Requests that wait more than 1 second are rejected with 400 Too many simultaneous requests — retry with exponential backoff.
user_lists
Named lists of users (e.g. “VIPs”, “Newsletter opt-ins”). One row per list. Membership lives in a separate object — see user_list_users.
GET
POST
PUT
DELETE
✅
✅
✅
✅
Columns
Column
Notes
id
Primary key. Auto-assigned.
name
List display name. Indexed.
Examples
# All lists
curl 'https://api:KEY@app.personyze.com/rest/user_lists'
# Delete (also clears all memberships in user_list_users via FK cascade)
curl -X DELETE 'https://api:KEY@app.personyze.com/rest/user_lists/17'
# → 1
user_list_users
Membership: which users belong to which user_lists. One row per (user_list_id, user_id) pair.
GET
POST
PUT
DELETE
✅
✅
—
✅
POST accepts either an existing user_id, or a lookup key (user_internal_id, user_email) — the API resolves it to a user_id, creating a stub users row if needed.
Columns
Column
Notes
user_list_id
FK → user_lists.id. Composite-key part.
user_id
FK → users.user_id. Composite-key part.
POST body extras (resolved to user_id server-side, then dropped)
Field
Resolves to
user_internal_id
user_id for the user with that internal_id. Creates the user if missing.
user_email
user_id for the user with that email. Creates the user if missing.
Examples
# Members of list 17
curl 'https://api:KEY@app.personyze.com/rest/user_list_users/where/user_list_id=17/limit/1000'
# Add by user_id
curl -X POST 'https://api:KEY@app.personyze.com/rest/user_list_users' \
-H 'Content-Type: application/json' \
-d '{"user_list_id":17,"user_id":5712334}'
# Add by external id (auto-creates a users row if needed)
curl -X POST 'https://api:KEY@app.personyze.com/rest/user_list_users' \
-H 'Content-Type: application/json' \
-d '{"user_list_id":17,"user_internal_id":"acct-987"}'
# Add by email
curl -X POST 'https://api:KEY@app.personyze.com/rest/user_list_users' \
-H 'Content-Type: application/json' \
-d '{"user_list_id":17,"user_email":"alice@example.com"}'
Personalization actions — what your campaigns do: render HTML, show a popup, send an email, push a notification, etc. Read-only over REST today (create/edit through the GUI).
GET
POST
PUT
DELETE
✅
—
—
—
Columns
Column
Notes
id
Primary key.
version_tag
production or testing.
name
Action display name.
type_id
The action type (HTML / popup / email / push / …). Resolved from the underlying action_js_id.
placeholders
JSON array of placeholder IDs the action targets.
content_type
Mime / kind of content (from actions_js).
content_param
Name of the JS-param key whose value is the renderable content.
content_begin
Computed: opening fragment of the rendered content (after wrapper substitution).
content_end
Computed: closing fragment.
presenting_rules
JSON: timing / frequency rules.
libs_app
App libraries the action depends on.
Examples
# All production actions
curl 'https://api:KEY@app.personyze.com/rest/actions
/where/version_tag=production
/columns/id,name,type_id,placeholders'
# One action's full content
curl 'https://api:KEY@app.personyze.com/rest/actions/where/id=42
/columns/id,name,content_type,content_param,content_begin,content_end'
conditions
Audience conditions — the when of campaigns. Read-only over REST.
GET
POST
PUT
DELETE
✅
—
—
—
Columns
Column
Notes
id
Primary key.
name
Condition display name.
Examples
# All tracker/offline conditions
curl 'https://api:KEY@app.personyze.com/rest/conditions/limit/1000'
placeholders
Containers of type placeholder — DOM slots where actions render content. Manage the catalog of placeholders defined for your site.
GET
POST
PUT
DELETE
✅
✅
✅
✅
Columns
Column
Notes
id
Primary key.
name
Display name.
html_id
DOM selector / id where the placeholder mounts.
units_count_max
Max number of action-units that can fill this placeholder. Default 1.
Examples
# All placeholders
curl 'https://api:KEY@app.personyze.com/rest/placeholders'
# One
curl 'https://api:KEY@app.personyze.com/rest/placeholders/14'
Endpoint scope.The handler scopes all queries to container_types='placeholder', so other container types (e.g. “grab variable”) aren’t visible from this endpoint — see containers_grab_variable.
containers_grab_variable
“Grab variable” containers — pull DOM/JS values from the visitor’s page back into the visitor profile. Each container says “watch this variable / DOM element; when it appears, capture it as a profile field.”
GET
POST
PUT
DELETE
✅
✅
✅
✅
Columns
Column
Notes
id
Primary key.
name
Display name.
is_active
1 / 0.
variable_path
DOM path or JS expression to grab.
mask
Optional regex/template applied to the grabbed string.
constant_value
Optional fallback / forced value.
watch_variable
Re-grab whenever the variable changes (1 / 0).
profile_column
Profile column the value is written to.
Examples
# All grab-variable containers
curl 'https://api:KEY@app.personyze.com/rest/containers_grab_variable'
Product catalog. Each row is one SKU. Column names are dynamic — beyond the documented housekeeping columns, you can store any custom fields your catalog needs.
GET
POST
PUT
DELETE
✅
✅
✅
✅
Identifying / housekeeping columns
Column
Notes
id
Primary key. Auto-assigned.
internal_id
Your SKU / external identifier.
data_last_modified
Unix seconds.
is_in_stock
'yes' / 'no' enum (not 1/0).
Common product fields (custom)
title, description_short, description_long, price, sale_price, image_big_url, image_medium_url, image_small_url, cart_url, brand, manufacturer, category, inventory, expiration_date, size, color, rank, is_new, age_from, age_to, available_location, not_available_location, etc. The actual field set depends on your account configuration.
Renamed inputs (on POST / PUT)
Input
Stored as
image_1
image_big_url
image_2
image_medium_url
image_3
image_small_url
Examples
# In-stock products in a category
curl 'https://api:KEY@app.personyze.com/rest/products
/where/category=tools&is_in_stock=yes
/columns/id,internal_id,title,price,inventory
/order_by/title
/limit/100'
# Lookup by internal_id
curl 'https://api:KEY@app.personyze.com/rest/products/where/internal_id=SKU-1234'
# Insert (or "patch" — duplicate internal_id will UPDATE rather than fail)
curl -X POST 'https://api:KEY@app.personyze.com/rest/products' \
-H 'Content-Type: application/json' \
-d '{"internal_id":"SKU-1234",
"title":"Cordless Drill",
"price":129.99,
"is_in_stock":"yes",
"image_1":"https://cdn.example.com/big.jpg"}'
# → 51234
# Update by internal_id
curl -X PUT 'https://api:KEY@app.personyze.com/rest/products/where/internal_id=SKU-1234' \
-H 'Content-Type: application/json' \
-d '{"price":119.99,"is_in_stock":"no"}'
Upsert behavior on POST.POST does patch-on-duplicate: an existing internal_id updates the row instead of failing. For bulk import from a feed URL, use scheduled feed sync via the Personyze GUI rather than per-row REST calls.
articles
Article catalog (blog posts, news, knowledge-base entries). Same shape as products but for editorial content.
GET
POST
PUT
DELETE
✅
✅
✅
✅
Identifying / housekeeping columns
Column
Notes
id
Primary key. Auto-assigned.
internal_id
Your external identifier (slug, CMS id).
data_last_modified
Unix seconds.
is_published
'yes' / 'no' enum.
Common article fields (custom)
title, description_short, description_long, image_big_url, image_medium_url, image_small_url, author, publish_date, category, tags, rank, etc. The actual list depends on your site’s other_columns_info config.
Renamed inputs
Input
Stored as
image_1
image_big_url
image_2
image_medium_url
image_3
image_small_url
Examples
# Recent published articles
curl 'https://api:KEY@app.personyze.com/rest/articles
/where/is_published=yes
/columns/id,internal_id,title,author,publish_date
/order_by_desc/publish_date
/limit/100'
# Lookup by internal_id
curl 'https://api:KEY@app.personyze.com/rest/articles/where/internal_id=how-to-personalize'
# Insert
curl -X POST 'https://api:KEY@app.personyze.com/rest/articles' \
-H 'Content-Type: application/json' \
-d '{"internal_id":"how-to-personalize",
"title":"How to personalize your site",
"author":"Alice",
"is_published":"yes",
"image_1":"https://cdn.example.com/big.jpg"}'
Article interactions live on the do endpoint.POST does patch-on-duplicate (same as products). For tracking visitor interactions on articles (viewed / commented / liked), use do with the Article … commands — there’s no dedicated REST object today.
products_interactions
Log of interactions on products: views, adds-to-cart, purchases, “favorite,” “delivered.” Append-mostly. Backed by an archive table.
GET
POST
PUT
DELETE
✅
✅
✅
✅
Columns
Column
Notes
user_id
FK → users.user_id. Indexed.
product_internal_id
FK → products.internal_id. Leading column of a composite index [product_internal_id, user_id, transaction_time].
quantity
Default 1 on insert.
status
One of viewed, delivered, extra (≈ added-to-cart), favorite, goal (purchase). Indexed.
action_id
If the interaction was attributed to a Personyze action, its ID. Otherwise null.
transaction_time
Unix seconds — order/transaction time.
time
Unix seconds — when the row was logged. Indexed.
amount
Monetary value (per the site’s currency settings).
Insert: identifying the user
POST accepts any one of these to identify the user:
Field
Resolves to
user_id (numeric)
Direct PK lookup.
user_internal_id
user_id of the user with that internal_id. Auto-creates a stub users row if missing.
user_email
user_id of the user with that email. Auto-creates if missing.
Examples
# All purchases in a window, paged
curl 'https://api:KEY@app.personyze.com/rest/products_interactions
/where/status=goal&time>1730000000
/order_by_desc/time
/limit/1000'
# A specific user's history with a product
curl 'https://api:KEY@app.personyze.com/rest/products_interactions
/where/product_internal_id=SKU-1234
/columns/user_id,status,quantity,amount,transaction_time'
# Log a purchase
curl -X POST 'https://api:KEY@app.personyze.com/rest/products_interactions' \
-H 'Content-Type: application/json' \
-d '{"user_internal_id":"acct-987",
"product_internal_id":"SKU-1234",
"quantity":2,
"status":"goal",
"transaction_time":1734000000,
"amount":259.98}'
# Delete by composite key
curl -X DELETE 'https://api:KEY@app.personyze.com/rest/products_interactions
/where/user_id=5712334&product_internal_id=SKU-1234&status=viewed'
Indexed columns
user_id, [product_internal_id, user_id, transaction_time], status, time. Queries without a where on one of these (or order_by on the same) are rejected as full-table scans.
events
Generic event log — one row per tracked event captured by the JS tracker, SDK, or do endpoint. Read-only over REST today.
GET
POST
PUT
DELETE
✅
—
—
—
Columns
Column
Notes
id
Primary key.
user_id
FK → users.user_id. Indexed.
time
Unix seconds.
visit_id
FK → visit row.
container_id
FK → containers.id (the source of the event). Indexed.
container_types
The container’s type (click event, submit event, etc.).
value
Event payload string.
first_visit_id
First visit_id of the session.
session_start_time
Unix seconds.
Examples
# Recent events for a user
curl 'https://api:KEY@app.personyze.com/rest/events
/where/user_id=5712334
/order_by_desc/time
/limit/100'
# Events from a specific container in a window
curl 'https://api:KEY@app.personyze.com/rest/events
/where/container_id=1234&time>1730000000&time<1731000000
/columns/id,user_id,time,value
/order_by_desc/time
/limit/1000'
When to use events vs. summary_actions.The table is large; queries must filter on an indexed column (id, user_id, container_id, …) or the request is rejected. For aggregated KPIs over time, use summary_actions instead — it has pre-computed daily counters per action.
forms
Form-submission log. One row per form-submit event captured by the tracker. Read-only over REST today.
GET
POST
PUT
DELETE
✅
—
—
—
Columns
Column
Notes
user_id
FK → users.user_id. Indexed.
time
Unix seconds.
action_id
Personyze action that triggered/owned this form, if any.
session_start_time
Unix seconds.
plus data (JSON)
The submitted form payload, packed as JSON. Read inline (its keys appear as columns in the response).
The data JSON is automatically expanded into top-level keys on read — request specific custom fields by name.
Examples
# Submissions for a user
curl 'https://api:KEY@app.personyze.com/rest/forms
/where/user_id=5712334
/order_by_desc/time
/limit/100'
# Submissions tied to a specific action
curl 'https://api:KEY@app.personyze.com/rest/forms
/where/action_id=42&time>1730000000
/columns/user_id,time,email,name,message
/limit/1000'
Indexed columns include user_id, action_id, and time. Queries must filter on one of these.
do
Fire-and-forget command dispatcher: send a single user-profile update or interaction event without speaking the tracker protocol. The body is an array of commands; each is dispatched independently.
# Tag a user as VIP
curl -X POST 'https://api:KEY@app.personyze.com/rest/do' \
-H 'Content-Type: application/json' \
-d '[["internal_id","acct-987","User profile","custom_t_1","VIP","first_name","Alice"]]'
# Log a purchase + a profile update in one round-trip
curl -X POST 'https://api:KEY@app.personyze.com/rest/do' \
-H 'Content-Type: application/json' \
-d '[
["email","alice@example.com","Product purchased","SKU-1234","quantity",2,"amount",259.98],
["email","alice@example.com","User profile","customer_segment","loyal"]
]'
When to use do vs. typed endpoints.Lookup keys (internal_id / email) auto-create a stub users row if no user matches. For high-throughput interaction logging, prefer products_interactions (typed and indexed) or the SDK’s batched event API.
sessions_archive
One row per visitor session (a contiguous window of activity). Backed by the long-lived archive table — much wider than events, with location, device, screen, and browser metadata.
GET
POST
PUT
DELETE
✅
—
—
—
Identifying / housekeeping
Column
Notes
first_visit_id
Primary key. The id of the first visit row in this session.
user_id
FK → users.user_id. Indexed.
session_start_time
Unix seconds.
last_session_time
Unix seconds.
session_counter
Which session number for this user (1, 2, 3, …).
total_visits
Pages viewed in the session.
time_in_focus
Seconds the tab was actually focused.
time_total
Seconds from start to last activity.
Geo / locale / device
Column
Notes
time_zone
Visitor’s TZ offset (hours).
country_code, region_code, city
Geo (from IP). city is joined from the shared lookup, so it’s a human-readable name (null if no match).
ad_campaign, ad_source, ad_medium, ad_term, ad_content — the standard UTM parameters as captured on landing.
Examples
# Sessions for a user, most recent first
curl 'https://api:KEY@app.personyze.com/rest/sessions_archive
/where/user_id=5712334
/columns/first_visit_id,session_start_time,total_visits,country_code,city
/order_by_desc/session_start_time
/limit/100'
# Single session by primary key
curl 'https://api:KEY@app.personyze.com/rest/sessions_archive
/where/first_visit_id=900000000123
/columns/user_id,session_start_time,total_visits,total_goal_value'
Indexed columns: first_visit_id, user_id, plus several others. Queries must filter on an indexed column or the request is rejected as a full-table scan.
user_interests
Per-user interests, categories, tags, and family/cross/upsale tags inferred by the tracker pipeline. One row per (user_id, value, class, time). Read-only.
GET
POST
PUT
DELETE
✅
—
—
—
Columns
Column
Notes
user_id
FK → users.user_id. Indexed.
value
The interest token (e.g. category name, tag, keyword).
How many times this value was observed for the user.
time
Unix seconds — when the interest was last updated. Indexed.
Indexed columns: user_id, time. Queries must filter on an indexed column.
Examples
# All interests for one user, strongest first
curl 'https://api:KEY@app.personyze.com/rest/user_interests
/where/user_id=5712334
/columns/value,class,rank,n_times,time
/order_by_desc/rank
/limit/100'
# Only categories, recently updated
curl 'https://api:KEY@app.personyze.com/rest/user_interests
/where/user_id=5712334&class=category
/order_by_desc/time
/limit/50'
products_stats_*
Per-product aggregated interaction counters maintained by the offline summary pipeline. Six rolling windows are exposed at separate paths — pick the one that matches your reporting horizon. All share the same column shape and indices; only the time window differs.
GET
POST
PUT
DELETE
✅
—
—
—
Endpoints
Path
Window
/rest/products_stats_1day
last 1 day
/rest/products_stats_2day
last 2 days
/rest/products_stats_4day
last 4 days
/rest/products_stats_week
last 7 days
/rest/products_stats_recent
recent (rolling — pipeline-defined)
/rest/products_stats_all
lifetime
Identifying
Column
Notes
internal_id
Primary key. The product’s external identifier (catalog SKU / id you provided). Indexed.
Per-product counters (count of interactions on this product within the window)
Column
Notes
n_viewed
Number of view events. Indexed.
n_delivered
Number of recommendations delivered (shown). Indexed (composite with n_viewed).
n_extra
“Extra” interactions (e.g. add-to-cart). Indexed (composite with n_viewed).
n_favorite
Favorited / wishlisted. Indexed (composite with n_viewed).
n_goal
Goal completions (purchases). Indexed (composite with n_viewed).
Catalog-wide distribution stats
The same value on every row — describes the whole catalog within this window. For each metric M ∈ {viewed, delivered, extra, favorite, goal}:
Column
Notes
overall_n_<M>
Sum across all products.
overall_avg_<M>
Mean across all products.
overall_avg_nonzero_<M>
Mean across products that had at least one event.
percentile_<M>
This row’s percentile rank for the metric.
Last 3 goal users (most recent purchasers of this product)
internal_id, n_viewed, n_delivered, n_extra, n_favorite, n_goal, last_goal_user_id_0, last_goal_user_id_1, last_goal_user_id_2. Queries must filter on (or order_by) one of these.
Examples
# Top 50 most-viewed products this week
curl 'https://api:KEY@app.personyze.com/rest/products_stats_week
/where/n_viewed>0
/columns/internal_id,n_viewed,n_delivered,n_extra,n_goal,percentile_viewed
/order_by_desc/n_viewed
/limit/50'
# Lookup one product's lifetime stats
curl 'https://api:KEY@app.personyze.com/rest/products_stats_all
/where/internal_id=SKU-12345'
# What a specific user purchased recently (matches against last 3 goal users)
curl 'https://api:KEY@app.personyze.com/rest/products_stats_recent
/where/last_goal_user_id_0=5712334
/columns/internal_id,n_goal,last_goal_user_time_0'
summary_actions
Daily aggregated KPIs per action — one row per (day, action_id) for actions bound to a specific campaign (condition_id). Read-only.
GET
POST
PUT
DELETE
✅
—
—
—
Strict indexing requirement.Only day is indexed. Every request must include where/day… — there’s no order_by-only escape hatch.
Identifying
Column
Notes
day
Unix timestamp (seconds) of 0:00 (12 AM) of the day on Greenwich (GMT+0000).
action_name
Action name.
action_id
Action ID.
campaign_name
Campaign name to which the action belongs.
campaign_id
Campaign ID to which the action belongs.
Action exposure
Column
Notes
n_executed
How many times executed (actions are considered executed even if the actual visual content is not yet shown).
n_delivered
How many times we received feedback from the browser page that the content became visible.
n_extra
Depends on action type. For HTML actions: number of clicks. For form actions: number of submissions.
n_failed
Only counted for email actions. How many times sending an email failed (e.g. invalid address).
n_closed
How many times the user clicked the “close” button after the action content became visible.
n_sessions_executed
In how many distinct sessions there was at least one n_executed for this action.
n_sessions_delivered
In how many distinct sessions there was at least one n_delivered.
n_sessions_extra
In how many distinct sessions there was at least one n_extra.
n_sessions_failed
In how many distinct sessions there was at least one n_failed.
n_sessions_closed
In how many distinct sessions there was at least one n_closed.
Product attribution (when this action recommended products)
Column
Notes
products_goal_n_times
How many products (across all visitors) reached “purchased” during a session in which this action was executed. Counts every product purchase event, so a single order with 3 items adds 3.
products_goal_n_sessions
In how many distinct sessions at least one product was purchased after this action was executed.
products_goal_value
Sum of monetary values of all purchased products counted in products_goal_n_times.
products_recom_viewed_n_times
How many times a product that this action recommended was subsequently viewed.
products_recom_viewed_n_sessions
In how many distinct sessions at least one recommended product was viewed.
products_recom_extra_n_times
How many times a recommended product was subsequently added to cart (or otherwise reached the “extra” interaction).
products_recom_extra_n_sessions
In how many distinct sessions at least one recommended product reached the “extra” interaction.
products_recom_extra_value
Sum of monetary values of all “extra”-interacted recommended products.
products_recom_goal_n_times
How many times a recommended product was subsequently purchased.
products_recom_goal_n_sessions
In how many distinct sessions at least one recommended product was purchased.
products_recom_goal_value
Sum of monetary values of all purchased recommended products.
Article attribution
Same shape as product attribution but for articles: articles_recom_viewed_n_times, articles_recom_viewed_n_sessions, articles_recom_extra_n_times, articles_recom_extra_n_sessions, articles_recom_extra_value, articles_recom_goal_n_times, articles_recom_goal_n_sessions, articles_recom_goal_value.
Per-account custom goal events
An account can configure up to 12 goal events. For every event container configured in your account with a non-zero goal_event_index (N from 1 to 12), four extra columns appear in the response:
goal_event_N_name — Display name of the configured goal event. Returned as a literal string, the same on every row.
goal_event_N_n_times — How many times this goal event fired during a session in which the action was executed.
goal_event_N_n_sessions — In how many distinct sessions this goal event fired at least once after the action was executed.
goal_event_N_value — Sum of monetary values reported for this goal event across the times counted in goal_event_N_n_times (zero unless the goal-event container is configured to capture a value).
Examples
# Last 30 days, daily KPIs per action
curl 'https://api:KEY@app.personyze.com/rest/summary_actions
/where/day>1730000000
/columns/day,action_name,n_executed,n_delivered,n_extra,products_goal_value
/order_by_desc/day
/limit/1000'
# A specific action's lifetime
curl 'https://api:KEY@app.personyze.com/rest/summary_actions
/where/action_id=42&day>1700000000
/order_by/day
/limit/1000'
tracker_code
Returns the JS snippet you embed in your site to bootstrap the Personyze tracker. The contents are derived from your account’s settings (account ID, tracking host, async/no-hide flags).
GET
POST
PUT
DELETE
✅
—
—
—
Response
A plain text/html (or JS-in-<script>) snippet ready to paste into a <head>. The body is not JSON — this is the one REST endpoint that returns raw HTML.
Tracker snippet conventions.The snippet bakes in your account ID and the list of allowed host names registered for that account. Don’t hand-edit it; re-fetch when you add new domains via the GUI. For native SDK clients (iOS / Android), this endpoint is not relevant — the SDK speaks the tracker protocol directly via internal endpoints.
Next steps
📖 Path Parameters SyntaxDeep dive into where/columns/order_by/limit with all operators and examples. Read →