ExtremeXCLIENT
← Integration guide
Specification 1.0SDK baseline 3.2.0Existing + proposed APIs

Advanced integration & API specification

Precise contracts for identity, consent and app data, with a clearly marked implementation plan for the next APIs.

This reference includes proposals. A signature or example here does not mean your installed SDK supports it. Confirm the platform and release before calling a method.

Product: ExtremeX ONE Identity, Consent & Application Data Platform Publisher: ExtremeX Technology Document classification: Developer reference / implementation proposal Revision: 1.0 — 23 October 2026 Existing SDK baseline: 3.2.0 (as shown on the reviewed integration guide) Status: Existing API inventory plus proposed additions; proposed methods are not confirmed shipped. Primary documentation: https://client.extremextechnology.com/docs Account portal: https://one.extremextechnology.com/account

1. Executive summary

ExtremeX ONE provides federated authentication, granular consent, privacy-preserving identity attributes, per-application encrypted storage and unified account-management flows. This specification standardises the one facade, documents existing behaviour, and proposes new application metadata, legal-document consent, organisation-membership and account-lifecycle interfaces.

Design objectives:

  1. Privacy by default: Applications receive only fields explicitly granted through ONE; raw date of birth and exact age must never be exposed.
  2. Least privilege: Account, application, organisation and moderation operations are authorised independently and enforced on the ONE server.
  3. Predictable outcomes: null means an unavailable/withheld profile value, never an assumed negative result or transport failure.
  4. Cross-platform parity: Shared logical contracts map to Kotlin, Android, Swift, JavaScript, React Native, Flutter, Java and other supported clients.
  5. Strong consistency of consent: Consent changes and disconnects take effect at the protected resource boundary; stale local caches cannot override server policy.
  6. Developer experience: Stable method names, typed results, explicit errors, completion prompts, diagnostics and migration guidance.

1.1 Implementation status legend

LabelMeaning
Existing — documentedFound in the reviewed live SDK 3.2 integration guide.
ProposedRequested API or expanded contract; requires backend/SDK development and release verification.
RecommendedDesign guidance or optional future enhancement, not a guarantee of current implementation.

Compatibility note: The current native guide uses one.auth.signOut() for local sign-out. one.auth.data.signOut() below is a proposed forwarding alias, not a replacement for the existing call. The identifiers Varified and Enroled are preserved where explicitly requested for source compatibility; correctly spelled aliases may be introduced later.

2. Existing integration architecture

Plain text
Host application (Android / iOS / Web / Desktop / Server)
    |
    +--> ONE SDK facade (`one`)
             |
             +--> Auth: browser login, OAuth 2.0 / PKCE, callback, tokens
             +--> Profile: consent-filtered identity & derived age checks
             +--> App data: app/user-scoped typed key-value operations
             +--> [PROPOSED] App metadata and legal-doc consent
             +--> [PROPOSED] Organisation access and moderation gateways
    |
    +--> ExtremeX ONE OAuth / API infrastructure
             |
             +--> Identity & verified attributes
             +--> Live consent and revocation enforcement
             +--> Encrypted application data
             +--> [PROPOSED] Versioned legal document records
             +--> [PROPOSED] Organisation/project role bindings
             +--> [PROPOSED] Privileged moderation service

2.1 Authentication sequence

  1. Register an application in ExtremeX Client and obtain APP_ID, CLIENT_ID, and the documented redirect configuration.
  2. Configure requested data fields in Client → Data access, with a specific purpose and required/optional classification.
  3. Start sign-in using the supported ONE browser-based flow. Public clients use OAuth 2.0 authorization code + PKCE (S256); never embed client secrets in shipped clients.
  4. ONE authenticates the user and displays its hosted consent and missing-profile completion screens.
  5. Validate callback parameters and exchange the authorization code using the documented platform flow.
  6. Bind an authenticated session to the one SDK instance. Refresh and persist rotating refresh tokens using platform-secure storage when available and authorised.
  7. Invoke protected profile, application-data or proposed APIs. Each server call evaluates current access rights.
  8. On local sign-out, clear local session state. Revocation of granted access is a separate ONE account action unless a future endpoint explicitly implements it.

Current service endpoints (documented):

Plain text
Authorization: https://one.extremextechnology.com/oauth/authorize
API base:     https://api.extremextechnology.com/one

GET    /oauth/authorize
POST   /oauth/token
GET    /oauth/userinfo
GET    /data?key=KEY
PUT    /data
DELETE /data?key=KEY

Important: The proposed app-document, organisation, and moderation endpoints later in this specification are design proposals. Their paths and payloads must be implemented and published before SDK methods can call them.

3. Shared API conventions

3.1 Namespaces

FacadeResponsibility
one.auth.data.*Consent-filtered user profile and derived identity attributes.
one.auth.*Authentication lifecycle and session controls.
one.app.data.*Registered app's public metadata and legal-document consent (proposed).
one.data.*Per-user, per-app encrypted key-value storage.
one.org.*Recommended future separation for organisation administration; existing requested aliases may remain under one.auth.data.
one.admin.*Recommended privileged moderation namespace; setBan can remain as a compatibility delegate after authorisation.

3.2 Result and null semantics

A getter may return T | null only when the requested profile attribute is missing, incomplete, or not granted. A missing but granted field should be eligible for ONE's existing completion experience; a denied field must not trigger a coercive completion prompt.

OutcomeReturn/behaviourRequired UI handling
Present and permittedTUse the value for the approved purpose.
Known condition is falsefalseTreat as verified evaluation of the boolean predicate, not lack of data.
Missing profile field, consent grantednullOffer ONE's existing completion prompt where supported, then retry after user returns.
Field not granted / permission withdrawnnull for profile getterExplain feature limitation; offer voluntary permissions review, not automatic escalation.
Invalid/expired loginExplicit auth errorRefresh once where valid, otherwise request sign-in.
Revoked/disconnected appExplicit access-revoked errorDiscard session and stop protected operations.
Network failureExplicit network errorShow retry action; do not convert to null or false.
Malformed request / server policy denialExplicit validation/access errorCorrect request or route to authorised administrator.

Boolean?/boolean | null has three meaningful states: true, false, and null. Never treat null as false for age gating, verification, employment, membership, or eligibility.

The following TypeScript-style contracts describe desired cross-platform semantics; they do not imply a production TypeScript SDK export.

TypeScript
type Nullable<T> = T | null;
type CountryCode = string;       // Prefer ISO 3166-1 alpha-2, or configured legacy OTHER
type LanguageCode = string;      // Define ISO language-code policy in backend schema
type UserName = [firstName: string | null, lastName: string | null];
type PhoneParts = [countryCode: string, nationalNumber: string];
type AddressParts = [
  premises: string | null,
  street: string | null,
  locality: string | null,
  region: string | null,
  country: string | null,
  postalCode: string | null
];
type Bitmap = PlatformNativeBitmap | DecodedRgbaBitmap;
interface DecodedRgbaBitmap { width: number; height: number; pixels: Uint8Array; }

Why phone numbers use strings: Country calling codes and subscriber numbers are identifiers, not quantities. Integers remove leading zeroes, cannot preserve +, extensions or significant formatting, and can overflow numeric representations. The live documentation already returns [country_code, phone_number] as string arrays. Preserve the exact storage and normalisation rules documented by ONE.

Why arrays preserve null slots: A six-part address must retain positional meaning even when apartment or county is absent. Do not shift components to fill gaps. For new API versions, a named object is preferable to positional arrays, while the requested existing array API remains supported.

3.4 Input validation principles

  • APP_ID: registered application identifier, not an arbitrary client-supplied namespace.
  • CLIENT_ID: public OAuth client identifier; always resolve it server-side to the authenticated registration.
  • CUSTOM_URI_SCHEME: registered callback scheme; cannot authorise revocation or disconnection by itself.
  • ORG_ID and PROJECT_ACCESS_ID: opaque identifiers, validated server-side against authorised relationships.
  • UUIDC: opaque identity handle scoped to a defined audience; never use an unverified client-supplied value as proof of identity.
  • Keys: predefined variable names where declarations are required; validate type, size, nesting and ownership.
  • Duration: strongly typed units; no ambiguous numbers without a duration unit.

4. Existing functions — user profile

All functions in this section are existing — documented in the reviewed native integration guide, subject to SDK/platform availability and live consent. The odd historical spelling of Varified is retained to match the exposed API.

4.1 Identity, avatar and name

FunctionPermissionReturnBehaviour
one.auth.data.getAvatar()avatarPlatform bitmap or nullReturns a decoded ONE profile image; documented max 256 × 256 pixels.
one.auth.data.getName()first_name, last_name[firstName, lastName] or nullReturns fixed-position name components; missing individual components remain null.
one.auth.data.getEmail()emailstring | nullReturns permitted personal email.
one.auth.data.getPhoneNumber()phone[countryCode, nationalNumber] | nullString parts without coercion to integers.
one.auth.data.getAddress()addressAddressParts | nullSix positions: premises, street, city, region, country, postal code.
one.auth.data.getCountry()addressstring | nullCountry derived from saved home address; currently uses country code or OTHER.
one.auth.data.getNationality()nationalitystring | nullNationality as permitted by scope and saved profile.
one.auth.data.getCountryOfBirth()country_of_birthstring | nullCountry of birth only; not exact birth date.
one.auth.data.getLanguages()languagesstring[] | nullUser's saved language entries.

Bitmap platform mapping (documented): Android Bitmap; iOS UIImage; macOS NSImage; browser ImageBitmap; Java AvatarBitmap; source-based runtimes may expose RGBA pixels and dimensions. Always adapt images using the platform UI layer; do not treat bitmaps as arbitrary file uploads.

4.2 Privacy-safe age and birthday checks

FunctionPermissionReturnPrecise meaning
one.auth.data.isUserTeen()date_of_birthboolean | nullUser is 13+. This does not mean aged 13–17 only.
one.auth.data.isUserLegal()date_of_birthboolean | nullUser is 18+. This is an age-threshold result, not a legal capacity guarantee in every jurisdiction.
one.auth.data.isUserAdult()date_of_birthboolean | nullUser is 25+. The name is legacy; do not assume 18–24-year-olds are minors.
one.auth.data.isUserAgeVarified()date_of_birthboolean | nullONE's identity-backed age-verification procedure passed. A self-entered DOB alone never marks this true.
one.auth.data.isUserBirthday()date_of_birthboolean | nullCalendar day matches user's birthday; current implementation uses UTC.

Hard privacy invariant: No client profile helper, REST userinfo response, log, debug payload, analytics property, SDK cache, or exception detail may expose exact date of birth or exact age. The currently reviewed integration guide expressly describes threshold-only results; historical SDK versions must not be relied on to access raw DOB.

Example — verified 18+ gate (illustrative Kotlin):

Kotlin
// Execute on a worker/coroutine after successful sign-in.
val is18Plus: Boolean? = one.auth.data.isUserLegal()
val hasVerifiedAge: Boolean? = one.auth.data.isUserAgeVarified()

when {
    is18Plus == null || hasVerifiedAge == null -> showUnavailableAgeState()
    is18Plus && hasVerifiedAge -> openRestrictedFeature()
    else -> showEligibilityOrVerificationScreen()
}

The UI functions above are application-defined placeholders. isUserAgeVarified() may offer ONE's existing age-verification action on a known false result, depending on the platform/UI integration.

4.3 Contact verification

FunctionPermissionReturnBehaviour
one.auth.data.isUserEmailVarified()emailboolean | nulltrue when saved personal email is verified.
one.auth.data.isPhoneNumberVerified()phoneboolean | nulltrue when saved personal phone number is verified.
one.auth.data.isWorkEmailVarified()work_emailboolean | nulltrue when saved work email is verified.
one.auth.data.isWorkPhoneNumberVerified()work_phoneboolean | nulltrue when saved work phone is verified.

An explicitly present unverified contact attribute returns false; an absent or withheld attribute returns null. A true verification state confirms ONE's verification mechanism, not perpetual ownership or suitability for any regulated communication.

4.4 Work profile

FunctionPermissionReturnBehaviour
one.auth.data.getWorkEmail()work_emailstring | nullPermitted work email.
one.auth.data.getWorkPhoneNumber()work_phone[countryCode, nationalNumber] | nullWork number as string components.
one.auth.data.getWorkAddress()work_addressAddressParts | nullSix-position work location.
one.auth.data.getWorkCountry()work_addressstring | nullCountry from work address.

4.5 Missing-data and verification prompts

The existing ONE UI already supports missing-profile completion for granted fields, and supported platforms expose missing-data handlers. The account completion page is provided by ONE: host applications must not collect ONE account passwords, impersonate the hosted consent flow, or bypass denial.

