Dart Types Reference

Every public type in neuctra_authix_dart_package. All of them come from the single package import — there are no sub-imports.

Dart
import 'package:neuctra_authix_dart_package/neuctra_authix_dart_package.dart';

How null works here

Parameter classes serialise with toJson(), and null fields are omitted from the request body — the same way JSON.stringify drops undefined in the JavaScript SDK. A null therefore means "leave unchanged", not "clear this field".

Client

NeuctraAuthix

The client. One positional config plus two optional named arguments.

Dart
1final authix = NeuctraAuthix(
2  config, {
3  http.Client? client,      // bring your own — BrowserClient, a mock, a retrying wrapper
4  SessionStore? session,    // share one cookie jar between clients
5});
6
7authix.appId;      // String
8authix.baseUrl;    // String — trailing slashes stripped
9authix.keyType;    // ApiKeyType.publishable | ApiKeyType.secret
10authix.keyPrefix;  // String — 'pk_live_a1b2c3d4'. Safe to log.
11authix.appName;    // String?
12authix.timeout;    // Duration
13authix.session;    // SessionStore
14authix.close();    // releases the client, if the SDK created it
15
16authix.toString(); // masks the key: 'sk_live_e5f6a7b8…cccc'

NeuctraAuthixConfig

Immutable configuration. Also exposes copyWith(); toString() masks the key.

FieldTypeNotes
appIdStringRequired. Every route is scoped to one app.
publishableKeyString?pk_live_… — safe to ship in an app. Supply this or secretKey, not both.
secretKeyString?sk_live_… — full account authority. Server-side only.
baseUrlStringDefaults to the production API. A trailing slash is stripped.
appNameString?Optional label. Cosmetic.
timeoutDurationPer-request timeout. Defaults to 30 seconds.
apiKeyString?Removed in v2 — kept only so an upgrade throws with an instruction instead of silently sending an unclassifiable key.

ApiKeyType · ParsedApiKey · parseApiKey · maskApiKey

Key parsing and misuse guards. These run before any network call, so the wrong kind of key fails immediately rather than working with more privilege than intended.

FieldTypeNotes
ApiKeyTypeenumpublishable | secret. Each carries .code — 'pk' or 'sk'.
ParsedApiKey.typeApiKeyTypeWhich authority the key carries.
ParsedApiKey.envString'live' or 'test'.
ParsedApiKey.prefixStringThe lookup handle, e.g. 'pk_live_a1b2c3d4'. Not secret — safe to log.
parseApiKey(raw)ParsedApiKey?null for a missing or malformed key.
maskApiKey(raw)StringPrefix plus the last four characters.
Dart
1// Parse a key locally, without contacting the API.
2final parsed = parseApiKey('pk_live_a1b2c3d4_…');
3
4parsed?.type;    // ApiKeyType.publishable
5parsed?.env;     // 'live'
6parsed?.prefix;  // 'pk_live_a1b2c3d4' — the lookup handle, not a secret
7
8// null for a missing or malformed key, so you can reject it early.
9parseApiKey('nonsense'); // null
10
11// Render a key safely for logs.
12maskApiKey(key); // 'pk_live_a1b2c3d4…9999'

Pagination

Page<T>

What every list and search returns. It extends Iterable<T>, so a page is its records.

FieldTypeNotes
dataList<T>The records — raw maps unless itemParser is supplied.
hasMoreboolWhether the server holds further records.
nextCursorString?Pass back as cursor for the next page. null on the last page.
totalintRecords in this page — not how many exist. Reads totalFetched or totalItems, whichever the endpoint sent.
successboolThe API's success flag.
messageString?The API's message, when it sent one.
rawMap<String, dynamic>The undecoded response body, for anything not surfaced above.
Page.empty()Page<T>An empty page, useful as a seed value in UI state.
Dart
1final page = await authix.getUserData(
2  GetUserDataParams(userId: userId, limit: 50),
3);
4
5// A Page IS an Iterable of its records.
6for (final record in page) {
7  print(record['title']);
8}
9
10page.length;      // records in this page
11page.isEmpty;     // from Iterable
12page.first;       // from Iterable
13page[0];          // indexed access
14page.hasMore;     // bool
15page.nextCursor;  // String? — pass back as cursor
16page.total;       // int — records in this page, as the API reported it
17page.raw;         // Map<String, dynamic> — the undecoded body
18
19Page<Map<String, dynamic>>.empty(); // a seed value for UI state

maxPageLimit · defaultPageLimit · normalizeLimit

The server's bounds, exposed so your UI can respect them.

FieldTypeNotes
maxPageLimitconst int100 — the ceiling on a single response.
defaultPageLimitconst int20 — what the API uses when limit is omitted.
normalizeLimit(limit)int?Clamps a requested page size. A value above 100 is clamped, not rejected; 0 or negative falls back to 20; null is left out so the server applies its own default.

iteratePages · iterateItems · pages

Cursor traversal as a Stream. Every iterate* method on the client is built on these, and they guard against a page that claims hasMore but returns no cursor — without that check the traversal would refetch page one forever.

Dart
1// Every iterate* method returns a Stream, so rows render as they arrive.
2await for (final record in authix.iterateUserData(
3  GetUserDataParams(userId: userId),
4  maxPages: 10,
5)) {
6  print(record['title']);
7}
8
9// Walk any cursor-taking method yourself.
10await for (final page in authix.pages(
11  (cursor) => authix.getUserData(
12    GetUserDataParams(userId: userId, cursor: cursor),
13  ),
14)) {
15  print('${page.length} records');
16}

ItemParser<T>

The factory signature the paginated methods accept to build your own models. Without one, T must be Map<String, dynamic>.

Dart
1typedef ItemParser<T> = T Function(Map<String, dynamic> json);
2
3// Your own model
4final notes = await authix.getUserData<Note>(
5  GetUserDataParams(userId: userId),
6  itemParser: Note.fromJson,
7);
8
9// Or the built-in record shape, which types version for you
10final items = await authix.getUserData<DataItem>(
11  GetUserDataParams(userId: userId),
12  itemParser: DataItem.fromJson,
13);

Auth parameters

SignupParams

Passed to signupUser.

FieldTypeNotes
nameStringRequired.
emailStringRequired.
passwordStringRequired.
usernameString?Optional handle.
phoneString?Optional.
addressString?Optional.
avatarUrlString?Optional.
isActivebool?Optional.
roleString?Optional.
extraMap<String, dynamic>Any further fields your app stores on the user record. Defaults to empty.

LoginParams

Passed to loginUser.

FieldTypeNotes
emailStringRequired.
passwordStringRequired.

UpdateUserParams

Passed to updateUser. userId travels in the path. appId is no longer a field — the client supplies it, so it can never disagree with the app the client is scoped to.

FieldTypeNotes
userIdStringRequired.
name · username · email · phone · address · avatarUrlString?Optional profile fields.
passwordString?Optional — bypasses the currentPassword check; prefer changePassword.
isActivebool?Optional.
roleString?Optional.
settings · packageInfo · notifications · extraInfodynamicOptional structured fields.
extraMap<String, dynamic>Any further fields to write.

ChangePasswordParams

Passed to changePassword. userId travels in the path, so only the passwords are serialised.

FieldTypeNotes
userIdStringRequired.
currentPasswordStringRequired — verified server-side.
newPasswordStringRequired.

DeleteUserParams

Passed to deleteUser.

FieldTypeNotes
userIdStringRequired.

User record parameters

AddUserDataParams

Passed to addUserData.

FieldTypeNotes
userIdStringRequired.
dataCategoryStringRequired. Lower-cased by the server.
dataMap<String, dynamic>Required — flattened into the request body.
parentIdString?Optional parent record, for order → line-item shapes.

GetUserDataParams

Passed to getUserData and iterateUserData. Renamed from GetUserAllDataParams in v2; the old name remains as a deprecated alias.

FieldTypeNotes
userIdStringRequired.
categoryString?Restrict to one category.
parentIdString?Restrict to the children of one record.
limitint?Page size. Defaults to 20 server-side, capped at 100.
cursorString?nextCursor from the previous page. Ignored by iterateUserData.

GetSingleUserDataParams

Passed to getSingleUserData.

FieldTypeNotes
userIdStringRequired.
dataIdStringRequired.

SearchUserDataParams

Passed to searchInUserData.

FieldTypeNotes
userIdStringRequired.
qString?Substring match across the whole record.
categoryString?Restrict to one category.
keysMap<String, dynamic>?Exact field match, e.g. {'status': 'paid'}.
limit · cursorint? · String?Pagination.

UpdateUserDataParams

Passed to updateUserData.

