Personyze Personyze developer docs
Open Personyze
Guides

Building an integration

How to connect another system to Personyze, and what will surprise you if you don't read this first.

Personyze developer documentation Questions: support@personyze.com

This is the orientation guide for connecting another system to Personyze — a CRM, an e-commerce platform, a data warehouse, a marketing tool, or an app you are publishing on someone else's marketplace. It explains which endpoint does what, and the handful of behaviours that will otherwise surprise you.

If you just want the endpoint reference, start at the REST API overview. If you want Personyze to make personalization decisions inside your own server code, see server-side personalization and A/B testing.

What integrations actually do

Nearly every integration is some combination of four jobs. Pick the ones you need:

Job Direction Endpoint
Push people into Personyze so campaigns can target them in users
Group those people into segments in user_lists, user_list_users
Report what they bought or viewed, so recommendations learn in products_interactions
Pull results and captured data back out out summary_actions, forms, sessions_archive, user_interests

1. Authentication

HTTP Basic over HTTPS, username api, password an API key. Nothing else — no tokens to refresh, no signing.

If your integration connects on behalf of customers, collect the key from each customer and validate it once with GET /rest/account, which returns {"id": …} and touches nothing. Store keys encrypted; a Personyze key can delete data.

2. Identity is the whole game

Personyze identifies a person by user_id (its own), email, fb_id, and internal_id (yours). Getting this right is the difference between a working integration and a database full of duplicates.

Note on internal_id (current behaviour). On the users object, internal_id is stored and returned, but it does not work as a lookup key: where/internal_id=... matches nothing, a POST carrying an internal_id does not merge into an existing profile (it creates a second one), and requesting internal_id in an explicit columns list returns null. Use email (or the Personyze user_id) as your key. This affects users, zapier_users and user_list_users only — on products and articles, internal_id behaves normally.

In practice: key your integration on email. Store your own id in internal_id if it is useful to have in the record, but do not rely on it to find, update or de-duplicate anyone.

Posting a user merges rather than duplicates — on email. If an incoming record matches an existing profile on email (or fb_id), the two are merged:

curl --data '{"internal_id": "crm-4471", "email": "john@example.com", "first_name": "John"}' 'https://api:YOUR_KEY@app.personyze.com/rest/users'

Two consequences worth designing around:

  • Re-sending is safe, as long as email is present. You do not need to check whether a user exists first, and a retry after a timeout will not create a second profile. Sync loops can be dumb and still be correct.
  • Always include email. It is the identifier that actually matches. A record posted without it — keyed only on your own internal_id — creates a new profile every run.
  • A changed email address creates a new profile. Since internal_id does not match, there is currently no way to follow a person across an email change over the API. If that matters, keep your own mapping of internal_id to the Personyze user_id returned by the first POST, and update by user_id afterwards.

Set custom fields by just sending them — profiles have no fixed schema. To find out which custom fields a given account already has (for a field-mapping UI, say), read users_columns.

3. Writing data

  • POST inserts, and merges when email or fb_id matches an existing record. It returns the record's id.
  • PUT updates everything matched by the path parameters, and returns how many rows changed.
  • DELETE likewise, and is permanent — there is no recycle bin for users.

Always address updates and deletes with an explicit condition:

curl -X PUT --data '{"phone": "202-555-0152"}' 'https://api:YOUR_KEY@app.personyze.com/rest/users/where/email=john@example.com'

A returned 0 means your condition matched nothing — usually a sign the identifier is wrong, not that the write failed.

4. Reading data

Every object accepts the same path parameter syntax for filtering, sorting, column selection and paging. Two limits shape how you read:

  • 1000 rows maximum per request. Page with /limit/{OFFSET},{LIMIT}.
  • Big tables must be queried by an index. Filtering users by email is fast; filtering by first name is a full scan and will be refused or truncated to the first 50 rows. The error message names the columns that are indexed. See errors and limits.

For incremental sync, page by a timestamp rather than by offset. Remember the highest value you imported and ask for everything after it:

curl 'https://api:YOUR_KEY@app.personyze.com/rest/users/where/data_last_modified>1769904000/order_by/data_last_modified/limit/1000'

data_last_modified is maintained automatically on every user profile change, and it is indexed. Offset paging over a table that is being written to will skip and repeat rows; timestamp paging will not.

5. Handling failures

  • 400 means your request is wrong — the body says how. Do not retry it unchanged; surface the message to whoever configured the integration, because it is usually a mapping mistake.
  • 401 means the key is wrong, revoked, or you used plain HTTP. Mark the connection as broken and ask the customer to reconnect.
  • 503, and 500 on writes, are worth retrying with exponential backoff.
  • 400 Too many simultaneous requests means you are writing users faster than the account allows. Serialize your writes and back off — do not widen your concurrency.

Error bodies are plain text, not JSON. A client that assumes JSON on every response will throw a parse error and hide the real message.

6. Before you ship

  • Re-run your full sync twice and confirm the user count doesn't double. If it does, you are keying on internal_id rather than email.
  • Confirm a deleted-then-recreated record behaves the way your customers expect.
  • Confirm you handle a revoked key without silently dropping data.
  • Confirm you page past 1000 rows.
  • Confirm you never log the API key.

Worked examples

Getting help

Write to support@personyze.com with the endpoint, the request body and the response you got back. If you are building a public integration and want us to review it before launch, say so — we would rather look early.