Person invites and sign-in
Invite a Person to sign in, redeem the invite, finish setup, and handle email, phone, and password changes with the Wingspan V3 API.
A Person is a human who can sign in. This page covers how a Person gets credentials from an invite, how they finish profile setup, and how they verify or change their email, verify a phone, and set or reset a password.
Treat every sessionToken and emailed token as a secret and don't log it.
Prerequisites
- To send an invite: an Account credential with scope
users.authorization:write, and the id of an existing Person. - To redeem an invite: the single-use
inviteTokenfrom the invitee's email. No credential is needed. - For the email, phone, and password calls: a signed-in Person session where the path
personIdis that Person. API keys are rejected with403.
Endpoints
| Method and path | Operation | Caller |
|---|---|---|
POST /v3/platform/persons/{personId}/invite | invitePerson | Account |
POST /v3/platform/persons/initialization-links | requestPersonInitializationLink | Public |
POST /v3/platform/persons/invite-redemptions | redeemPersonInvite | Public |
POST /v3/platform/persons/submissions | submitPerson | Invite token |
POST /v3/platform/persons/submissions-as-self | submitPersonAsSelf | Person session |
POST /v3/platform/persons/{personId}/verify-email | verifyPersonEmail | Person session |
POST /v3/platform/persons/{personId}/verify-phone | verifyPersonPhone | Person session |
POST /v3/platform/persons/{personId}/change-email | startPersonEmailChange | Person session, MFA step-up |
POST /v3/platform/persons/{personId}/confirm-email-change | confirmPersonEmailChange | Person session |
POST /v3/platform/persons/{personId}/reset-password | resetPersonPassword | Person session, or reset token |
Person statuses
A Person's status moves Created, Invited, Pending, Active, and can end as Inactive or Disabled.
1. Send the invite
curl -X POST https://api.wingspan.app/v3/platform/persons/$PERSON_ID/invite \
-H "Authorization: Bearer $WINGSPAN_TOKEN" \
-H "X-Wingspan-Account: $ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{ "expiresIn": "P7D", "message": "Welcome to the team." }'The body is optional. Fields:
| Field | Notes |
|---|---|
shouldSendEmail | Default true. With false the invite is still created and no email is sent. The invitee can ask for a link with initialization-links. |
expiresIn | ISO 8601 duration. Default P14D, maximum P30D. |
message, notes | Up to 4096 characters each. |
redirectUri | A URI. |
The 200 response is a receipt: id, personId, expiresAt, sentTo, createdAt, and credentialGrant. The invite link is never returned to you. It goes to the invitee by email only. credentialGrant: true means the link lets the invitee set credentials; false means it's an action link for a Person who already has credentials. Re-issuing an invite replaces any unused outstanding invite. Errors: 404 for an unknown Person, 409 for a conflict with the Person's state.
2. The invitee requests a link or redeems the token
POST /v3/platform/persons/initialization-links takes { "email": "..." }. It also accepts the captcha fields captchaToken, captchaVersion, and forceCaptcha. For a credential-less Person it sends a registration link. For an Active Person it sends a reset-password link. Otherwise it does nothing. The response is always 200 for a well-formed request and doesn't reveal which case applied:
{ "success": true, "message": "..." }Pre-production environments also return magicLink. Errors: 422 for a malformed email, 429 when the rate limit is hit, 503 when the service is unavailable.
POST /v3/platform/persons/invite-redemptions takes { "inviteToken": "..." } and returns 201 with a Person session:
| Field | Meaning |
|---|---|
personId, status, email, isEmailVerified | The invited Person. |
sessionToken, sessionExpiresAt | Use the token as an ordinary Authorization: Bearer for the first session. |
elevated | Whether the session already counts as MFA step-up. |
inviteContext | inviteId, inviterPersonId, accountId, stakeholderId, payerPayeeLinkRequestId, modules[], requirementDefinitionNames[], and presentation (inviter and Account display names, logoUrl, brandColor). |
Errors: 404 for an unknown token, 410 when the token is expired or already used, 422 when inviteToken is missing, 503 when redemption is unavailable.
3. Set the first password
Call POST /v3/platform/persons/{personId}/reset-password with the redeemed session and { "newPassword": "..." } and no token. Do it within 30 minutes of redemption; the invite-redemption session is exempt from the usual MFA step-up only during that window.
4. Submit profile setup
After redemption, send the profile with POST /v3/platform/persons/submissions-as-self (Person session) or POST /v3/platform/persons/submissions (invite token as the bearer). Neither takes ids in the body, and neither accepts X-Wingspan-Account.
| Field | Notes |
|---|---|
person | firstName, lastName, email, phone. |
displayProfile | Presentation-only profile fields. |
marketingConsent | Boolean. false is stored; it isn't treated as omitted. |
The 200 response has personId, status, and a requirements summary. Don't send profile, credentials, or requirementFulfilments: the API returns 422. Identity data goes through ComplianceEntity, credentials through the password call above, and requirements through the onboarding surfaces. Other errors: 401 without a bearer, 403 for an API key on submissions-as-self, 410 InviteTokenExpired for an expired invite token on submissions.
Verify email and phone
POST .../verify-email with no body requests a new verification email. With { "token": "..." } it completes verification. It never changes the address. The response is the Person. A request from an API key or another Person returns 403 or 404.
POST .../verify-phone has the same shape for SMS (token optional).
Change the sign-in email
POST .../change-emailwith{ "email": "[email protected]" }. Needs a recent MFA step-up forHighRiskWriteAction. The API sends a confirmation link to the new address and returns204. Errors:403for an API key or missing step-up,404,409,422.POST .../confirm-email-changewith{ "token": "..." }. The API updates the sign-in and displayed email, marks it verified, signs the Person out of every V3 session, and returns the Person. A wrong or used token returns404.
Sign in again with the new email and password afterwards.
Reset or change a password
POST .../reset-password has three forms:
| Body | What it does | Caller |
|---|---|---|
none, or {} | Emails a reset link to the Person. Returns 204. | Signed-in Person session for that personId. |
{ "token", "newPassword" } | Completes an emailed reset. Returns 204. | The reset-only token from the link. It isn't an API bearer. |
{ "newPassword" } | Self-service change. Returns 204. | Signed-in Person session. Needs MFA step-up, or a redeemed invite session within its window. |
A password is 8 to 512 characters, has at least one ASCII letter and one digit, and has no whitespace. A successful change revokes every session of that Person.
| Status | When |
|---|---|
401 | The reset token is invalid or expired, or the wrong Person's token. The body doesn't say which. |
403 StepUpMfaRequired | A self-service change without recent MFA step-up. |
403 | An API key was used. |
404 | The session's Person isn't the path personId. |
422 | The password doesn't meet the rules, or token was sent without newPassword. |
503 | The password service is unavailable. |
Webhooks
The catalog lists Person.* events. Subscribe with POST /v3/platform/webhooks. See Webhooks and events.
Related pages
Updated 11 minutes ago