Stitchflow
Keap logo

Keap 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

Keap exposes a REST API at `https://api.infusionsoft.com/crm/rest/v1` (legacy domain; intentional) with OAuth 2.0 authentication. User management operations - list, get, create, update, and deactivate - are available under the `/users` resource. There is no SCIM 2.0 endpoint and no SAML support; any IdP integration requires a custom REST API layer.

The only available OAuth scope is `full`, which grants broad read/write access across all resources. There is no user-management-only scope, so integrations built on this API carry elevated privilege by design. Access tokens expire after 24 hours; refresh token rotation must be handled explicitly in the integration layer.

For teams building an identity graph across SaaS tools, Keap user records expose `id`, `global_user_id`, `infusionsoft_id`, `email_address`, `admin`, `partner`, and `status` fields - sufficient to anchor a cross-system identity node, though the binary `admin` boolean is the only machine-readable role signal available via the API.

API quick reference

Has user APIYes
Auth methodOAuth 2.0
Base URLOfficial docs
SCIM availableNo

Authentication

Auth method: OAuth 2.0

Setup steps

  1. Register a developer application at https://keys.developer.keap.com/
  2. Obtain a Client ID and Client Secret from the developer console
  3. Redirect the user to https://accounts.infusionsoft.com/app/oauth/authorize with client_id, redirect_uri, response_type=code, and scope parameters
  4. Exchange the returned authorization code for an access token via POST to https://api.infusionsoft.com/token
  5. Include the access token as a Bearer token in the Authorization header for all API requests
  6. Use the refresh token to obtain new access tokens before expiry (access tokens expire in 24 hours)

Required scopes

Scope Description Required for
full Full access to all API endpoints including read and write on contacts, users, and other resources All user management operations

User object / data model

Field Type Description On create On update Notes
id integer Unique identifier for the user system-assigned read-only Used as path parameter in user-specific endpoints
given_name string User's first name required optional
family_name string User's last name required optional
email_address string Primary email address of the user required optional Must be unique within the account
global_user_id integer Global identifier across Keap accounts system-assigned read-only
infusionsoft_id string Legacy Infusionsoft username/ID system-assigned read-only Retained for backward compatibility
admin boolean Whether the user has admin privileges optional optional
partner boolean Whether the user is a partner/affiliate optional optional
status string Account status of the user (e.g., Active, Inactive) system-assigned read-only via this endpoint Activation is handled via a separate invite/activation flow
time_zone string User's time zone setting optional optional IANA time zone format
phone_number string User's phone number optional optional
website string User's website URL optional optional
job_title string User's job title optional optional
address object User's address object (line1, line2, locality, region, zip_code, country_code) optional optional

Core endpoints

List Users

  • Method: GET
  • URL: https://api.infusionsoft.com/crm/rest/v1/users
  • Watch out for: Returns only users belonging to the authenticated app's account. Pagination uses limit/offset; max limit is 1000.

Request example

GET /crm/rest/v1/users?limit=100&offset=0
Authorization: Bearer {access_token}

Response example

{
  "users": [
    {"id": 1, "given_name": "Jane", "family_name": "Doe",
     "email_address": "jane@example.com", "admin": true}
  ],
  "count": 1
}

Get User

  • Method: GET
  • URL: https://api.infusionsoft.com/crm/rest/v1/users/{userId}
  • Watch out for: Returns 404 if the userId does not belong to the authenticated account.

Request example

GET /crm/rest/v1/users/42
Authorization: Bearer {access_token}

Response example

{
  "id": 42,
  "given_name": "Jane",
  "family_name": "Doe",
  "email_address": "jane@example.com",
  "admin": true,
  "status": "Active"
}

Create User

  • Method: POST
  • URL: https://api.infusionsoft.com/crm/rest/v1/users
  • Watch out for: Creating a user triggers an invitation email to the provided email address. The user status will be 'Pending' until they accept. User seat limits apply per plan.

Request example

POST /crm/rest/v1/users
Authorization: Bearer {access_token}
Content-Type: application/json

{"given_name":"John","family_name":"Smith","email_address":"john@example.com","admin":false}

Response example

{
  "id": 99,
  "given_name": "John",
  "family_name": "Smith",
  "email_address": "john@example.com",
  "status": "Pending"
}

Update User

  • Method: PATCH
  • URL: https://api.infusionsoft.com/crm/rest/v1/users/{userId}
  • Watch out for: Partial updates are supported. Email address changes may require re-verification.

Request example

PATCH /crm/rest/v1/users/99
Authorization: Bearer {access_token}
Content-Type: application/json

{"given_name":"Jonathan","admin":true}

Response example

{
  "id": 99,
  "given_name": "Jonathan",
  "family_name": "Smith",
  "email_address": "john@example.com",
  "admin": true
}

Get Current Authenticated User

  • Method: GET
  • URL: https://api.infusionsoft.com/crm/rest/v1/oauth/connect/userinfo
  • Watch out for: Returns the user associated with the current OAuth token. Useful for identifying which user authorized the app.

Request example

GET /crm/rest/v1/oauth/connect/userinfo
Authorization: Bearer {access_token}

Response example

{
  "sub": "42",
  "email": "jane@example.com",
  "given_name": "Jane",
  "family_name": "Doe"
}

List Users (v2)

  • Method: GET
  • URL: https://api.infusionsoft.com/crm/rest/v2/users
  • Watch out for: v2 endpoints may use cursor/token-based pagination instead of offset. Check response for next_page_token. v2 is still evolving; verify endpoint availability in the official reference.

Request example

GET /crm/rest/v2/users?page_size=50
Authorization: Bearer {access_token}

Response example

{
  "users": [...],
  "next_page_token": "abc123"
}

