MortgageGuidelines API

Partner User Lifecycle

Provision, deactivate, update, delete, and reprovision users for an embedded partner integration.

Partner user lifecycle

Partner-user endpoints use the immutable, opaque external_user_id from your system. Do not use an email address as this identifier, and do not change it when a user's name or email changes.

MortgageGuidelines assigns an integration identifier during onboarding. Substitute that exact allowlisted value for {integration} in every route below; a descriptive placeholder is not accepted by the API. The examples store it in INTEGRATION_ID.

The same bounded integration-slug schema applies to paths and responses. Authorization additionally requires active MG-owned integration configuration associated with the authenticated key's organization and linked client; neither a valid slug nor an external user/team ID grants access to another partner. Identical external user IDs may exist independently in different partners.

Grant each server-only key the minimum scopes it needs:

PurposeScopes
Read users and lifecycle operationsembed:users:read
Provision, deactivate, reactivate, edit profiles, import, and reprovisionembed:users:write
Permanently delete accountsembed:users:delete
Read or manage teamsembed:teams:read, embed:teams:write
Create iframe launchesembed:launch

The deletion scope is never added to an existing key automatically. An organization administrator must grant it explicitly.

Provisioning and lifecycle keys retain this scope model; they do not require embed:launch or a launch-only binding. MG provisions a distinct initially disabled binding for each launch key.

Provision a user

Use PUT /v1/integrations/{integration}/users/{external_user_id} to create or match a user:

API_BASE_URL="https://api.mortgageguidelines.com"
INTEGRATION_ID="<assigned-integration-id>"
EXTERNAL_USER_ID="employee-123"

curl -X PUT \
  "$API_BASE_URL/v1/integrations/$INTEGRATION_ID/users/$EXTERNAL_USER_ID" \
  -H "Authorization: Bearer mgapi_live_provisioning_key" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "taylor.morgan@example.com",
    "name": "Taylor Morgan",
    "team_external_id": "retail-west"
  }'

Provisioning is an identity-matching operation. Sending a different email for an existing user returns 409; use a profile-change operation instead. A deleted user requires explicit reprovisioning.

Public user responses are intentionally sanitized. They include entitlement status, readiness, account generation, profile synchronization state, and lifecycle-operation state, but not names, email addresses, passwords, or WordPress IDs.

Use GET /v1/integrations/{integration}/users to list users and GET /v1/integrations/{integration}/users/{external_user_id} to read one user's current state. Deleted users are excluded from the default list; request status=deleted explicitly to return their sanitized records.

List users for a team

The list endpoint supports team filtering with a key that has embed:users:read. Use the team's external_team_id from a team response as the value of the team_external_id query parameter; the field and filter names differ.

EXTERNAL_TEAM_ID="retail-west"

curl --get \
  "$API_BASE_URL/v1/integrations/$INTEGRATION_ID/users" \
  -H "Authorization: Bearer mgapi_live_read_key" \
  --data-urlencode "team_external_id=$EXTERNAL_TEAM_ID"

To check one user's membership in that team, add external_user_id to the same list request:

curl --get \
  "$API_BASE_URL/v1/integrations/$INTEGRATION_ID/users" \
  -H "Authorization: Bearer mgapi_live_read_key" \
  --data-urlencode "team_external_id=$EXTERNAL_TEAM_ID" \
  --data-urlencode "external_user_id=$EXTERNAL_USER_ID"

The matching sanitized record is returned in the users array. If the user is absent, belongs to another team, or is excluded by another filter, the response has an empty users array. Deleted users require status=deleted here as well.

The list returns 25 users per page by default. Set limit between 1 and 100, then pass the response's next_cursor as cursor on the next request with the same filters. A null next_cursor means there are no more results. The response's counts summarize the assigned integration within the key's organization; they are not totals for the filtered team or search. counts.total excludes deleted users, which are reported separately in counts.deleted.

Other supported filters are listed in the API Reference. Use q for a partial external user ID or external_user_id for an exact match; do not combine them. Use unassigned=true to find users without a team, and do not combine it with team_external_id. User names and email addresses are not returned, and email searches are not accepted in query parameters.

