Stitchflow
Iterable logo

Iterable User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 11, 2026

Summary and recommendation

Iterable's REST API (base URL: https://api.iterable.com/api) authenticates via API key passed as the `Api-Key` HTTP header. Keys are project-scoped - a key issued in one Iterable project cannot read or write data in another. The API supports user profile upserts, bulk updates, list subscription management, event tracking, and permanent deletion.

There is no SCIM endpoint; automated provisioning and deprovisioning require direct REST integration. When building an identity graph across systems, Iterable's dual-identifier model (email as default primary key, with optional `userId` via `preferUserId=true`) must be handled consistently across every call - mixing identifier strategies across requests will produce split profiles.

API quick reference

Has user APIYes
Auth methodAPI Key (passed as header: Api-Key)
Base URLOfficial docs
SCIM availableNo
SCIM plan requiredEnterprise

Authentication

Auth method: API Key (passed as header: Api-Key)

Setup steps

  1. Log in to Iterable and navigate to Integrations > API Keys.
  2. Click 'New API Key' and select the appropriate key type (Standard, Server-side, Mobile, or Web).
  3. Assign the required permissions/scopes to the key.
  4. Copy the generated API key value.
  5. Include the key in all requests via the HTTP header: Api-Key: <your_api_key>.

Required scopes

Scope Description Required for
users.read Read user profile data GET /users/getByEmail, GET /users/{id}
users.write Create or update user profiles POST /users/update, POST /users/bulkUpdate
users.delete Delete user profiles DELETE /users/{email}
lists.read Read static list membership GET /lists/getUsers
lists.write Subscribe/unsubscribe users to/from lists POST /lists/subscribe, POST /lists/unsubscribe
events.write Track custom events for users POST /events/track

User object / data model

Field Type Description On create On update Notes
email string Primary identifier for the user profile required required (or userId) Case-insensitive; used as the default user identifier
userId string Optional external user ID; can be used as an alternate identifier optional optional If provided, can be used instead of email in some endpoints
dataFields object Key-value map of custom profile attributes (e.g., firstName, lastName, plan, etc.) optional optional Merged with existing dataFields by default; use mergeNestedObjects flag to control nested merging
preferUserId boolean If true, Iterable uses userId as the primary identifier instead of email optional optional Relevant when userId is set and email may change
mergeNestedObjects boolean Controls whether nested objects in dataFields are merged or replaced optional optional Default is false (replace nested objects)
emailListIds array List IDs to subscribe the user to on update optional optional Used in /users/update to manage list subscriptions inline
unsubscribedChannelIds array Channel IDs from which the user is unsubscribed optional optional Manages channel-level suppression
unsubscribedMessageTypeIds array Message type IDs from which the user is unsubscribed optional optional Manages message-type-level suppression
subscribedMessageTypeIds array Message type IDs to which the user is explicitly subscribed optional optional Used for opt-in message types
profileUpdatedAt string (ISO 8601) Timestamp of last profile update system-set system-set Read-only; set by Iterable
signupDate string (ISO 8601) Date the user signed up; stored in dataFields by convention optional optional Custom dataField; not a reserved system field

Core endpoints

Create or update a user

  • Method: POST
  • URL: https://api.iterable.com/api/users/update
  • Watch out for: Upserts by default - creates the user if they do not exist. Does not return the full user object.

Request example

POST /api/users/update
{
  "email": "user@example.com",
  "dataFields": {
    "firstName": "Jane",
    "plan": "pro"
  }
}

Response example

{
  "msg": "User updated",
  "code": "Success",
  "params": {}
}

Bulk create or update users

  • Method: POST
  • URL: https://api.iterable.com/api/users/bulkUpdate
  • Watch out for: Maximum 1,000 users per request. Partial failures are not surfaced per-record in the response.

Request example

POST /api/users/bulkUpdate
{
  "users": [
    {"email": "a@example.com", "dataFields": {"plan": "free"}},
    {"email": "b@example.com", "dataFields": {"plan": "pro"}}
  ]
}

Response example

{
  "msg": "Users updated",
  "code": "Success",
  "params": {}
}

Get user by email

  • Method: GET
  • URL: https://api.iterable.com/api/users/{email}
  • Watch out for: Email must be URL-encoded. Returns 404 if user does not exist.

Request example

GET /api/users/user@example.com

Response example

{
  "user": {
    "email": "user@example.com",
    "userId": "u_123",
    "dataFields": {"firstName": "Jane"},
    "profileUpdatedAt": "2024-01-15T10:00:00Z"
  }
}

Get user by userId

  • Method: GET
  • URL: https://api.iterable.com/api/users/byUserId/{userId}
  • Watch out for: Only works if userId was set on the profile. Returns 404 if not found.

Request example

GET /api/users/byUserId/u_123

Response example

{
  "user": {
    "email": "user@example.com",
    "userId": "u_123",
    "dataFields": {}
  }
}

Delete user by email

  • Method: DELETE
  • URL: https://api.iterable.com/api/users/{email}
  • Watch out for: Permanently deletes the user profile and all associated data. Irreversible.

Request example

DELETE /api/users/user@example.com

Response example

{
  "msg": "User deleted",
  "code": "Success",
  "params": {}
}

Update user email address

  • Method: POST
  • URL: https://api.iterable.com/api/users/updateEmail
  • Watch out for: The old email address is retired; all profile data and history migrate to the new email.

Request example

POST /api/users/updateEmail
{
  "currentEmail": "old@example.com",
  "newEmail": "new@example.com"
}

Response example

{
  "msg": "Email updated",
  "code": "Success",
  "params": {}
}

