Endpoints¶
Configuration¶
API URL : https://api.neomia.ai/pulse
API Key
To use this API, please send your neomia Pulse API key in the headers for each request.
1 | |
<APIKEY> with your own api key.
For further details, please consult our documentation Swagger here.
Core concepts¶
User Reference
The parameter indicated userRef represents your custom user ID. We recommend using a name respecting email format conventions.
User references are normalized: they are lowercased, trimmed, and spaces are replaced by -. Alice, alice and alice designate the same user. The same normalization applies to member_ref.
Accounts and members. An identity in Pulse is an account:
- a nominative account belongs to one person — its single member is the account (
memberRefequalsuserRef); - a generic (shared) account is used by several people — each has their own
member_ref, biometric profile and security code.
On a generic account, every user-scoped call takes a ?member_ref= query parameter (or member_ref in the body) to designate the member; on a nominative account it is omitted.
Session header. The integration flow is stateful: the bootstrap call (GET /users/{userRef}) returns an X-Pulse-Session response header. Send this header back on every subsequent call of the flow (/verify, /typing-patterns, /security-code, …). A missing or expired session returns 400 with the message "Missing or expired X-Pulse-Session — call GET /users/{user_ref} to bootstrap".
Integration flow¶
A complete integration follows this sequence (see also API Integration):
- Bootstrap —
GET /users/{userRef}: resolve the identity, obtain the session and the account state (biometricStatus,requiresSecurityCode,suggestedWords,targetRefPatterns, …). - Create the identity if it does not exist —
POST /users/{userRef}. - Enroll —
POST /users/{userRef}/typing-patternsin a loop, one reference pattern per call, untilbiometricStatusisok(target:targetRefPatternspatterns, default 5). - Optionally set a security code —
PUT /users/{userRef}/security-code. - Verify —
POST /users/{userRef}/verifywith a typing pattern (or a security code, when the policy allows the fallback).
Request : Status¶
GET /status
This endpoint allows to know if Pulse API is up to receive requests.
Response : OK¶
1 2 3 4 5 6 7 | |
Response : NOK¶
1 2 3 4 5 6 7 | |
NOK is also returned while the service runs in degraded mode (configuration store unreachable) — in that state every other endpoint answers 503.
Request : Bootstrap User¶
GET /users/{userRef}
The entry point of every flow. Resolves the identity, mints (or echoes) the X-Pulse-Session response header, and returns everything the client needs to decide the next step. Optional query parameters: member_ref (generic accounts), language (for the suggested words).
Response : User exists¶
Status code : 200
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
Key fields:
accountType:nominative|generic.memberRef: on a generic account,nulluntil the member is designated (?member_ref=).memberSelection(ask|list) tells the client whether to prompt for the member reference or to offer the member list (fetch it withGET /users/{userRef}/members).biometricStatus:not-ready|in-progress|ok|full|reset|expired. Enrollment is complete when it reachesok.pendingAction: a profile action queued by an administrator (RESET_BIOMETRIC_PROFILE,UPDATE_BIOMETRIC_PROFILE) to honor at this sign-in.suggestedWords/suggestedWordsLanguage: the words to propose in the typing widget.
Response : User does not exist¶
Status code : 404 — the body is still populated as an "onboarding shell" (biometricStatus: "not-ready", nPatternsRef: 0, suggested words included) so the client can chain directly into user creation and enrollment.
Request : Create User¶
POST /users/{userRef}
Creates the identity (the account and its first member) — no biometric data is sent on this call.
Request body¶
1 2 3 4 5 6 | |
type:nominative(default) orgeneric.member_ref: first member of a generic account.rotate_security_code: whentrue, a security code is generated and returned once in the response (securityCode).user_display_name: optional display label shown on the dashboard (never used as an identity key).
Status code : 201 on creation, 200 if the account already exists.
Request : Enroll Reference Pattern¶
POST /users/{userRef}/typing-patterns
Adds one reference pattern to the user's biometric profile. Requires the X-Pulse-Session header; returns 404 if the account does not exist (create it first).
The request body carries the pattern captured by the Pulse recorder (same shape as the verify pattern body below) plus, for generic accounts, member_ref.
Response¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Loop contract: keep posting patterns until biometricStatus is ok (or full), i.e. until nPatternsRef == targetRefPatterns.
Related endpoints:
- DELETE
/users/{userRef}/typing-patterns— reset the biometric profile (removes all reference patterns). - DELETE
/users/{userRef}/typing-patterns/{patternId}— remove one reference pattern.
Request : User Verify¶
POST /users/{userRef}/verify
The main authentication endpoint: checks a typing pattern (or a security code) against the user's profile. Requires the X-Pulse-Session header.
Request Body (Pattern)¶
The pattern object produced by the Pulse recorder libraries. The relevant top-level fields:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
Send the end-user IP
Your backend relays the pattern to Pulse, so the transport IP that Pulse sees is your server's, not the user's. Set ip to the end-user's address — it feeds the network, location and impossible-travel indicators. Relying on the transport IP is deprecated.
For generic accounts add member_ref. To authenticate with the security-code fallback instead of a pattern, send:
1 | |
Response : Verify¶
Status code : 200
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
The fields to act on:
authentication.authenticated(boolean) andauthentication.recommendedAction:auth|challenge|block. If the recommended action isauth, the user is authenticated by Pulse.authentication.authMethod:biometricorsecurity_code— a code fallback should be treated as a challenged authentication, not a clean biometric pass.nextAttempt: populated when the attempt failed and the session may continue —mode(biometric|security_code|locked), the remaining attempt counts and freshsuggestedWords.enrollmentRequired:truewhen a security code matched but the biometric profile is not complete — do not issue the login; send the user through enrollment first.
Response : Robot detected¶
If a pattern is generated by a bot (for example, a password manager), Pulse returns a bot detection response: authenticated: false, recommendedAction: "block" and reason: "detection-bot" (status code 200).
Request : Security Code¶
The security code is the per-member fallback PIN used when biometric attempts fail (if the authentication policy enables the fallback).
- PUT
/users/{userRef}/security-code— set or replace a user-chosen code. Body:{"securityCode": "483920"}. Weak/common codes are refused with 422. - POST
/users/{userRef}/security-code— generate a temporary code server-side. The plaintext is returned once in the response; the user must replace it. - DELETE
/users/{userRef}/security-code— clear the code.
All three require the X-Pulse-Session header and take ?member_ref= on generic accounts.
Request : Members (generic accounts)¶
GET /users/{userRef}/members
Returns the member roster of a generic account, for the list member-selection mode.
Request : Account Management¶
- PATCH
/users/{userRef}— account gestures: changetype(nominative↔generic),groups,tag,member_selection(ask|list).- Promoting a nominative account to generic requires explicit
type: "generic"and a distinctmember_ref; otherwise 409. - Downgrading a generic account to nominative is only allowed with at most one active member; otherwise 409.
- Promoting a nominative account to generic requires explicit
- POST
/users/{userRef}/pending-action— queueRESET_BIOMETRIC_PROFILEorUPDATE_BIOMETRIC_PROFILEfor the next sign-in; DELETE clears it. - PUT
/users/{userRef}/preferred-language— per-member widget language override ({"language": "fr"},nullclears).
Request : Delete User¶
DELETE /users/{userRef}
Deletes the account and all its data. On a generic account, ?member_ref= archives that single member instead of deleting the account. The account stays generic even when only one member remains.
Successful Response¶
1 2 3 4 5 6 7 | |
Request : Organization¶
- GET
/organization— organization info and subscription counters (nUsers,subscriptionQuantity,subscriptionGenericQuantity,subscriptionUsage, validity dates). - GET/PATCH
/organization/language— the widget display-language setting ({default_language, language_mode: "auto"|"forced"}). - GET/POST/PATCH/DELETE
/organization/typing-words— manage the organization's typing words (core platform words can be disabled but not edited or deleted — 403).GET /organization/typing-words/languageslists the available languages. - DELETE
/user-display-names— organization-wide clearing of the stored display names.
Errors¶
Every error uses the same envelope:
1 2 3 4 5 6 | |
reason values: invalid-action, invalid-data, api-failed, detection-bot, fraud-detected, user-not-found, quota-exceeded, internal-error.
| Status | Situation |
|---|---|
| 400 | Missing or expired X-Pulse-Session; member_ref required on a generic account; member_ref mismatch on a nominative account. |
| 401 | Missing or unknown API key (no organization resolved). |
| 404 | User/account not found. On GET /users/{userRef} the 404 body is a populated onboarding shell. |
| 409 | License quota exceeded (see below); account-type change requiring consent or blocked; duplicate member reference; duplicate typing word. |
| 422 | Invalid pattern (too short, too long, unsupported version), bot detected, weak security code, or a request-validation error. |
| 500 | Internal error — the message carries a request id to communicate to support. |
| 503 | Service in degraded mode (configuration store unreachable). |
License quotas
Account creation is subject to the license quotas (accounts, shared accounts, members per shared account). When strict enforcement is enabled and a quota is reached, the API answers 409 with reason: "quota-exceeded" and a message prefixed by ACCOUNTS_QUOTA_EXCEEDED:, SHARED_ACCOUNTS_QUOTA_EXCEEDED: or SHARED_ACCOUNT_MEMBERS_EXCEEDED:. By default enforcement is soft: nothing is blocked, and overage is flagged on the dashboard's Subscription page.
Legacy endpoints (deprecated)¶
The following endpoints remain available for existing integrations but are deprecated — new integrations must use the v2 endpoints above. Deprecated responses carry Deprecation, Sunset and successor Link headers.
POST /user-verify/{userRef}¶
Legacy verify. Contrary to POST /users/{userRef}/verify, it can create the user on the fly with the header {'x-enrollment': 'USER'} and does not require a prior bootstrap. Superseded by the bootstrap → create → enroll → verify sequence.
POST /user-action/{userRef}¶
Legacy profile actions (LINK_PATTERN, LINK_PATTERN_ID, UNLINK_PATTERN_ID, RESET_BIOMETRIC_PROFILE). Superseded by POST /users/{userRef}/typing-patterns, DELETE /users/{userRef}/typing-patterns[/{patternId}] and POST /users/{userRef}/pending-action.
DELETE /user-delete/{userRef}¶
Alias of DELETE /users/{userRef}.
POST /feedback/{authenticationId}¶
Deprecated no-op — kept only for response-shape compatibility.