Plain text
App requests a field
   |
   +-- Not granted -----------------> null; no missing-data prompt
   |
   +-- Granted but missing ---------> null + optional ONE completion prompt
   |                                      |
   |                                      +--> User updates ONE profile
   |                                             |
   |                                             +--> Refresh profile / retry
   |
   +-- Granted and present ---------> value
   |
   +-- Session, server, network failure -> explicit error

For identity verification, ONE may offer a verification prompt linking to the account portal. The documented process includes trusted-ID and liveness/face-match checks; do not implement a fake local verification toggle.

5. Existing functions — encrypted application data

Status: Existing — documented (one.data.set/get/rep/del). Each entry belongs to the signed-in user and the registered application namespace and requires the applicable App data consent (attributes).

FunctionReturn conceptBehaviour
one.data.set("VARIABLE_NAME", VALUE)Success / errorCreate or overwrite an application variable.
one.data.get("VARIABLE_NAME")JSON-compatible value or nullRead an existing value; a missing key resolves to null.
one.data.rep("VARIABLE_NAME", VALUE)Success / errorReplace/upsert a value; a non-null replacement is required by the native guide.
one.data.del("VARIABLE_NAME")Success / errorRemove one variable from this user's application namespace.

The currently reviewed integration guide also describes list and remove aliases in some supported SDK contexts. Do not assume that a JSON null stored value can always be distinguished from a missing key using get alone; prefer explicit existence metadata if that distinction is required.

5.1 Storage guarantees and limits (documented)

  • Encryption at rest: AES-256-GCM, with application-derived keys.
  • Compression: DEFLATE before encryption.
  • Accepted content: JSON-compatible strings, numbers, booleans, null, arrays and objects.
  • Maximum uncompressed value: 16 KiB of UTF-8 JSON.
  • Maximum write batch: 100 keys.
  • Maximum nesting: 20 levels.
  • Maximum request body: 1.7 MB.
  • App isolation: one application cannot read another application's namespace.
  • File uploads, media blobs, data URLs, binary byte arrays and disguised files are not supported in app data.

App-variable definitions and type checking remain server-owned. set() or rep() cannot evade declaration constraints or grant boundaries.

5.2 Example (documented API shape; illustrative Kotlin)

Kotlin
// Execute after sign-in and outside the Android main thread.
one.data.set("theme", "dark")
val theme = one.data.get("theme")  // "dark" or null
one.data.rep("theme", "light")
one.data.del("theme")

Implementation recommendation: Treat set and rep as idempotent upserts for the same key/value, but document actual concurrency and conditional-write semantics before promising optimistic locking. Do not assume cross-request transactions or atomic increments.

6. Proposed functions — registered application metadata

Status: Proposed. Public branding already appears in the documented SDK login view; the following explicit accessor API is not verified as released.

FunctionSuggested typeContract
one.app.data.appDisplayName()string | nullRegistered display name, normalised for safe presentation.
one.app.data.appDescription()string | nullCurrent public description of the calling application.
one.app.data.appWebsite()string | nullVerified/public HTTPS website URL, if configured.
one.app.data.appIcon()Bitmap | nullFetched/decoded public app icon, platform-native representation.

6.1 Behaviour

  1. The SDK resolves its authenticated/registered APP_ID rather than accepting a caller-provided identity override.
  2. The server returns only public metadata explicitly configured by the application owner.
  3. Metadata may be cached with a short TTL and invalidated on app-settings changes; do not claim instant cross-device cache coherency.
  4. Missing metadata returns null; network errors still raise typed errors.
  5. Applications must not use display name, description, icon or website as proof of a legal entity or security authority.
  6. The SDK should sanitise URLs and text before rendering. Load remote artwork only from approved HTTPS locations with bounded bytes, dimensions and redirects.

Suggested metadata response:

JSON
{
  "app_id": "com.example.product",
  "display_name": "Example Product",
  "description": "A privacy-aware example application.",
  "website": "https://example.com",
  "icon_url": "https://example.com/icon.png",
  "updated_at": "2026-10-23T00:00:00Z"
}

The above is a proposed payload, not an existing ONE endpoint response.

Status: Proposed. Design these APIs as a distinct document-consent service, not as regular application data. Consent to terms is separate from granting personal-data scopes.

7.1 Exact requested API

Plain text
one.app.data.docs.isAgreed(type, slug, version)
one.app.data.docs.get(type, slug, version)
one.app.data.docs.agreeTo(type, slug, version)

7.2 Document types and versioning

TypeScript
enum docType {
  TERMS   = "TERMS",
  POLICY  = "POLICY",
  LICENCE = "LICENCE",
  OTHER   = "OTHER"
}

type DocumentVersion = string; // "1.0", "1.01", "1.001" (exact identifiers)

Do not represent versions as floating point. 1.0, 1.00, 1.01, and 1.001 may be different publication identifiers, while floating-point conversion can erase trailing zeroes or introduce rounding. Normalise and validate versions server-side using an agreed string format; avoid numeric comparison of document revisions.

7.3 Operations

FunctionSuggested returnContract
docs.get(type, slug, version)LegalDocument | nullRetrieve an immutable published version. A missing document may return null; unauthorised/private docs return explicit access errors.
docs.isAgreed(type, slug, version)boolean | nulltrue if the authenticated user has an active, verifiable acceptance of this exact version; false if definitively not accepted; null if the identity/acceptance state is unavailable.
docs.agreeTo(type, slug, version)AgreementReceiptExplicitly record an authenticated user's informed acceptance of an exact published document.
TypeScript
interface LegalDocument {
  appId: string;
  type: docType;
  slug: string;
  version: DocumentVersion;
  title: string;
  locale: string;
  contentFormat: "markdown" | "text" | "html";
  content: string;
  sha256: string;          // Digest of canonical published bytes
  effectiveAt: string;    // ISO 8601
  publishedAt: string;    // ISO 8601
  status: "published" | "superseded" | "withdrawn";
}

interface AgreementReceipt {
  receiptId: string;
  appId: string;
  documentType: docType;
  documentSlug: string;
  documentVersion: DocumentVersion;
  documentSha256: string;
  acceptedAt: string;    // Server timestamp, ISO 8601
  subject: string;       // Opaque user subject, not raw personal identity
  consentMethod: "one_hosted" | "verified_app_flow";
  locale: string;
}