Subscribe users to a list

  • Method: POST
  • URL: https://api.iterable.com/api/lists/subscribe
  • Watch out for: Maximum 1,000 subscribers per request. Users are created if they do not already exist.

Request example

POST /api/lists/subscribe
{
  "listId": 12345,
  "subscribers": [
    {"email": "user@example.com"}
  ]
}

Response example

{
  "successCount": 1,
  "failCount": 0,
  "invalidEmails": []
}

Get users in a list

  • Method: GET
  • URL: https://api.iterable.com/api/lists/getUsers
  • Watch out for: Returns only email addresses, not full profile data. For large lists, use the Data Export API instead.

Request example

GET /api/lists/getUsers?listId=12345

Response example

{
  "getUsers": {
    "listId": 12345,
    "emails": ["user@example.com", "other@example.com"]
  }
}

Rate limits, pagination, and events

  • Rate limits: Rate limits are enforced per API key per endpoint category. Limits vary by endpoint type. Exceeding limits returns HTTP 429.
  • Rate-limit headers: Yes
  • Retry-After header: Yes
  • Rate-limit notes: HTTP 429 is returned when limits are exceeded. Iterable recommends exponential backoff. Bulk endpoints (e.g., /users/bulkUpdate) accept up to 1,000 records per call and are preferred over looping single-user calls.
  • Pagination method: token
  • Default page size: 0
  • Max page size: 0
  • Pagination pointer: startDateTime / endDateTime for export endpoints; /lists/getUsers returns all users in a list without pagination (use export API for large sets)
Plan Limit Concurrent
Standard (all plans) 500 requests/second for /users/update; 100 requests/second for most other endpoints 0
Bulk endpoints Up to 1,000 users per bulk request; overall throughput subject to account-level limits 0
  • Webhooks available: Yes
  • Webhook notes: Iterable supports outbound webhooks (called 'Webhooks' in the platform) that fire on messaging events such as email sends, opens, clicks, bounces, and unsubscribes. These are configured in Integrations > Webhooks.
  • Alternative event strategy: Iterable also supports a Data Export API (CSV/JSON streaming) for bulk historical event and user data retrieval.
  • Webhook events: emailSend, emailOpen, emailClick, emailBounce, emailUnsubscribe, emailComplaint, smsSend, smsReceived, pushSend, pushOpen, inAppSend, inAppOpen, inAppClick, customEvent

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: Enterprise
  • Endpoint: Not documented

Limitations:

  • Iterable does not support SCIM provisioning as of the current documentation.
  • SAML SSO with Just-in-Time (JIT) provisioning is available on Enterprise plans.
  • User provisioning must be handled via the REST API or manual invitation.

Common scenarios

Three integration patterns cover the majority of lifecycle automation use cases.

First, provisioning: POST /api/users/update (upsert) to create or update a profile, then POST /api/lists/subscribe to add the user to the relevant onboarding segment, and optionally POST /api/events/track to fire a custom event for journey triggering.

Second, bulk CRM sync: batch records into groups of up to 1,000 and POST /api/users/bulkUpdate per batch; note that bulk responses do not surface per-record failure details, so request payloads should be logged independently for reconciliation.

Third, GDPR deletion: confirm the profile exists via GET /api/users/{email} (URL-encode the address), then DELETE /api/users/{email} - this is permanent, removes all historical event data, and cannot be undone.

Rate limits are enforced per API key: 500 req/s on /users/update, 100 req/s on most other endpoints; HTTP 429 responses should trigger exponential backoff.

Provision a new user and subscribe to onboarding list

  1. POST /api/users/update with email, userId, and relevant dataFields (e.g., firstName, plan, signupDate).
  2. POST /api/lists/subscribe with the onboarding listId and the user's email to add them to the onboarding segment.
  3. Optionally POST /api/events/track to record a 'userSignedUp' custom event for journey triggering.

Watch out for: /users/update is an upsert; if the email already exists, the profile will be updated, not duplicated. Ensure dataFields are correct before calling.

Update user profile attributes in bulk after CRM sync

  1. Batch updated user records into groups of up to 1,000.
  2. POST /api/users/bulkUpdate for each batch with the email and changed dataFields.
  3. Monitor response for 'code: Success'; implement exponential backoff on HTTP 429 responses.

Watch out for: bulkUpdate does not return per-record success/failure details. Log request payloads to diagnose issues if counts don't match expectations.

Deprovision a user (GDPR deletion)

  1. Confirm the user's email address via GET /api/users/{email} to verify the profile exists.
  2. DELETE /api/users/{email} to permanently remove the user profile and all associated event data.
  3. If the user has a userId alias, also call DELETE /api/users/byUserId/{userId} if needed (verify current API docs - deletion by email removes all aliases).

Watch out for: Deletion is irreversible and removes all historical event data for the user. There is no soft-delete or archive option. Confirm compliance requirements before executing.

Why building this yourself is a trap

The upsert behavior of POST /api/users/update is the most common source of unintended data side effects: any call with a new email address silently creates a profile, which can inflate contact counts and trigger unwanted journey enrollments.

The /lists/getUsers endpoint returns only email addresses - not full profile data - so any integration that needs complete user records must route through the Data Export API instead, which is a meaningfully different operational pattern.

Deleting a user by email removes all aliases and all associated event history with no soft-delete or archive option; this is irreversible and should be gated behind a confirmation step in any automated workflow.

Finally, because Iterable has no SCIM, any identity graph that relies on IdP deprovisioning signals to cascade access removal will have a gap at the Iterable layer - REST API calls for deletion must be explicitly orchestrated.

Automate Iterable workflows without one-off scripts

Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 11, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste