Skip to main content

Track a Login

Call /v1/evaluate/login on every login attempt, including failed ones. Pinch correlates the attempt with device, IP, and historical patterns to detect account takeover, credential stuffing, and session hijack.

Failed-login data is as valuable as successful logins — it's how Pinch sees brute-force attempts. Send both.

Request​

POST /v1/evaluate/login HTTP/1.1
Host: api.pinch.ai
Authorization: {api-key}
Content-Type: application/json

Body​

FieldTypeRequiredDescription
providerCustomerIdstringyesYour customerId for the user attempting to log in. For attempts on a non-existent account, set to the attempted username.
loginStatusstringyes$success or $failure.
emailstringyesEmail on the login attempt.
usernamestringyesUsername on the login attempt. Often the same as email.
siteDomainstringyesDomain where the login happened.
verificationPhoneNumberstringnoPhone used for SMS or 2FA, if any.
authMethodobjectyesDetails about how the user authenticated. See below.

Auth method​

{
"type": "password" | "sso" | "magic_link" | "passkey" | "oauth",
"mfaUsed": true,
"mfaMethod": "app_authenticator" | "sms" | "email" | "hardware_key",
"deviceFingerprints": [{ "deviceIdentifier": "{visitorId}" }]
}
FieldTypeRequiredDescription
typestringyesPrimary auth method.
mfaUsedbooleannoWhether MFA challenge was completed.
mfaMethodstringnoWhich MFA method was used.
deviceFingerprintsarrayrecommended[{ "deviceIdentifier": "{visitorId}" }] from the JS SDK.

Example request — successful login​

curl https://api.pinch.ai/v1/evaluate/login \
-H "Authorization: $PINCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"providerCustomerId": "user_12345abcde",
"loginStatus": "$success",
"email": "johndoe@example.com",
"username": "johndoe@example.com",
"verificationPhoneNumber": "+15551234567",
"siteDomain": "demostore.com",
"authMethod": {
"type": "password",
"mfaUsed": true,
"mfaMethod": "app_authenticator",
"deviceFingerprints": [
{ "deviceIdentifier": "abc123visitorId" }
]
}
}'

Example request — failed login​

Send these too. Pinch needs them to detect brute-force.

{
"providerCustomerId": "johndoe@example.com",
"loginStatus": "$failure",
"email": "johndoe@example.com",
"username": "johndoe@example.com",
"siteDomain": "demostore.com",
"authMethod": {
"type": "password",
"mfaUsed": false,
"deviceFingerprints": [{ "deviceIdentifier": "xyz789visitorId" }]
}
}

When the account doesn't exist, you may not have a customerId. Pass the attempted username as providerCustomerId in that case so Pinch can group attempts.

Response​

{
"providerLoginID": "user_12345abcde",
"pinchLoginID": "plgn_9d8c7b6a",
"Decisions": [
{
"decisions": [
{
"decisionType": "APPROVE/DECLINE",
"decision": "APPROVE",
"subDecision": "Default Approve",
"decisionReason": "Known device, MFA verified",
"abuseScore": 6
}
]
}
]
}

Decision semantics​

DecisionRecommended action
APPROVEAllow the session normally.
DECLINEBlock. For a successful login, terminate the session and require step-up auth (MFA challenge, email verification). For a failed login, increment your block counter and rate-limit.
REVIEWForce step-up auth — email magic link or MFA prompt — before granting the session.

For high-stakes accounts (payouts, admin), consider treating both DECLINE and REVIEW as forcing MFA, regardless of the user's normal flow.

Common abuse patterns detected at login​

  • Credential stuffing — many $failure attempts across many accounts from a small set of IPs/devices
  • Account takeover (ATO) — a $success from a device that has never been associated with this account, especially right after a sequence of $failure attempts on the same account
  • MFA bypass attempts — patterns of mfaUsed=false on accounts that have MFA enabled
  • Session hijack — a device that suddenly logs into accounts it has never touched, in quick succession

Errors​

HTTPCodeMeaning
400invalid_requestRequired field missing
422unprocessable_entityloginStatus not one of $success / $failure
429rate_limitedSlow down

See also​