Skip to main content

Sign-in for app developers

This page is for developers building an Arcel Konnect client (web, iOS, Android) against the Daily Dose API. It covers Google sign-in and email and password sign-in: what to call, in what order, what comes back, and which errors to handle. Every operation named here is in the API reference with its request, reply and examples; you can try them from the reference.

Base URL. Staging: https://staging.arcelintelligence.com (all paths below start with /v1). Send Content-Type: application/json on every request with a body.

The common parts​

Ask which methods to show​

Call listSignInProviders (GET /v1/auth/providers?platform=web|ios|android) when the sign-in screen opens and show the methods in the order it returns. Show only what it lists:

ValueShow
emailEmail address with a one-time code (works for verified test addresses only until email delivery is enabled)
passwordContinue with email and password
googleGoogle's sign-in button
apple, linkedin, phoneTheir buttons (Apple on iOS)
guestContinue without an account

Identify the installation​

Every sign-in request carries the same three device fields:

FieldValue
installationIdA random ID you create once per installation and keep (16 to 64 letters, digits or hyphens; a UUID works)
platformweb, ios or android
appVersionYour app's version, for example 2.0.0

Guests​

To let people browse first, call startGuestSession (POST /v1/auth/guest) with the device fields and keep the returned token. When the guest later signs in by any method, send the guest token as Authorization: Bearer <guest token> on the sign-in request: the guest's saves and preferences move into the account, and the guest token stops working.

The session you get back​

Every successful sign-in answers 200 with:

{
"token": "…",
"expiresAt": "2027-10-11T08:12:40Z",
"account": { "id": 5311, "kind": "reader", "providers": ["password"], "email": null, "…": "…" }
}
  • Store token in secure storage (Keychain on iOS, EncryptedSharedPreferences or the Keystore on Android; on the web the app keeps it in local storage) and send it on every call as Authorization: Bearer <token>.
  • The session lasts up to a year and ends after 90 days without use. A 401 on any call means the session ended: sign in again.
  • Then call getProfile (GET /v1/dailydose/profile). onboarded: false means the reader still has to finish onboarding. displayName is already filled with the name Google gave, so prefill your "What should we call you?" step with it.
  • signOut (POST /v1/auth/logout) ends the session.

Google sign-in​

Google sign-in uses Google's own SDK on the device to get an ID token, which you send to the API. There is no redirect URI and no client secret in the app.

Client IDs (public values, from the Google Cloud project arcel-daily-dose):

PlatformClient ID
Web (staging)610493135736-i2bmqqic4qpvfvleioflugplv0o4dkmh.apps.googleusercontent.com
iOS, AndroidCreated per app when the mobile apps register their bundle ID or package name; ask the ARCEL team. The API accepts only tokens issued for the IDs it lists.

The web origins Google accepts for this client are https://staging.arcelintelligence.com, https://d1cnuvka5u241f.cloudfront.net and http://localhost:5174. Until the Google project is published, only accounts listed as test users can sign in.