7.5 Agreement lifecycle

  1. Application owner creates and publishes a document version using an authenticated administrative publishing workflow.
  2. ONE stores the immutable publication and content digest; an edited draft must be published as a new version.
  3. SDK retrieves the exact version and presents its complete contents or a trusted rendering.
  4. The user performs an explicit affirmative action, e.g. selecting Agree and continue. Passive page views or prechecked boxes must not count as consent.
  5. Server verifies identity, publisher, app ownership, document state and digest before issuing the receipt.
  6. isAgreed checks the stored receipt for that specific (app_id, type, slug, version, digest) tuple.
  7. Later document versions do not silently inherit older acceptance. Define a re-acceptance policy explicitly, with jurisdiction-specific legal review if needed.
  8. For privacy policy acknowledgements, do not incorrectly equate contractual acknowledgement with GDPR consent for processing. Track the legal basis separately.

7.6 Example (pseudocode, not a currently shipped SDK call)

TypeScript
const type = docType.TERMS;
const slug = "app-terms";
const version = "1.001";
const doc = await one.app.data.docs.get(type, slug, version);
if (!doc) throw new Error("Requested terms document is unavailable");

renderLegalDocument(doc); // Must be fully accessible and readable.

// Invoke ONLY after the user intentionally accepts the displayed document:
async function onUserPressedAgree() {
  const receipt = await one.app.data.docs.agreeTo(type, slug, version);
  await persistReceiptReference(receipt.receiptId); // Optional app-owned reference
}

Proposed backend endpoints (not currently documented):

HTTP
GET  /apps/me/metadata
GET  /apps/me/documents/{type}/{slug}/versions/{version}
GET  /apps/me/documents/{type}/{slug}/versions/{version}/agreement
POST /apps/me/documents/{type}/{slug}/versions/{version}/agreement

Never send untrusted raw HTML directly to a WebView without sanitisation and strict script/content security controls.

8. Proposed functions — extended user profile

FunctionSuggested returnContract and access policy
one.auth.data.UUIDC()string | nullUnique opaque user identification code; prefer app- or organisation-scoped pseudonymous identity rather than a globally correlatable identifier.
one.auth.data.userGender()string | nullSelf-described optional gender attribute; return only when explicitly requested and granted. Do not infer it.
one.auth.data.getLanguages.primary()string | nullUser-selected primary language from their saved preferences, subject to languages scope.
one.auth.data.isOrgEnroled(ORG_ID, PROJECT_ACCESS_ID, UUIDC)boolean | nullCheck active organisation and specified project enrollment through the server; do not trust the supplied UUIDC alone.
one.auth.data.getOrgInfo(ORG_ID)PublicOrgInfo | nullRead an explicitly public, published organisation profile.
one.auth.data.signOut()Completion / errorProposed alias for documented one.auth.signOut(); clears the current local session only.
one.auth.data.disconnectProfile(CLIENT_ID, APP_ID, CUSTOM_URI_SCHEME)DisconnectResultProposed account-connection revocation, distinct from local sign-out; requires strong server-side verification and user confirmation.

8.1 UUIDC() — user identity safety

Problem: A globally stable identifier shared across unrelated applications enables unwanted cross-app tracking. Current ONE identity tooling already documents an opaque stable sub for its authentication flow.

Recommended: Make UUIDC an opaque pairwise identifier derived from the authenticated subject and authorised audience (e.g. app or organisation), or explicitly document where it matches an existing sub. It must not contain an email, phone, DOB, national ID or reversible personal-data component.

Rules:

  • A client cannot ask the server to impersonate an arbitrary UUIDC.
  • The server determines the currently signed-in user from the token/session.
  • Org access checks must compare the supplied handle with that authenticated identity, or require privileged delegated access.
  • Reject enumeration, excessive queries and cross-tenant lookups.
  • Never log UUIDC in third-party analytics as a cross-service tracking key.

8.2 userGender()

Gender can be sensitive personal data in context. Make collection optional, purpose-specific and expressly grantable. Recommended values include a user-specified string/controlled vocabulary with a privacy-preserving prefer not to say state. Do not infer gender from name, photos or identity-document markers. Avoid mixing null (not granted/missing) with a deliberately selected privacy preference.

8.3 getLanguages.primary()

The requested syntax uses .primary() as a submethod, which means getLanguages is a callable object as well as a function in some languages. Java/Kotlin cannot implement that ergonomically without an intermediate facade. Recommended cross-platform alias:

Plain text
Requested compatibility syntax: one.auth.data.getLanguages.primary()
Recommended standard syntax:    one.auth.data.getPrimaryLanguage()

If the requested syntax is essential, implement a language-specific getLanguages facade; otherwise prefer getPrimaryLanguage() to avoid a brittle or impossible cross-platform binding. The primary language must be selected explicitly or according to a declared fallback policy, never guessed silently from nationality.

9. Proposed functions — organisation membership and public organisations

9.1 Membership eligibility

Exact requested signature:

Plain text
one.auth.data.isOrgEnroled(ORG_ID, PROJECT_ACCESS_ID, UUIDC)

Recommended policy:

  1. Verify that ORG_ID exists and the project belongs to it.
  2. Resolve authenticated user identity server-side; ensure the UUIDC argument is the same user unless caller has a dedicated administrative permission.
  3. Evaluate current organisation membership, membership status, project binding, expiry and suspension.
  4. Return true only if all required checks pass at the time of evaluation.
  5. Return false for a definitive non-membership or absent project entitlement that the caller is authorised to check.
  6. Return null only for unavailable/withheld identity context; reject unauthorised third-party enumeration with explicit errors.
  7. Enforce all protected project actions again on the backend. A UI-level true is not an access token.

Potential improved interface:

TypeScript
interface MembershipAssessment {
  enrolled: boolean;
  orgId: string;
  projectAccessId: string;
  effectivePermissions?: string[];
  expiresAt?: string | null;
  checkedAt: string;
}

A richer response should require appropriate scope and must not reveal private organisation membership to arbitrary applications.

9.2 Organisation public information

Plain text
one.auth.data.getOrgInfo(ORG_ID)

Recommended response:

TypeScript
interface PublicOrgInfo {
  id: string;
  name: string;
  displayName?: string;
  description?: string;
  website?: string;
  logoUrl?: string;
  verified?: boolean;
  publicProjects?: Array<{ id: string; title: string }>;
  updatedAt: string;
}

Only administrator-approved public fields may be returned. Never expose employee rosters, internal project IDs, ownership information, billing configuration or unlisted membership from a public organisation lookup.

10. Proposed functions — moderation and bans

10.1 Requested function

Plain text
one.auth.data.setBan(duration, date, reason)

