iOS SDK API
Functions, options, parameters, return values, and propagation helpers for the Anectico Swift SDK.
On this page
This is the public Swift API for the native Anectico iOS SDK. It supports iOS 15 and later.
configure throws AnecticoConfigurationError for invalid options; telemetry calls made before
configuration remain safe no-ops with a log warning. Event/error network work runs off the calling thread.
Use a project key with ingest:write and analytics:write. The native SDK does not record replay.
Configure the SDK
import Anectico
try Anectico.configure(
AnecticoOptions(
apiKey: "an_...",
environment: "production",
release: "com.acme.Shop@2.4.1+318",
dist: "318"
)
)
| API | Parameters | Returns | Behavior |
|---|---|---|---|
Anectico.configure(options) |
AnecticoOptions |
throws; Void |
Validates options, then configures identity, sessions, event queue, error transport, crash handlers, lifecycle hooks, and timers. If the app is already active, emits its missed $app_opened exactly once. Repeated calls are ignored; calls while shutdown is still draining throw. Ordinary configuration preserves analytics withdrawal across restart. |
Anectico.flush(completion:) |
callback taking Bool |
Void |
Starts an asynchronous diagnostic-event flush and hands the completion whether every batch it attempted was accepted. See Knowing whether your events arrived. |
Anectico.shutdown(completion:) |
callback taking Bool |
Void |
Stops timers/hooks, flushes queued events, releases state, and permits reconfiguration after its completion fires. The completion carries the final flush's outcome, like flush. |
Anectico.disableAnalytics() |
— | Bool |
Stops analytics admission/retries and persists withdrawal. true confirms the withdrawal marker and queue purge; see below for failure handling. |
Anectico.configure(options, resumeAnalyticsCollection: true) |
AnecticoOptions; explicit renewed consent |
throws; Void |
After shutdown completion, purges withdrawn events before clearing the marker and creating a fresh client. |
Anectico.stats() |
— | AnalyticsStats? |
Delivery counters — recorded, delivered, dropped, queued — or nil before configure. |
Anectico.onDeliveryError(_:) |
handler taking DeliveryError, or nil |
Void |
Registers a handler called once per permanently discarded batch with status, dropped, and reason. Safe to call before configure. |
Knowing whether your events arrived
flush answers one question: was everything the SDK had queued accepted? It reports success only
when every batch it attempted was accepted, and finding an empty queue is a success — nothing was
left unaccepted. Errors and crash reports travel their own pipeline and are not covered by this
answer.
A failure has two shapes, and Anectico.stats() separates them:
| What happened | Your events | flush |
stats()?.queued |
drop callback |
|---|---|---|---|---|
Permanently rejected — a bad request, or a key that is revoked, wrong, or missing the analytics:write scope |
discarded, never retried | failure | excludes refused positions | fires once |
| Temporarily unavailable — no network, rate limited, or a server error | still queued for the next flush | failure | includes them | silent |
Anectico.stats() reports recorded, delivered, dropped, and queued, and recorded always equals the
other three added together. delivered counts positions acknowledged queued in a complete version-one
capture ledger, not unique stored rows or immediate query visibility. queued includes in-flight events.
A mixed receipt retires queued and explicitly refused positions while preserving uncertain original
IDs, timestamps, identities and payloads ahead of unsent events. The durable spool retains those
uncertain events for recovery after restart. Malformed, oversized (over 64 KiB), incomplete or
contradictory receipts at any HTTP status retain the entire affected chunk. HTTP 200 alone cannot
claim delivery, and an untyped HTTP 4xx cannot authorize a drop. Without a server hint, consecutive uncertain attempts back off from one second, doubling up to
60 seconds and resetting after a fully settled receipt;
server Retry-After hints are capped at 60 seconds. The default HTTP attempt has a 15-second wait bound.
OTLP error and crash delivery uses its separate transport policy.
Session and identity changes remain effective in memory when local persistence fails. Logging out
rotates both identities even if storage cannot be cleared; a backward clock change starts a new
session. Property serialization stops at depth 32 and emits [MaxDepth] for deeper values. HTTP
redirects are rejected so event credentials are sent only to the configured endpoint.
Anectico.onDeliveryError(_:) fires once per discarded batch with the response HTTP status (including 200 for ledger refusals), how many events were
lost, and a stable lower-case reason. Ledger refusals use invalid_event, quota_exceeded, or
mixed_rejection when one chunk has multiple refusal causes. Typed request refusals use
bad_request, unauthorized, forbidden, or payload_too_large. Local drops report status 0: queue_overflow (the queue filled up and the oldest events were evicted) and
not_serializable (an event's properties could not be encoded). collection_disabled marks withdrawal
of pending or uncertain positions. A temporary failure alone does not fire it. The handler runs
outside the queue and bookkeeping locks, on the caller thread for local drops or the flush dispatcher
for delivery outcomes.
Capturing does not wait for network delivery: capture, identify, group, and screen serialize and persist the queued event, then return, so the delivery outcome reaches you through the three signals above and never through
their own return value.
Anectico.onDeliveryError { error in
print("lost \(error.dropped) events: \(error.reason.rawValue) (HTTP \(error.status))")
}
Anectico.flush { accepted in
if !accepted, let stats = Anectico.stats() {
// stats.queued > 0 means a retry is pending; otherwise the events are gone.
}
}
Withdraw analytics collection
Call Anectico.disableAnalytics() when analytics consent is withdrawn. It blocks subsequent
capture, screen, identify, group and analytics reset operations, stops the periodic analytics
timer, discards pending events, and records collection_disabled with status 0. SDK lifecycle
events also stop being admitted. Identity and group state are not changed by refused analytics calls.
The method performs synchronous local disk I/O but does not wait for network delivery, so a delivery
error callback may invoke it safely. Use flush(completion:) outside that callback to observe final
counters after an already-admitted request settles.
Already-admitted requests may finish. Validated queued/refused receipt positions keep their actual outcomes; uncertain positions and later unsent chunks are discarded without retry. A discarded uncertain event may already have reached the server. Withdrawal neither erases remote data nor stops the separate error, crash and OTLP producers.
The returned Bool confirms both the persisted withdrawal marker and deletion of the analytics
spool. If it is false, collection still stops in this configured process, but disk cleanup or marker
persistence failed: retry disableAnalytics() and do not assume restart safety until it returns
true. Calling it before configuration returns false. Repeated calls retry the disk operation
without reopening admissions or double-counting discarded events.
Ordinary configure(options) respects the durable marker after a restart. Only after obtaining new
consent should the application wait for shutdown completion, then call
try Anectico.configure(options, resumeAnalyticsCollection: true). Renewal removes the old spool even if the marker is absent
before clearing the marker; filesystem failure throws and leaves the SDK unconfigured. Never set
that argument automatically on every launch. React Native and Flutter expose corresponding awaited disableAnalytics and explicit renewed-consent configuration controls; see their SDK references.
AnecticoOptions
Only apiKey is required. Invalid endpoints, timers, capacities, frame limits, and non-finite or
out-of-range sampling values throw AnecticoConfigurationError rather than being clamped.
| Option | Type/default | Purpose |
|---|---|---|
apiKey |
String; required |
Key sent to error and event endpoints. |
endpoint |
String; https://api.anectico.com |
Base URL for /v1/traces and /api/v1/capture. |
environment |
String; development |
deployment.environment resource value. |
release |
String?; service version when real |
Regression and symbol-artifact identifier. |
dist |
String; empty |
Build/artifact discriminator. |
serviceName |
String?; bundle ID |
service.name. |
serviceVersion |
String?; bundle marketing version |
service.version. |
flushAt |
Int; 20 |
Event-count flush threshold. |
flushIntervalMs |
Int; 5000 |
Foreground-only periodic event flush; zero disables the timer. |
maxStackTraceFrames |
Int; 50 |
Maximum frames per error. |
breadcrumbCapacity |
Int; 100 |
Ring-buffer capacity. |
maxQueueSize |
Int; 10000 |
Diagnostic-event queue cap; oldest entries drop at the cap. |
errorSampleRate |
Double; 1 |
Non-fatal error sampling in the inclusive range 0–1. |
enableCrashReporting |
Bool; true |
Install uncaught NSException and fatal-signal handlers. |
debug |
Bool; false |
Emit SDK diagnostics through Apple logging. |
Identity, accounts, and events
| Method/property | Parameters | Returns | Behavior |
|---|---|---|---|
Anectico.identify(distinctId, set:) |
stable ID; optional person properties | Void |
Links the anonymous ID to a known person and queues identify. |
Anectico.group(type:key:set:) |
account type/key; optional properties | Void |
Records membership and queues $groupidentify. |
Anectico.capture(event, properties:) |
event name; properties | Void |
Queues a diagnostic event with current person/session/groups. |
Anectico.screen(name, properties:) |
screen name; properties | Void |
Queues $screen with $screen_name. |
Anectico.reset() |
— | Void |
Logout: creates a new anonymous ID, clears groups, rotates the session, and clears global error-user context and breadcrumbs. |
Anectico.distinctId |
property | String? |
Current known/anonymous ID, or nil before configuration. |
Anectico.sessionId |
property | String? |
Current durable session ID without extending its idle window. |
Errors, messages, users, and breadcrumbs
| Method | Parameters | Returns | Behavior |
|---|---|---|---|
Anectico.captureError(error, options:) |
Swift Error; optional CaptureOptions |
String |
Captures a caught error and returns its ID, or "" before configuration. |
Anectico.captureError(exception, options:) |
NSException; optional options |
String |
Captures an Objective-C exception without changing app behavior. |
Anectico.captureMessage(message, level:options:) |
message; level default info; options |
String |
Captures a diagnostic message and returns its ID. |
Anectico.addBreadcrumb(category:message:level:data:) |
strings; level default info; data |
Void |
Adds trail context attached to a later error. |
Anectico.setUser(user) |
AnecticoUser |
Void |
Sets global error user context. Cross-signal identity still comes from identify. |
Anectico.clearUser() |
— | Void |
Clears global error user context. |
Anectico.captureRawError(...) |
type, message, frame JSON, fatal, mechanism, tags | String |
Bridge API for React Native/Flutter pre-parsed stacks. Native Swift apps should use captureError. |
CaptureOptions fields are tags: [String:String], extra: [String:Any], optional user, optional
level, and optional fingerprint: [String]. Fingerprint components are comma-joined; do not put
commas inside components. AnecticoUser supports id, email, username, ipAddress, and segment.
Fatal native crashes are persisted and delivered on the next application launch. Keep the exact
archive dSYM and upload the bundle or its DWARF binary with
anectico symbols upload-dsym MyApp.dSYM. Anectico matches organization-scoped dSYM slices by exact Mach-O
image UUID; release and distribution are not dSYM lookup keys.
For native symbolication, each frame carries its image UUID and load address. The complete loaded image set stays in the private crash sidecar; only a bounded table of frame-referenced images rides the recovered occurrence, so large simulator processes cannot exceed the ingest attribute cap.
Every iOS error occurrence automatically carries severity, handled state, an honest capture mechanism, release/distribution, SDK/platform, hardware model code/family, OS version, and app version/build. Caught Swift and explicitly captured Objective-C errors are handled and nonfatal; uncaught Objective-C exceptions and signals are unhandled and fatal. Signal crashes use the crash-time snapshot after relaunch.
These SDK-owned fields take precedence over colliding CaptureOptions.tags. The SDK records a model
code such as iPhone15,4, not a unique phone: it never collects IDFV, the user-assigned device name,
a serial number, or an installation ID.
The SDK-owned $app_opened lifecycle event carries the same privacy-safe release, app/build,
platform, OS, and device-family context. It is emitted once per real foreground transition, while
duplicate notifications in one active period are ignored. Backgrounding emits one
$app_backgrounded, pauses recurring flushes, and performs one explicit flush; foregrounding
recreates exactly one timer without rotating the session by itself. Anectico uses its versioned
lifecycle marker to count canonical-person release adoption and the adopted-person error-free rate;
host properties cannot override the marker context.
The reserved $release/$app_version string properties are stamped on every captured event
(not only $app_opened), sourced from the same release/serviceVersion configure() resolved.
Neither is invented: an app that never sets release and has no bundle version to fall back to
sends events with neither property. See
Reserved event properties.
Agent runs
Anectico.startAgentRun(_ agent: String, options: AgentRunOptions = AgentRunOptions()) -> AgentRun
starts a local run handle. It snapshots the start time, identity, and session.
let run = Anectico.startAgentRun(
"checkout-helper",
options: AgentRunOptions(agentId: "checkout", agentVersion: "1.4.0", conversationId: "chat-42")
)
// Perform the agent's work, then declare its actual outcome.
let accepted = run.end(.completed)
// On failure instead: run.end(.failed, terminalReason: "tool_failed")
agentId, agentVersion, and conversationId are optional strings mapping to
gen_ai.agent.id, gen_ai.agent.version, and gen_ai.conversation.id. The agent name maps to
gen_ai.agent.name. Configure and identify the customer before starting a run. A terminal record
is an invoke_agent span sent with ingest:write; it does not require an agent-read or agent-write
management scope. It is not automatic instrumentation of nested model/tool calls.
end(_ status: AgentRunTerminalStatus = .completed, terminalReason: String? = nil) -> Bool
accepts .completed, .failed, .timedOut, .cancelled, or .maxSteps. The multiword
wire values are timed_out and max_steps.
Use a stable, non-sensitive reason code, not an exception message, prompt, or customer value.
Reasons are trimmed, lowercased, and must match ^[a-z][a-z0-9_]{0,63}$. Omitted reasons default to
timeout for a timeout, user_cancelled for cancellation, and the wire status for other outcomes.
These are source-declared outcomes; Anectico does not infer success from the absence of an error.
An invalid reason returns false and leaves the handle open. The first accepted outcome wins;
later valid calls return true without emitting another span. Acceptance is a local handoff,
not confirmation of network delivery. The event-queue flush result does not certify this
separate span transport.
recordAgentRun(agent:options:status:terminalReason:startTimeUnixNano:) is the native bridge
entry point used by React Native and Flutter. Swift application code should use the typed
startAgentRun handle.
Backend propagation
| API | Parameters | Returns | Behavior |
|---|---|---|---|
Anectico.propagationHeaders() |
— | [String:String] |
Creates a fresh traceparent and identity baggage when configured. |
AnecticoPropagation.apply(to:&request) |
inout URLRequest |
Void |
Applies propagation while preserving unrelated baggage. |
AnecticoPropagation.newTraceparent() |
— | String |
Creates a sampled W3C traceparent. |
AnecticoPropagation.baggageWithDistinctId(id, existing:) |
ID; existing baggage | String |
Replaces the Anectico member and preserves unrelated baggage. |
AnecticoPropagation.percentEncode(value) |
string | String |
Encodes a W3C baggage value. |
Apply identity baggage only to application backends you trust. A backend must authenticate the mobile request rather than treating the baggage value itself as proof of identity.