In the Postman Collection, set partnerIntegration, partnerExternalTeamId, and partnerExternalUserId to your assigned integration and opaque IDs. In Partner Users → List partner users, enable team_external_id in the Params tab and optionally external_user_id. The collection also includes List users in a team and Find a user in a team with those filters enabled.

The key is authorized for its organization and assigned integration. A team query filter selects records; it does not restrict the key's permissions to that team.

Deactivate or reactivate access

Use PATCH /v1/integrations/{integration}/users/{external_user_id}:

{
  "status": "disabled"
}

Deactivation immediately revokes chat grants and pending authorization. A partner-created WordPress account is locked and its sessions are destroyed. A pre-existing MortgageGuidelines account retains unrelated WordPress access but cannot launch or use the partner chat experience.

Send {"status":"active"} to reactivate a disabled user. Reactivation permits a fresh login; it never restores an old session. A deleted account cannot be reactivated through this endpoint.

Change an email address or display name

Use POST /v1/integrations/{integration}/users/{external_user_id}/profile-changes. Idempotency-Key is required.

curl -X POST \
  "$API_BASE_URL/v1/integrations/$INTEGRATION_ID/users/$EXTERNAL_USER_ID/profile-changes" \
  -H "Authorization: Bearer mgapi_live_provisioning_key" \
  -H "Idempotency-Key: profile-employee-123-v2" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "taylor.wilson@example.com",
    "name": "Taylor Wilson"
  }'

Partner-created identities are updated directly. Email changes to a pre-existing MortgageGuidelines identity require verification at the new address unless an authorized MortgageGuidelines administrator applies an audited override. Name-only changes to those pre-existing identities also require that override.

The old profile remains active while verification is pending. After a successful email change, existing grants and WordPress sessions are revoked and the user must authenticate again. A name-only change does not force logout.

Permanently delete an account

Use POST /v1/integrations/{integration}/users/{external_user_id}/deletions with a key that has embed:users:delete. Idempotency-Key is required and the audit note is optional.

curl -X POST \
  "$API_BASE_URL/v1/integrations/$INTEGRATION_ID/users/$EXTERNAL_USER_ID/deletions" \
  -H "Authorization: Bearer mgapi_live_deletion_key" \
  -H "Idempotency-Key: deletion-employee-123-001" \
  -H "Content-Type: application/json" \
  -d '{"note":"Employment ended"}'

The API returns 202 and disables access immediately. Account deletion then completes asynchronously:

  • A partner-created WordPress account is deleted.
  • A pre-existing MortgageGuidelines account remains, but its partner mapping is detached.
  • The current chat identity is blocked.
  • The current account generation is closed and the partner user becomes deleted.

Account deletion is not privacy erasure. Authorized auditors retain the user's identified profile history, lifecycle history, and earlier conversations indefinitely. No deletion notification is sent to the user.

Poll an operation

Profile changes, deletions, and reprovisioning return an operation.operation_id. Poll it with:

GET /v1/integrations/{integration}/user-operations/{operation_id}

The key needs embed:users:read. Operation states are queued, verification_pending, processing, completed, failed, expired, or cancelled. Public operation responses never include audit notes, profile values, or verification secrets.

Persist one idempotency key before submitting an operation. Reuse it only to retry the identical route and payload; use a new key for a different user or changed request.

Reprovision a deleted user

Ordinary provisioning and reactivation cannot revive a deleted account. Use POST /v1/integrations/{integration}/users/{external_user_id}/reprovision with embed:users:write and a required Idempotency-Key.

Reprovisioning preserves the root partner-user record and immutable external ID while incrementing account_generation. It creates new WordPress and chat identities. The returning user cannot access conversations from an earlier generation; authorized auditors retain access to that history.

Teams and bulk imports

Team routes use the same assigned integration identifier:

  • GET /v1/integrations/{integration}/teams
  • PUT /v1/integrations/{integration}/teams/{external_team_id}
  • GET /v1/integrations/{integration}/teams/{external_team_id}
  • PATCH /v1/integrations/{integration}/teams/{external_team_id}

Use POST /v1/integrations/{integration}/user-imports for up to 1,000 unique users and poll GET /v1/integrations/{integration}/user-imports/{job_id}. Imports provision and match identities; they do not perform profile changes or deletions.