Security classification: Privileged administrative mutation. This method must not be callable by every signed-in app/user. Its existence under auth.data should be a compatibility shim; the preferred long-term interface is a server-side one.admin.users.setBan(...) API with delegated moderation scope, tenant separation and audit logging.

10.2 Duration and permanence

You requested a permanent ban when the duration in minutes exceeds 100 days.

Plain text
100 days = 100 × 24 × 60 = 144,000 minutes

if durationMinutes > 144000:
    banKind = PERMANENT
else:
    banKind = TEMPORARY

Boundary: Exactly 144000 minutes remains temporary under your stated greater-than condition. If you intend 100 days or longer, use >= and update the contract.

TypeScript
type BanKind = "TEMPORARY" | "PERMANENT";
interface BanRequest {
  targetSubject: string;           // Required: authenticated/admin-resolved user identifier
  appId: string;                   // App-scoped by default
  durationMinutes: number;         // Integer >= 1
  effectiveAt?: string;            // ISO 8601; omission means server now
  reasonCode: string;              // Stable policy category
  reason: string;                  // Moderation explanation
  evidenceReference?: string;      // Internal controlled reference, not raw evidence
  idempotencyKey: string;
}
interface BanRecord {
  id: string;
  kind: BanKind;
  effectiveAt: string;
  expiresAt: string | null;
  reason: string;
  createdBy: string;
  createdAt: string;
}

Signature problem to resolve: setBan(duration, date, reason) omits the target user. Under the proposed alias, it can only target the currently authenticated user, which is generally unsuitable for moderation. Do not allow the calling application to mutate arbitrary accounts without an explicit, server-verified subject and scope. A more useful privileged method is setBan(targetSubject, durationMinutes, effectiveAt, reason).

10.4 Enforcement requirements

  • Require administrator service authentication, a moderation role and app/tenant-scoped authorisation.
  • Default to app-scoped bans, not global ONE account bans. Platform-wide enforcement is a separate high-trust workflow.
  • Verify policy, reason, target, duration and effective date server-side.
  • Store server-computed expiry; clients cannot decide they are unbanned by changing device clocks.
  • Apply denial to protected ONE-facing resources for the relevant app according to its moderation policy.
  • Record immutable audit evidence: actor, action, reason code, timestamp, target scope and previous/new state.
  • Provide appeal/review and unban administrative processes, with retention according to applicable policy.
  • Rate-limit requests, protect against abusive moderators, and avoid disclosing sensitive moderation evidence in public API errors.

Existing baseline: The reviewed guide describes app-scoped bans administered from the Client Users tab and exposed moderation error details. It does not establish that one.auth.data.setBan() already exists.

11. Proposed account lifecycle — sign-out and disconnect

11.1 Sign-out

Plain text
Proposed alias: one.auth.data.signOut()
Current API:   one.auth.signOut()

Current documented behaviour: clear the local app's ONE session. It does not guarantee sign-out from the system browser, revoke refresh tokens remotely or remove the application's user-data grant.

Required client handling: Clear local tokens, personally identifying view models, cached sensitive display state and active protected requests. If asynchronous sign-out is supported, complete those steps before reporting success.

11.2 Disconnect the connected profile

Plain text
one.auth.data.disconnectProfile(CLIENT_ID, APP_ID, CUSTOM_URI_SCHEME)

Status: Proposed. This is a materially stronger operation than sign-out and needs a backend revocation contract.

Proposed sequence:

  1. Require a live, authenticated user session and a deliberate action to disconnect this app.
  2. Resolve CLIENT_ID and APP_ID from server-side registration; reject any mismatch with current caller identity.
  3. Validate the callback scheme only for navigation, never as proof of consent or ownership.
  4. Present ONE-hosted confirmation specifying which app will lose access and what happens to app-specific stored data.
  5. Revoke the appropriate application's grants and refresh-token chain on the server; invalidate access at protected endpoints.
  6. Clear SDK local session/tokens, unsubscribe push or websocket streams where applicable and purge sensitive caches.
  7. Return a non-sensitive receipt/status. Data deletion or retention must follow a separate explicitly documented retention policy; disconnection must not be silently treated as irreversible deletion without notice.

Recommended return:

TypeScript
interface DisconnectResult {
  appId: string;
  disconnected: boolean;
  effectiveAt: string;
  receiptId: string;
  dataDisposition: "retained_per_policy" | "deletion_requested" | "deleted";
}

Important: A disconnected token must not be able to call the same method to obtain new access. This is an account-connection lifecycle workflow, not an OAuth callback trick.

12. Permissions and data-minimisation matrix

This matrix identifies baseline documented profile scopes and proposed extensions. Registration, consent-screen field names and backend enforcement must be updated together.

Data or operationScope / gateNull on missing/denied?Completion prompt?Notes
Namefirst_name, last_nameYesIf granted but missingFixed positions.
AvataravatarYesIf granted but missingDecoded bitmap.
Email / email verifiedemailYesIf granted but missingVerification predicate returns false for known unverified.
Personal phone / verifiedphoneYesIf granted but missingString components.
Home address / countryaddressYesIf granted but missingSame scope, country derived.
DOB-derived age and birthday flagsdate_of_birthYesIf granted but missingNever expose raw DOB.
Work email / verifiedwork_emailYesIf granted but missingDistinct from personal scope.
Work phone / verifiedwork_phoneYesIf granted but missingDistinct from personal scope.
Work address / countrywork_addressYesIf granted but missingCountry derived.
NationalitynationalityYesIf granted but missingDistinct from country of birth.
Country of birthcountry_of_birthYesIf granted but missingNever exact DOB.
LanguageslanguagesYesIf granted but missingPrimary language requires a defined profile field (proposed).
Gendergender (proposed)YesIf granted but missingOptional and purpose-specific.
App dataattributes / App dataKey missing returns nullNo profile prompt for missing keyRequires app variable declarations, where configured.
Long-lived sessionofflineN/AOAuth user decisionRefresh tokens rotate when used.
Public app metadataRegistration/visibility policy (proposed)YesNoNo account profile permission needed for public branding.
Legal-document retrievalPublished/visibility policy (proposed)Not found → nullNoReceipt lookup requires authenticated subject.
Agreement receipt writeAuthenticated user action (proposed)NoUser intentionally acceptsNot interchangeable with data-processing consent.
Organisation membershiporg.membership.read (proposed)Only for unavailable own identityNoNo third-party enrollment enumeration.
Organisation infoPublic record (proposed)Not found → nullNoPublic-only attributes.
Ban assignmentmoderation.ban.write (proposed)NoNoPrivileged backend-only gate.
Disconnect profileUser-authenticated revocation (proposed)NoONE-hosted confirmationServer-side revocation.