FieldTypeNotes
userIdStringRequired.
dataIdStringRequired.
dataMap<String, dynamic>Required — fields to write. Omitted fields are left alone.
versionint?The version you last read. Omit it and the write always wins; supply it and a competing change raises VersionConflictError.

DeleteUserDataParams · DeleteManyUserDataParams

FieldTypeNotes
DeleteUserDataParams.userId · .dataIdStringBoth required.
DeleteManyUserDataParams.userIdStringRequired.
DeleteManyUserDataParams.dataIdsList<String>Required — up to 100 ids, removed in one transaction.

BatchParams · BatchOperation

Passed to batch(). Use the named constructors rather than raw maps — the shape each kind needs differs, and getting it wrong would otherwise be a runtime 400.

FieldTypeNotes
BatchParams.userIdStringRequired.
BatchParams.operationsList<BatchOperation>Required — up to 50.
BatchOperation.create{dataCategory, data, parentId?}Insert a new record.
BatchOperation.update{id, data, version?}Update an existing record, optionally version-guarded.
BatchOperation.delete{id}Remove a record.

App data parameters

AddAppDataParams

Passed to addAppData.

FieldTypeNotes
dataCategoryStringRequired — travels in the URL path.
dataMap<String, dynamic>Required — sent as the body verbatim. No envelope, and no appId is merged in.

GetAppDataParams · SearchAppDataParams

FieldTypeNotes
GetAppDataParamscategory?, limit?, cursor?All optional.
SearchAppDataParamsq?, category?, keys?, limit?, cursor?All optional.

UpdateAppDataParams

Passed to updateAppData.

FieldTypeNotes
dataIdStringRequired.
dataMap<String, dynamic>Required — sent as the body.
versionint?Optional optimistic concurrency guard.

DeleteAppDataParams

Passed to deleteAppData.

FieldTypeNotes
dataIdStringRequired.

GetAllAppUsersParams · SearchAllAppUsersParams · GetAllAppUsersDataParams · SearchAllAppUsersDataParams

The across-all-users parameter objects. All fields optional.

FieldTypeNotes
GetAllAppUsersParamslimit?, cursor?Passed to getAllUsersFromApp and iterateAllUsers.
SearchAllAppUsersParamsq?, keys?, limit?, cursor?keys is restricted to id, username, name, email, phone, address, role, isVerified, isActive.
GetAllAppUsersDataParamscategory?, limit?, cursor?Passed to getAllUsersDataFromApp.
SearchAllAppUsersDataParamsq?, category?, keys?, limit?, cursor?Passed to searchInAllAppUsersData.

Responses

CheckUserResponse

Returned by checkIfUserExists.

FieldTypeNotes
successboolBackend success flag.
existsboolWhether the user is registered for this app.

CheckSessionResponse

Returned by checkUserSession.

FieldTypeNotes
authenticatedboolWhether an end user is signed in on this client.
userMap<String, dynamic>?The signed-in user, when authenticated.
userIdString?Shorthand for user?['id'].

DataItem

One stored record, user or app-wide — they share a shape. Replaces AppDataItem, which remains as a deprecated alias.

FieldTypeNotes
idStringRecord ID.
dataCategoryStringThe category it was filed under.
versionintBumped on every write. Pass it back on update.
createdAt · updatedAtDateTime?Parsed timestamps, when the API sent them.
parentIdString?Parent record, when created with one.
operator []dynamicRead a payload field: item['title'].
payloadMap<String, dynamic>The payload with the identity fields stripped out.
fieldsMap<String, dynamic>The full decoded record.
DataItem.fromJsonItemParser<DataItem>Pass it as itemParser to get typed records from a Page.

DataItemResponse

Returned by every write that stores or changes a single record.

FieldTypeNotes
successboolBackend success flag.
messageString?The API's message, when it sent one.
dataDataItem?The stored record.
idString?Shorthand for data?.id.
versionint?Shorthand for data?.version. Keep it to update the record next.
rawMap<String, dynamic>The undecoded response body.

Errors

AuthixException

The base type for every failure. NeuctraAuthixException remains as an alias, so v1 code that wrote `on NeuctraAuthixException` still compiles.

FieldTypeNotes
messageStringBackend message, transport error, or a generic fallback.
statusintHTTP status; 0 when no response was received.
codeString?Machine-readable code from the API, e.g. 'VERSION_CONFLICT'.
payloadMap<String, dynamic>The decoded response body.
isNetworkError · isAuthErrorboolConvenience predicates.

The hierarchy

Failures are mapped onto the most specific subclass the status code and error code allow.

TypestatusWhen
ConfigurationErrorBad client setup or a missing required argument. Thrown before any request.
NetworkErrorConnection failure, timeout, or DNS error.
ValidationError400Rejected as invalid, including a filter on a non-searchable field.
AuthenticationError401Missing, malformed, expired or revoked credential.
NoUserSessionError401Subclass of AuthenticationError — the endpoint acts on the signed-in user, but nobody is signed in.
InsufficientScopeError403Publishable key on a secret-key endpoint. Carries .hint.
PermissionDeniedError403Authenticated but not permitted — unverified account, plan limit reached.
NotFoundError404The app, user, or record does not exist under this account.
VersionConflictError409The record changed since you read it. Carries .currentVersion and .expectedVersion; nothing was written.
RateLimitError429Rate limited or quota exhausted. Carries .resetDate.
ServerError5xxThe API failed to process the request.
Dart
1try {
2  await authix.updateUserData(
3    UpdateUserDataParams(
4      userId: userId,
5      dataId: dataId,
6      data: {'status': 'shipped'},
7      version: 3,
8    ),
9  );
10} on VersionConflictError catch (e) {
11  e.currentVersion;   // int? — where the record is now
12  e.expectedVersion;  // int? — what you sent
13} on InsufficientScopeError catch (e) {
14  e.hint;             // String? — which credential the endpoint needs
15} on RateLimitError catch (e) {
16  e.resetDate;        // String? — when the quota resets
17} on AuthixApiError catch (e) {
18  e.status;           // int
19  e.code;             // String? — 'VERSION_CONFLICT', 'INSUFFICIENT_SCOPE', …
20  e.payload;          // Map<String, dynamic> — the decoded body
21} on AuthixException catch (e) {
22  // The base type — catches configuration and network failures too.
23  e.message;
24}

Session

SessionStore

The cookie jar that stands in for the browser's automatic cookie handling. It lives in memory — persist sessionCookie yourself.

Dart
1authix.session.hasSession;            // bool
2authix.session.sessionCookie;         // String? — persist this
3authix.session.cookies;               // Map<String, String>, unmodifiable
4authix.session.cookieHeader;          // String? — what gets sent
5
6authix.session.setSessionCookie(v);   // restore a persisted session
7authix.session.setCookie(name, v);    // seed any cookie
8authix.session.clearSession();        // drop the Neuctra Authix session cookie only
9authix.session.clear();               // drop everything
10
11SessionStore.sessionCookieName;       // 'authix_user_session'

On Flutter Web this stays empty

Pass a BrowserClient with withCredentials = true and the browser holds the HTTP-only cookie itself. session.hasSession will read false even while the user is signed in — trust checkUserSession() instead.

Escape hatch

SDKRequestOptions · rawRequest

Reach an endpoint the SDK does not wrap, with the same headers, cookie handling and error mapping.

FieldTypeNotes
methodStringRequired. 'GET', 'POST', 'PATCH', …
pathStringRequired. Appended to baseUrl.
dataMap<String, dynamic>?JSON body. Sent on every method except GET.
queryMap<String, dynamic>?Query parameters. null values are dropped.
extraHeadersMap<String, String>Extra headers. Defaults to empty.
injectAppIdboolMerge the configured appId into the body. Defaults to true — turn it off for routes that carry the app id in their path, or it lands in the stored payload.
Dart
1final result = await authix.rawRequest(
2  const SDKRequestOptions(
3    method: 'POST',
4    path: '/custom/endpoint',
5    data: {'foo': 'bar'},
6    query: {'verbose': true},
7    extraHeaders: {'x-trace-id': 'abc123'},
8    injectAppId: true,
9  ),
10);

appId is overridable

On routes that inject it, request bodies are built as {appId, ...data}, so a field literally named appId inside your data wins over the configured one. Avoid appId, dataCategory, parentId and version as field names in records you store.

Differences from the JavaScript SDK

  • Errors are a typed class hierarchy, not plain thrown objects — catch the case you handle instead of switching on a status code.
  • Cursor traversal is exposed as a Stream, so rows can render as they arrive.
  • logoutUser does not reload the page — it calls your onLoggedOut callback, and clears the local session even if the server call fails.
  • A malformed or mismatched key throws at construction rather than on the first request.
  • Nothing is ever written to the console.

Related