Skip to main content

Login & self-service profile — full walkthrough

Logging in

TP=(-H "X-Touchpoint-Code: <code>" -H "X-Touchpoint-Key: <key>" -H "Content-Type: application/json")

curl -sX POST "$BASE/api/v1/login" "${TP[@]}" -d '{
"identifier": "ada@example.com",
"password": "Secret123!"
}'
# → 200 { "customerId": "...", "token": "<Customer JWT>" }

identifier accepts email, cellphone, or document number — whichever the consumer used to register. Wrong credentials return 401 INVALID_CREDENTIALS (deliberately the same response whether the identifier doesn't exist or the password is wrong, so you can't enumerate accounts by probing). Missing/invalid touchpoint credential returns 401 TOUCHPOINT_UNAUTHORIZED instead — check which code came back.

Hammering login too fast returns 429 RATE_LIMITED with a retryAfter in seconds — see Errors & rate limits.

Keep the returned token; attach it as Authorization: Bearer <token> on every call below.

Viewing your own profile

JWT=(-H "Authorization: Bearer <token>")

curl -sX GET "$BASE/api/v1/me" "${TP[@]}" "${JWT[@]}"
# → 200 { "id": "...", "version": 3, "firstName": "Ada", "email": "ada@example.com", ... }

version is the optimistic-lock counter — read it before every PATCH.

Editing your own profile

curl -sX PATCH "$BASE/api/v1/me" "${TP[@]}" "${JWT[@]}" -d '{
"version": 3,
"firstName": "Ada",
"addressCity": "Rosario"
}'
# → 200 updated profile, version incremented

Only a fixed field set is honored: version, email, cellphone, country, addressCountry, addressState, addressCity, addressLine1, addressLine2, addressPostalCode, firstName, lastName, birthdate, gender, companyName, emailOptin, smsOptin, whatsappOptin, termsAccepted, privacyAccepted. Anything else — status, type, verification state, document/identity fields, custom fields — is silently ignored; you cannot escalate your own account this way.

Things to handle in your UI:

  • Stale version409 VERSION_CONFLICT. Re-fetch GET /me and retry with the fresh version.
  • Email/cellphone collision409 DUPLICATE_CUSTOMER with field naming which one.
  • Changing email or cellphone resets that channel to UNVERIFIED — prompt the consumer to re-verify (below).
  • Inactive account403 CUSTOMER_INACTIVE.

Verifying a channel

Whether the email/cellphone is fresh (just changed) or was never verified (instant registration), the flow is the same — requires the Customer JWT:

curl -sX POST "$BASE/api/v1/verifications/EMAIL/request" "${TP[@]}" "${JWT[@]}"
# → 202 (code sent)

curl -sX POST "$BASE/api/v1/verifications/EMAIL/confirm" "${TP[@]}" "${JWT[@]}" -d '{"code":"123456"}'
# → 200 { "status": "VERIFIED" }

A wrong code returns 400 INVALID_OTP. channel is EMAIL or CELLPHONE.

Changing your password

curl -sX POST "$BASE/api/v1/password/change" "${TP[@]}" "${JWT[@]}" -d '{
"oldPassword": "Secret123!",
"newPassword": "NewSecret1!"
}'
# → 200

Wrong oldPassword401 INVALID_CREDENTIALS.

Forgot / reset password (no session needed)

curl -sX POST "$BASE/api/v1/password/forgot" "${TP[@]}" -d '{"identifier":"ada@example.com","channel":"EMAIL"}'
# → 200 always (doesn't reveal whether the account exists)

curl -sX POST "$BASE/api/v1/password/reset" "${TP[@]}" -d '{
"identifier": "ada@example.com",
"channel": "EMAIL",
"code": "123456",
"newPassword": "Reset123!"
}'
# → 200

Logging out

curl -sX POST "$BASE/api/v1/logout" "${TP[@]}" "${JWT[@]}"
# → 200

Logout is stateless on the server side — there's no session to invalidate remotely. Discard the JWT client-side; it simply expires on its own after that.