Registration rule: Request only the scope needed for a working user feature, clearly disclose the use, and allow optional fields to be withheld without blocking unrelated functionality.

13. Error model and recovery

Use the existing ExOneException style or platform-equivalent exceptions for transport/auth/validation failures. Extend it with stable machine-readable codes rather than parsing error-message text.

Code (existing or proposed)MeaningSuggested handling
invalid_grantInvalid/used authorization code or refresh grantRestart login; never replay consumed code.
session_expiredNo refreshable sessionReturn to ONE sign-in.
access_revokedUser disconnected or scope revokedClear sensitive local state.
insufficient_scopeApplication lacks required grantExplain limitation; route to standard permission process.
network_errorTransport unavailableRetry with bounded backoff and cancellation.
invalid_argument (proposed)Invalid identifier, duration, version or inputCorrect developer call; do not retry blindly.
document_not_published (proposed)Requested legal version unavailable for acceptanceDisplay unavailability; do not record agreement.
agreement_conflict (proposed)Version/digest mismatched or supersededFetch and display current published version.
org_access_denied (proposed)Caller cannot inspect membershipShow access denied; do not leak membership.
moderation_forbidden (proposed)Caller lacks administrative privilegesDisable admin control; audit attempt.
ban_active (proposed code)Access blocked by policyShow permitted reason/expiry and appeal path.
disconnect_requires_confirmation (proposed)No validated user confirmationOpen ONE-hosted confirmation.

HTTP baseline: The reviewed API reference associates 400 with invalid input, 401 with invalid session, 403 with missing/revoked access, 413 with oversized requests and 415 with non-JSON content.

Operational requirements: Never convert 401, 403, timeout, rate limiting, backend policy errors or corruption to null. Avoid infinite sign-in loops; apply bounded retries and idempotency keys for sensitive mutations.

14. Cross-platform implementation patterns

14.1 Android / Kotlin

The reviewed native guide shows SDK 3.2.0 and use of ExOneAndroid. The current working Kotlin/Android install pattern is:

Kotlin
// settings.gradle.kts
maven { url = uri("https://client.extremextechnology.com/repo") }

// app/build.gradle.kts — inside dependencies { ... }
implementation("com.extremex.one:exone-android:3.2.0")
Kotlin
import com.extremex.one.android.ExOneAndroid

val one = ExOneAndroid(applicationContext, "APP_ID", "CLIENT_ID")

// Show ONE's native sign-in component and handle the callback through
// the documented Activity lifecycle. Never call protected APIs before auth.

Native callbacks and sign-in wiring depend on the host Activity. Register APP_ID://callback appropriately in the Android manifest and handle both initial and subsequent callback Intents. The official guide documents attaching the client to recreated activities where necessary. Blocking profile/data reads belong on worker threads; async callbacks touching UI must switch to the main thread.

14.2 Kotlin Multiplatform

Keep domain policy and nullable result interpretation in commonMain, but delegate identity/image representations and browser/callback handling to platform-specific adapters. Do not assume Java Bitmap is available in common Kotlin code. Use an immutable shared decoded-image structure or expect/actual platform return types.

Kotlin
// Conceptual shared interface — not a shipped SDK declaration.
interface OneProfileReader {
    suspend fun is18Plus(): Boolean?
    suspend fun isAgeVerified(): Boolean?
    suspend fun getNameParts(): List<String?>?
}

14.3 Web / Next.js

Use the official browser sign-in mechanism and an authenticated server/session model. Keep token exchange, any confidential credentials, privileged moderation credentials and organisation administration on the backend. Avoid putting broad bearer tokens or personal profile payloads in publicly rendered HTML or client logs.

TypeScript
// Conceptual call flow; docs/agreement methods require implementation.
async function loadFeatureEligibility(one: OneClient) {
  const legal = await one.auth.data.isUserLegal();
  const verified = await one.auth.data.isUserAgeVarified();
  if (legal === null || verified === null) return "unknown";
  return legal && verified ? "eligible" : "ineligible";
}

OneClient above is an illustrative application type; adapt to the actual JS SDK export and callback/promise form in your installed version.

14.4 iOS / Swift

Use ASWebAuthenticationSession for sign-in and register the callback URI scheme/universal link described by ONE. Convert optional NSNumber/bool results carefully so nil remains unknown. Present age-completion and legal-agreement UIs in accessible sheets; do not infer identity from device settings.

14.5 React Native / Flutter / desktop

Use the ONE-supported source module or native bridge for the target platform, an external system browser for OAuth and a callback handler that validates state and PKCE. Images must use the platform-appropriate decoded representation. For headless applications, forward missing-data completion links to an authenticated UI rather than opening a server-side browser.

Feature-parity rule: A method should not be presented as universally supported merely because the TypeScript/Kotlin signature appears in this specification. Track builds and actual runtime tests platform by platform.

15. Worked integration scenarios

15.1 Profile display with progressive completion

  1. Authenticate with ONE.
  2. Request first_name, last_name, avatar and any optional contact scopes with stated reasons.
  3. Call getName() and getAvatar() after sign-in.
  4. If a granted profile field is missing, offer the existing ONE completion route; do not demand access to an ungranted optional field.
  5. Retry on return, after current consent is confirmed.
  6. Render partial information safely (e.g. first name only) rather than failing the whole screen.

15.2 Age-restricted experience

Plain text
isUserLegal() == true AND isUserAgeVarified() == true
     -> eligible for a verified-18+ feature (subject to other requirements)

One false, other known
     -> not yet eligible under this rule; offer ONE verification where appropriate

Either null
     -> eligibility unknown; keep restricted functionality inaccessible

Age threshold alone must never substitute for any independently required regional age-assurance, licensing or regulatory requirement.

15.3 Persisting user settings

Kotlin
one.data.set("appearance", "system")
val appearance = one.data.get("appearance")
one.data.rep("appearance", "dark")

Use platform-local storage for device-only or offline-only settings where server synchronisation is unnecessary. Do not store passwords, OAuth client secrets or oversized files in app data.

15.4 App terms re-acceptance (proposed)

  1. Product team publishes TERMS/app-terms/1.001 immutably.
  2. App fetches document and verifies success.
  3. It checks the user's receipt for exactly 1.001.
  4. If false, display the full new text and explain differences where relevant.
  5. Only the user's active confirmation invokes agreeTo.
  6. Backend records a verifiable receipt; app proceeds.
  7. If null or network failure, do not assert acceptance. Apply an explicit, legally reviewed offline policy.