Steps

  1. Create a random nonce (at least 16 characters) for this sign-in attempt.

  2. Start Google sign-in with the client ID and that nonce:

    • Web: Google Identity Services (https://accounts.google.com/gsi/client), google.accounts.id.initialize({ client_id, nonce, callback }), then render Google's button. The callback's credential is the ID token.
    • Android: Credential Manager with GetGoogleIdOption, setServerClientId(<web client ID>) and setNonce(nonce); the result's idToken.
    • iOS: Google Sign-In for iOS with the iOS client ID and the nonce; user.idToken.tokenString.
  3. Call signInWithGoogle (POST /v1/auth/google):

    {
    "idToken": "<the ID token>",
    "nonce": "<the same nonce>",
    "installationId": "8a1c4e7b-2d5f-4a9c-b3e6-0f7d9c2a5b18",
    "platform": "android",
    "appVersion": "1.4.0"
    }
  4. Store the session as described above.

Errors

ReplyMeaningWhat to show
401 UNAUTHENTICATEDThe token is not for our client ID, expired, or the nonce differs"Google sign-in failed. Try again." Start again with a new nonce
400 VALIDATION_ERRORA missing or malformed fieldA generic error; fix the request
429 RATE_LIMITEDToo many attempts from this networkWait for Retry-After seconds

Each ID token works once; never reuse one.

Email and password​

Readers can create an account with an email address and a password and sign in with them. Use this as the email option while email codes cannot reach every reader.

Password rules (checked by the API; check the length on the device too):

  • 12 to 128 characters, any characters. No rules about symbols or digits: suggest a few unrelated words.
  • A password that appears in known data breaches is refused.
  • Turn on the platform's password managers: autocomplete="email" and autocomplete="new-password" or "current-password" on the web, the textContentType or autofillHints equivalents on iOS and Android.

The email address is not verified yet. It identifies this sign-in method only: another method with the same address (a Google account, an email code) is a different account. When email delivery is enabled, readers will confirm their address with a code.

Create an account​

registerWithPassword (POST /v1/auth/password/register), with the guest token if there is one:

{
"email": "layla.haddad@example.com",
"password": "three distant harbour lights",
"installationId": "3f2b8c1e-7a4d-4e9b-b6c2-1d5f8a9e0c47",
"platform": "web",
"appVersion": "2.0.0"
}

200 returns the session with passwordChangeRequired: false.

ReplyMeaningWhat to show
400 VALIDATION_ERROR with fieldErrors.passwordToo short, too long, or found in a data breachThe message from fieldErrors.password under the password field
400 VALIDATION_ERROR with fieldErrors.emailNot an email addressThe message under the email field
409 EMAIL_TAKENThis address already has a password"An account with this email already exists." and a button to switch to sign-in
429 RATE_LIMITEDToo many sign-ups from this networkWait for Retry-After seconds

Sign in​

signInWithPassword (POST /v1/auth/password/sign-in) with email, password and the device fields (and the guest token if there is one). 200 returns the session and passwordChangeRequired.

ReplyMeaningWhat to show
401 INVALID_CREDENTIALSThe email or the password is wrong (the API never says which)"Email or password is incorrect"
429 RATE_LIMITED10 wrong passwords in a row locked the address for 15 minutes, or too many attempts from this network"Too many attempts. Try again in 15 minutes."
403 FORBIDDENThe account cannot sign in (suspended)"You can't sign in with this account. Contact support."

After a reset: passwordChangeRequired​

A reader who forgot the password contacts ARCEL support. After checking who they are, support gives them a temporary password (there is no email reset yet). Signing in with it answers passwordChangeRequired: true. Keep the session, but show only a "Choose a new password" screen until they change it:

changePassword (POST /v1/auth/password/change, with the session token):

{ "currentPassword": "<the temporary password>", "newPassword": "a phrase they will keep" }

200 answers { "changed": true, "otherSessionsEnded": 0 }. Then continue as after any sign-in (getProfile).

Change the password​

Offer Change password in the account settings when getAccount (GET /v1/auth/account) lists password in providers. Use the same changePassword call with the current password. The reader's other devices are signed out; this one stays signed in.

ReplyMeaningWhat to show
400 with fieldErrors.currentPasswordThe current password is wrongIts message under the current-password field
400 with fieldErrors.newPasswordToo short, the same as the current one, or found in a data breachIts message under the new-password field
404 NOT_FOUNDThis account has no password (it signs in another way)Hide the option
429 RATE_LIMITEDToo many wrong current passwords"Too many attempts. Try again in 15 minutes."

Checklist​

  • The sign-in screen shows the methods listSignInProviders returns, in that order.
  • One installationId per installation, sent on every sign-in.
  • A guest's token is sent on the sign-in request, then replaced by the new token.
  • Tokens are kept in secure storage and sent as Authorization: Bearer.
  • Google: a new nonce per attempt, the same nonce sent to the API, the ID token used once.
  • Passwords: 12+ characters checked on the device, password-manager autofill on, fieldErrors shown under their fields, one message for any wrong email or password.
  • passwordChangeRequired: true leads straight to "Choose a new password".
  • Change password is offered only when providers contains password.
  • After getProfile, onboarded: false starts onboarding with displayName prefilled.