Delete User (Deactivate)

  • Method: DELETE
  • URL: https://api.infusionsoft.com/crm/rest/v1/users/{userId}
  • Watch out for: Keap may deactivate rather than hard-delete users to preserve data integrity. Verify behavior in sandbox before production use. Not all plan tiers may expose this endpoint.

Request example

DELETE /crm/rest/v1/users/99
Authorization: Bearer {access_token}

Response example

HTTP 204 No Content

Rate limits, pagination, and events

  • Rate limits: Keap enforces rate limits per application. The documented limit is 25 requests per second per app. Burst limits may apply.
  • Rate-limit headers: Yes
  • Retry-After header: No
  • Rate-limit notes: HTTP 429 is returned when the rate limit is exceeded. Official docs recommend exponential backoff. Exact header names (e.g., X-RateLimit-Remaining) are referenced in the API but full header spec is not fully documented publicly.
  • Pagination method: offset
  • Default page size: 1000
  • Max page size: 1000
  • Pagination pointer: limit / offset
Plan Limit Concurrent
All plans 25 requests/second per application 0
  • Webhooks available: Yes
  • Webhook notes: Keap supports REST Hooks (webhook subscriptions) via the API. Hooks can be registered programmatically to receive event notifications via HTTP POST to a specified URL.
  • Alternative event strategy: Polling the /users or /contacts endpoints is an alternative for systems that cannot receive inbound webhooks. Note: user-specific webhook events (e.g., user.add) are not explicitly documented; contact-level events are the primary webhook targets.
  • Webhook events: contact.add, contact.edit, contact.delete, opportunity.add, opportunity.edit, task.add, task.edit, order.add, payment.add, invoice.paid, tag.applied, tag.removed

SCIM API status

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

Limitations:

  • Keap does not offer a native SCIM 2.0 endpoint
  • No native SAML SSO support; community requests for SAML/SCIM remain unimplemented as of early 2025
  • Okta integration is available only via Secure Web Authentication (SWA), not SCIM provisioning
  • User provisioning must be performed via the REST API or manually through the Keap UI

Common scenarios

Three primary automation scenarios are supported by the current API surface:

  • Provision a new user: POST to /crm/rest/v1/users with given_name, family_name, email_address, and admin flag. Keap automatically sends an invitation email - this cannot be suppressed via the API. User status will be Pending until the invite is accepted; poll GET /users/{userId} to confirm activation. If the account has reached its plan seat limit, the POST will fail; additional seats must be added through the Keap billing UI before the API call will succeed.

  • Sync users to an external directory: Call GET /crm/rest/v1/users?limit=1000&offset=0 and paginate via offset increments. There is no delta or incremental sync endpoint; full-list polling against a locally cached snapshot is the only change-detection mechanism. Webhook events exist for contact-level changes but user-specific events (e.g., user.add) are not explicitly documented.

  • Update role programmatically: Send PATCH /crm/rest/v1/users/{userId} with {"admin": true} or {"admin": false}. This is the full extent of API-accessible role control; granular permission toggles within the Standard User role are only configurable through the Keap UI.

Provision a new internal user via API

  1. Authenticate via OAuth 2.0 and obtain an access token with 'full' scope
  2. Check current user count against plan seat limit by calling GET /crm/rest/v1/users
  3. POST to /crm/rest/v1/users with given_name, family_name, email_address, and admin flag
  4. Keap sends an invitation email to the new user automatically
  5. Poll GET /crm/rest/v1/users/{userId} to confirm status transitions from 'Pending' to 'Active' after user accepts invite

Watch out for: If the account has reached its user seat limit, the POST will fail. Additional users cost $39/user/month and must be added via the Keap billing UI before the API call will succeed.

Sync Keap users to an external directory

  1. Authenticate via OAuth 2.0
  2. Call GET /crm/rest/v1/users with limit=1000&offset=0 to retrieve all users
  3. Paginate using offset increments until the returned count is less than the limit
  4. Map Keap user fields (id, given_name, family_name, email_address, admin, status) to the external directory schema
  5. Store the Keap user id as the external reference key for future updates

Watch out for: There is no delta/incremental sync endpoint; full list polling is required. For change detection, compare against a locally cached snapshot or use webhook events on contact-level changes as a proxy signal.

Update user role (admin flag) programmatically

  1. Authenticate via OAuth 2.0
  2. Retrieve the target user's id via GET /crm/rest/v1/users or by storing it at provisioning time
  3. Send PATCH /crm/rest/v1/users/{userId} with body {"admin": true} or {"admin": false}
  4. Confirm the change by calling GET /crm/rest/v1/users/{userId} and verifying the admin field

Watch out for: Keap's permission model is binary (admin vs. non-admin) at the API level; granular role-based access control is managed within the Keap UI and is not fully exposed via the REST API.

Why building this yourself is a trap

The most significant integration risk is the coexistence of v1 and v2 API endpoints with differing pagination behavior - v1 uses limit/offset, while v2 uses cursor/token-based pagination. Some resources exist only in v2, and the v2 surface is still evolving; endpoint availability should be verified against the official reference before building against it.

Rate limits are enforced at 25 requests/second per application, not per user. Shared integrations or high-frequency polling will hit this ceiling faster than single-tenant use suggests. HTTP 429 is returned on breach; exponential backoff is recommended, but the full rate-limit header spec is not completely documented publicly.

The DELETE endpoint for users (/crm/rest/v1/users/{userId}) deactivates rather than hard-deletes, preserving data integrity - but this behavior should be verified in a sandbox before production use, as availability may vary by plan tier.

Finally, because there is no SCIM layer, any identity graph built on Keap data requires the integration to own the full provisioning state machine, including pending-to-active status tracking and seat-limit pre-checks.

Automate Keap 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