15.5 Organisation-gated project access (proposed)

  1. Authenticated user enters an org-bound feature.
  2. Client requests an eligibility check for the current user and the exact project.
  3. ONE verifies org enrollment and project membership server-side.
  4. Client may show eligible UI on true.
  5. Every subsequent protected operation rechecks authorisation server-side; a cached boolean does not confer access.

15.6 Administrative ban (proposed)

  1. Authenticated and authorised moderator selects a user and an app scope.
  2. Server validates the request, including target identity, duration, reason and moderation privileges.
  3. More than 144000 minutes selects PERMANENT; otherwise compute server-side expiry.
  4. Server records a policy-bound ban and audit trail; middleware blocks affected operations.
  5. User sees the permitted reason/expiry and appeal route. Client is never trusted to implement the restriction alone.

16. Suggested SDK facade evolution

To preserve existing calls while keeping authority boundaries clear:

Plain text
one
├── auth
│   ├── signOut()                             [EXISTING]
│   └── data
│       ├── getAvatar()                      [EXISTING]
│       ├── getName()                        [EXISTING]
│       ├── isUserTeen() / isUserLegal()     [EXISTING]
│       ├── isUserAdult()                    [EXISTING]
│       ├── isUserAgeVarified()              [EXISTING]
│       ├── isUserBirthday()                 [EXISTING]
│       ├── contact, address, language...    [EXISTING]
│       ├── UUIDC()                          [PROPOSED]
│       ├── userGender()                     [PROPOSED]
│       ├── getPrimaryLanguage()             [RECOMMENDED]
│       ├── getLanguages.primary()           [REQUESTED; platform adapter]
│       ├── isOrgEnroled(...)               [PROPOSED]
│       ├── getOrgInfo(...)                  [PROPOSED]
│       ├── signOut()                        [PROPOSED alias]
│       ├── disconnectProfile(...)          [PROPOSED]
│       └── setBan(...)                      [PROPOSED privileged alias]
├── app
│   └── data
│       ├── appDisplayName()                 [PROPOSED]
│       ├── appDescription()                 [PROPOSED]
│       ├── appWebsite()                     [PROPOSED]
│       ├── appIcon()                        [PROPOSED]
│       └── docs
│           ├── get(type,slug,version)       [PROPOSED]
│           ├── isAgreed(type,slug,version)  [PROPOSED]
│           └── agreeTo(type,slug,version)   [PROPOSED]
└── data
    ├── set(key,value)                     [EXISTING]
    ├── get(key)                           [EXISTING]
    ├── rep(key,value)                     [EXISTING]
    └── del(key)                           [EXISTING]

Recommended follow-on: Formalise a separate one.admin and one.org namespace in a future major release without abruptly removing legacy aliases.

17. Security, privacy and compliance engineering

17.1 Mandatory security properties

  • Require TLS and verify remote hosts and certificate trust.
  • Use OAuth PKCE on public clients; never bundle client_secret in APK, IPA, desktop binaries or JavaScript.
  • Validate OAuth state, code lifetime, redirect URI and PKCE verifier; do not replay authorization codes.
  • Store and rotate refresh tokens securely; replace the persisted token after each successful refresh.
  • Revalidate scope, user identity, organisation membership and revocation server-side for protected operations.
  • Treat callback URI schemes as routing identifiers, not authorisation credentials.
  • Avoid logging profile data, DOB-derived internal values, tokens, full addresses, contact information and legal-agreement evidence in telemetry.
  • Apply rate limits and audit logging to privileged actions and agreement receipts.
  • Isolate per-user/per-app storage namespaces.
  • Prevent unsafe HTML/script execution in document rendering.
  • Provide accessible consent and missing-data completion experiences.

17.2 Privacy controls

  • Date-of-birth minimisation: never return exact DOB or age from this API.
  • Purpose limitation: request and retain only fields necessary for features.
  • User choice: distinguish missing data from denied consent, and avoid repeated prompts after denial.
  • Revocation: ensure withdrawn permission blocks future protected reads even if cached data exists locally.
  • Sensitive demographics: gender and nationality require appropriately justified access; no derived demographic inference.
  • Identity correlation: pairwise/tenant-scoped UUIDC over global tracking IDs whenever possible.
  • Document auditability: associate acceptance with immutable document digest, version and server time.
  • Legal caveat: GDPR and other applicable laws can impose additional obligations; legal-document consent, data-processing consent and age verification are separate concepts.

17.3 Threat model checkpoints

ThreatControl
Malicious app probes denied profile fieldServer-enforced live consent; field omitted/null.
Compromised client submits someone else's UUIDCBind identity to session; reject forged targets.
Ordinary app submits setBanBackend moderator-only permission gate.
App falsely marks a user age verifiedONE-owned identity verification state only.
Tampered terms content during acceptanceImmutable publication + digest and receipt validation.
Redirect scheme spoofingPKCE, state, exact registered callback and external browser.
Refresh-token reuseRotation and revocation checks.
Stale offline membership entitlementRecheck all protected actions on backend.
Untrusted document markupSanitised rendering, script disabled, content policy.
Network failures hidden as nullTyped errors and transparent UI recovery.

18. Verification and quality-assurance matrix

Test IDTest caseExpected outcome
AUTH-01Normal browser sign-inValidated callback creates session.
AUTH-02Modified state / PKCE mismatchAuthentication denied; no session.
AUTH-03Reuse consumed codeRejected.
AUTH-04Rotated refresh token reusedRejected, secure session recovery.
PROFILE-01Optional field deniedRelevant getter returns null, no coercive completion prompt.
PROFILE-02Granted field missingnull and ONE completion flow where supported.
PROFILE-03Value present but unverifiedRelevant verification returns false.
PROFILE-04Exact DOB requested via SDK/RESTNever exposed.
PROFILE-05Age 12 / 13 / 17 / 18 / 24 / 25Correct 13+/18+/25+ threshold matrix.
PROFILE-06Birthday near UTC midnightBehaviour matches documented UTC calendar.
PROFILE-07Phone with leading zeroesStrings preserve all digits.
PROFILE-08Sparse addressSix slots preserved with null positions.
PROFILE-09Missing avatar / huge source imagenull or safely bounded bitmap, no resource exhaustion.
DATA-01Set/get/replace/deleteRound-trip and deletion correct.
DATA-02Cross-user/app readDenied or isolated.
DATA-03Invalid declared variable typeExplicit validation error.
DATA-04Oversized value/file-like payloadCorrect rejection and no partial corrupt write.
DOC-01Exact 1.0 vs 1.001Different receipt keys.
DOC-02Accept without user actionRejected.
DOC-03Tamper document after publishImmutable digest check rejects mutation.
DOC-04Re-accept current versionIdempotent outcome with consistent receipt.
ORG-01Authenticated user is enrolled in org but not projectfalse.
ORG-02Client spoofs a different UUIDCDenied without leaking membership.
ORG-03Revoked organisation membershipProtected operation denied.
BAN-01Duration = 144000 minutesTEMPORARY under > rule.
BAN-02Duration = 144001 minutesPERMANENT.
BAN-03Ordinary user invokes ban APIForbidden; audited.
DISC-01Local signOutClears local session; consent not silently revoked.
DISC-02Confirmed disconnectGrants revoked; protected calls fail; data retention policy respected.
NET-01Offline or timeoutExplicit network error, never eligibility false.

