Authentication
Authenticate storefront contacts and platform operators with verification codes
Arky has two explicit authentication surfaces:
initializefromarky-sdk/storefrontauthenticates customers on a storefront.createAdminfromarky-sdk/adminauthenticates platform operators and store team members.
Both use an email verification code. The request returns a challenge_id; keep it and send it with the code. A code without its challenge cannot be verified.
Storefront Contact Authentication
Create one storefront store for the browser application:
import { initialize } from "arky-sdk/storefront";
const storefront = initialize("arky_pk_...", {
market: "us",
locale: "en",
});
Request a code and retain the returned challenge:
const identified = await storefront.identify({
email: "contact@example.com",
verify: true,
});
const challengeId = identified.verification_challenge?.challenge_id;
if (!challengeId) throw new Error("Verification challenge was not created");
Verify the code entered by the customer:
await storefront.verify({
challenge_id: challengeId,
code: "123456",
});
const contact = await storefront.me();
console.log(contact.email);
The browser SDK persists the storefront session internally as an arky_vst_...
visitor token. It sends that token only after a stateful operation creates the
visitor session. Read current state through the store, subscribe to changes, or
log out through the same instance:
const session = storefront.session.get();
const stop = storefront.onAuthStateChanged((nextSession) => {
console.log(nextSession?.contact.email ?? "signed out");
});
await storefront.logout();
stop();
Calling identify() without an email creates or resumes the anonymous storefront contact used for carts and other pre-login activity. Authentication is established only after verify succeeds.
The arky_pk_... publishable key identifies the Store and is safe in browser
code. It is not a visitor or Admin credential. Never put a Personal API Token
in storefront code; the SDK creates and persists arky_vst_... visitor
sessions itself.
Platform Operator Authentication
Use the admin client for operators, never the storefront contact client:
import { createAdmin } from "arky-sdk/admin";
const admin = createAdmin({
baseUrl: "https://api.arky.io",
storeId: "store_abc123",
market: "us",
});
const challenge = await admin.account.auth.code({
email: "operator@example.com",
});
await admin.account.auth.verify({
challenge_id: challenge.challenge_id,
code: "123456",
});
const account = await admin.account.getMe({});
console.log(account.email);
For a store-branded operator challenge, use account.auth.storeCode and account.auth.storeVerify with the same challenge_id rule.
const challenge = await admin.account.auth.storeCode("store_abc123", {
email: "operator@example.com",
});
await admin.account.auth.storeVerify("store_abc123", {
challenge_id: challenge.challenge_id,
code: "123456",
});
The admin client also persists its browser session internally:
console.log(admin.isAuthenticated);
await admin.logout();
Error Handling
Do not retry verification with a challenge from another request. If the challenge is missing or expired, request a new code.
try {
await storefront.verify({ challenge_id: challengeId, code: "000000" });
} catch (error) {
console.error(error instanceof Error ? error.message : "Verification failed");
}
Next Steps
- Core Concepts - Learn about stores, resources, and permissions
- Authentication API Reference - Platform account authentication and sessions
- CRM API Reference - Storefront contact authentication
- Error Handling - Handle API errors