Release verification: Run unit tests, integration tests, consent-revocation tests, security reviews and real-device testing on each supported SDK platform. Do not mark platform parity complete based only on shared source code compiling.

19. Delivery plan and acceptance criteria

Phase 1 — Baseline consistency

  • Freeze a canonical inventory of 3.2.0 exported SDK symbols per platform.
  • Document null/error handling and keep DOB exposure prohibited at every layer.
  • Align existing helpers and return types; retain spelling aliases where already shipped.
  • Add shared contract tests for age thresholds, personal/work scope enforcement and app-data operations.

Phase 2 — Public app metadata

  • Implement secure public metadata read, safe icon rendering and cache invalidation.
  • Add platform-specific decoded image adapters and accessibility fallbacks.
  • Document precise availability and installation versions.
  • Implement document publication, exact string versions, content digests and per-user acceptance receipts.
  • Provide audit export, supersession rules and failure recovery.
  • Validate intentional user acceptance in each UI platform.

Phase 4 — Extended profile and organisation APIs

  • Define gender and selected-primary-language storage/permissions.
  • Define UUIDC identity scope and org/project access checks.
  • Implement anti-enumeration checks, organisation public profiles, membership cache policies and server-side enforcement.

Phase 5 — Moderation and disconnection

  • Design explicit privileged moderation principals, scopes, reason codes, review and audit workflows.
  • Implement disconnect confirmation and grant/token revocation.
  • Keep local sign-out and remote disconnect semantically distinct.

Phase 6 — Publication and observability

  • Publish versioned API reference, migration guides, SDK generated examples and release notes.
  • Measure success/error/latency by operation without collecting personal content in logs.
  • Complete security/privacy reviews and real-device/platform certification checks.

Definition of done

A proposed method is considered shipped only when all are true: backend contract exists; access policy is enforced; SDK implementation is available in a published version; platform-specific types are validated; test cases pass; errors are documented; the main developer documentation is updated; and a migration/release note identifies its availability.

20. Developer quick reference

Plain text
// Existing user profile
one.auth.data.getAvatar()
one.auth.data.getName()
one.auth.data.isUserTeen()                  // 13+
one.auth.data.isUserLegal()                 // 18+
one.auth.data.isUserAdult()                 // 25+
one.auth.data.isUserAgeVarified()           // ONE identity-verified age
one.auth.data.isUserBirthday()              // current UTC birthday match
one.auth.data.isUserEmailVarified()
one.auth.data.isPhoneNumberVerified()
one.auth.data.getEmail()
one.auth.data.getPhoneNumber()              // [callingCode, number] strings
one.auth.data.getAddress()                  // 6-part address
one.auth.data.getCountry()
one.auth.data.getWorkEmail()
one.auth.data.getWorkPhoneNumber()
one.auth.data.isWorkEmailVarified()
one.auth.data.isWorkPhoneNumberVerified()
one.auth.data.getNationality()
one.auth.data.getWorkAddress()
one.auth.data.getWorkCountry()
one.auth.data.getCountryOfBirth()
one.auth.data.getLanguages()

// Existing app data
one.data.set("KEY", VALUE)
one.data.get("KEY")
one.data.rep("KEY", NON_NULL_VALUE)
one.data.del("KEY")

// Existing session method
one.auth.signOut()

// Proposed public app info
one.app.data.appDisplayName()
one.app.data.appDescription()
one.app.data.appWebsite()
one.app.data.appIcon()

// Proposed legal-doc consent
one.app.data.docs.get(docType.TERMS, "app-terms", "1.001")
one.app.data.docs.isAgreed(docType.TERMS, "app-terms", "1.001")
one.app.data.docs.agreeTo(docType.TERMS, "app-terms", "1.001")

// Proposed profile and org methods
one.auth.data.UUIDC()
one.auth.data.userGender()
one.auth.data.getLanguages.primary()       // requested; binding design needed
one.auth.data.getPrimaryLanguage()          // recommended cross-platform alias
one.auth.data.isOrgEnroled(ORG_ID, PROJECT_ACCESS_ID, UUIDC)
one.auth.data.getOrgInfo(ORG_ID)

// Proposed account lifecycle and privileged moderation
one.auth.data.signOut()                     // forwarding alias
one.auth.data.disconnectProfile(CLIENT_ID, APP_ID, CUSTOM_URI_SCHEME)
one.auth.data.setBan(durationMinutes, date, reason) // privileged only; signature needs target resolution

21. Canonical references

  • ExtremeX ONE Client Integration Guide: https://client.extremextechnology.com/docs — reviewed 23 October 2026; baseline SDK 3.2.0 and current behaviour for native profile helpers, age checks, app data, login/callback and missing-data prompts.
  • ExtremeX ONE account: https://one.extremextechnology.com/account — profile completion and age-verification destination referenced in the live guide.
  • OAuth 2.0 for Native Apps: RFC 8252 — https://www.rfc-editor.org/rfc/rfc8252
  • Proof Key for Code Exchange (PKCE): RFC 7636 — https://www.rfc-editor.org/rfc/rfc7636

Final contract notice

This document is an advanced integration specification and implementation handoff, not a claim that all proposed APIs already exist. Sections explicitly tagged Existing — documented reflect behaviour reviewed from the public documentation. Sections tagged Proposed or Recommended are design requirements for future ExtremeX ONE SDK and backend releases. Production consumers must use only methods confirmed by their installed SDK/API version.