Synchronizing
Architectural Primitives

Integration guide

For copyable examples covering applications, member invitations and status webhooks, start with the integration quickstart.

Keep your backend responsible for credentials, application identity and reconciliation. Your frontend sends applicants into the Aegis portal, where they provide their own forms, documents and answers.

The integration in four steps
Select an intake, create an application, send the applicant into the portal, then use webhooks and application reads to keep your system in sync. API credentials stay on your backend.

Prepare your integration

1

Arrange a tenant and intake

Ask Aurora Edge for a test tenant, a usable intake label and server API credentials. There is no self-serve sandbox. Keep test and production credentials separate.
2

Request the scopes you need

Provisioning uses applications:write. Add applications:read for reconciliation and webhooks:manage for endpoint registration.
3

Store your application identity

Choose a stable externalRef of at most 200 characters, normalized applicant email and explicit labelId. Persist the returned clientId. Keep current ownership in your own record if you will transfer it.
4

Plan asynchronous outcomes

A successful API call creates a case or performs an action; it does not approve onboarding. Store application status separately from the success of your HTTP request.

Choose your provisioning flow

SituationFlow
Applicant is waiting on your websitePOST /v1/login-sessions, save clientId, redirect the intended applicant to loginUrl.
Your system sends an invitation emailPOST /v1/login-sessions, save clientId and send the exact loginUrl privately in your own email.
Compliance staff will invite laterPOST /v1/applications, save clientId; staff issue a link from the dashboard.
Existing applicant needs another linkPOST /v1/applications/{clientId}/login-sessions. Optional email selects an existing member; omission selects the current owner.
A teammate needs accessPOST members with their email, then POST the application login-sessions route naming that email.

Links are single use and live three days from issue. Read expiresAt rather than hardcoding the duration. Aegis does not send an email for tenant API login-session requests. A repeated call mints a new ticket; never construct the portal URL yourself or assume retry returns the same ticket.

Server quickstart

First, call GET /v1/intakes and select the label for your onboarding flow. Use its labelId in the create request. An empty intake list requires configuration by your Aurora Edge representative; do not guess a label.

Discover intake labels
curl --silent --show-error \
  'https://aegis-api.theauroraedge.com/v1/intakes' \
  --header 'Authorization: Bearer aegis_<key-id>_<secret>'

This cURL example creates an application and returns a sign-in link. Replace placeholders with values from onboarding. Keep the response out of routine logs because it contains loginUrl.

cURL
curl --silent --show-error --request POST \
  'https://aegis-api.theauroraedge.com/v1/login-sessions' \
  --header 'Authorization: Bearer aegis_<key-id>_<secret>' \
  --header 'Content-Type: application/json' \
  --data '{
    "email": "cfo@acme.example",
    "companyName": "Acme Partner FZ-LLC",
    "externalRef": "ORDER-88213",
    "labelId": "corporate",
    "redirectPath": "/dashboard"
  }'
Response 200
{
  "loginUrl": "https://aegis-gateway.theauroraedge.com/sso?ticket=<single-use-ticket>",
  "clientId": "a1b2c3d4-1111-4222-8333-123456789abc",
  "expiresAt": "2026-09-13T09:00:00.000Z"
}

After saving clientId, send an HTTP redirect or place the returned URL in a private invitation. Avoid link-preview and automated link-checking systems that could consume a single-use ticket. Redact URLs containing tickets from analytics and access logs.

Handle HTTP responses consistently

This server-side JavaScript helper preserves status and diagnostic headers, handles 204 without parsing JSON and tolerates an empty or non-JSON failure from an upstream proxy. It leaves retries to the caller so a side-effecting request is not repeated blindly.

JavaScript HTTP helper
export async function aegisRequest(path, { method = 'GET', body } = {}) {
  if (!path.startsWith('/v1/')) throw new Error('Use an Aegis /v1 path');
  const key = process.env.AEGIS_API_KEY;
  if (!key) throw new Error('AEGIS_API_KEY is not configured');
  const response = await fetch('https://aegis-api.theauroraedge.com' + path, {
    method,
    headers: {
      Authorization: 'Bearer ' + key,
      ...(body === undefined ? {} : { 'Content-Type': 'application/json' })
    },
    body: body === undefined ? undefined : JSON.stringify(body),
    signal: AbortSignal.timeout(30000)
  });
  const text = response.status === 204 ? '' : await response.text();
  let result = null;
  try { result = text ? JSON.parse(text) : null; } catch { /* proxy response */ }
  if (!response.ok) {
    const error = new Error('Aegis request failed');
    error.status = response.status;
    error.code = result?.error?.code;
    error.details = result?.error?.details;
    error.requestId = response.headers.get('Aegis-Request-Id') ?? result?.error?.requestId;
    error.retryAfter = response.headers.get('Retry-After');
    throw error;
  }
  if (response.status !== 204 && result === null) throw new Error('Invalid Aegis response');
  return result;
}

Retry 429 and transient 5xx with bounded exponential backoff and jitter, honoring Retry-After when present. Network errors and timeouts also need reconciliation. Preserve the same provisioning identity. A 409 requires fixing the reference/email conflict, and a 401 requires a valid key. A 403 may require the correct scope, unlocking the application or restoring tenant access. The error reference explains each case.

Use the helper in your backend

Set AEGIS_API_KEY in your server environment, then use the helper above. The sample corporate label must be replaced with a label returned for your tenant. Save the returned clientId before handing off the applicant; never log the session object.

Create an application and applicant link
const { data: intakes } = await aegisRequest('/v1/intakes');
const intake = intakes.find(item => item.labelId === 'corporate');
if (!intake) throw new Error('Configure the corporate intake before creating applications');

const externalRef = 'ORDER-88213'; // Your stable database record ID.
const session = await aegisRequest('/v1/login-sessions', {
  method: 'POST',
  body: {
    email: 'cfo@acme.example',
    companyName: 'Acme Partner FZ-LLC',
    externalRef,
    labelId: intake.labelId,
    redirectPath: '/dashboard'
  }
});

// Persist { externalRef, clientId: session.clientId } in your database.
// Redirect the intended applicant to session.loginUrl, or email it privately.
// Use session.expiresAt to tell the applicant when the link expires.

Reconcile outcomes

GET the application by its saved clientId with applications:read. Its status, latest decision and rejectionReason are the outcome contract. active means approved; pending_approval does not. pending can mean submitted and awaiting review, so do not infer submission solely from status.

Read the application
const application = await aegisRequest('/v1/applications/' + clientId);
// Persist application.status and application.decision against your own case.
// Branch on "active", "rejected", "needs_info" and other lifecycle values.
// Treat unfamiliar states as unresolved, never as approved.

Poll at a cadence that fits the shared 60-per-minute key budget, spread requests over time and reduce polling for settled cases. Use the application list with externalRef to recover a missing clientId, or updatedSince to reconcile a window of changes.

Handle information requests

1

Read the request

GET /v1/applications/{clientId}/info-requests for request identifiers, rounds, item counts, prompts and item states.
2

Notify the right person

Mint a new link through the application login-sessions endpoint with their existing member email and redirectPath: /requests. Send it privately.
3

Let the applicant answer

Answers, corrections and uploads happen in the portal. A tenant key cannot submit the applicant's attestation.
4

Wait for review

responded means the applicant finished a round, not that staff accepted it. Reopened items can need another round. Read the case again before treating it as decided.

Membership and access controls

You can add up to 20 members. Save each returned uid for later removal. Repeating an add preserves joinedAt. Removing the owner requires newOwnerUid in the query, naming another member; role labels alone do not identify the owner after a handover. A repeat removal returns 400, so check the roster after an uncertain result.

Lock disables applicant access without changing the decision or deleting the case. Reads, removal and locking remain available during tenant suspension; provisioning, new links, addition and unlocking are refused. The application read does not return ownerUid or accessActive; retain successful handover and lock/unlock responses in your integration record.

Keep outcomes in sync with webhooks

Register your receiver, store its signing secret and send a test event using the webhook reference. Subscribe to application.status.changed for outcomes and application.info_request.raised for applicant follow-up. Use application reads to reconcile every accepted event.

Deduplicate event IDs and process every unseen event. Sequence numbers describe event allocation order, which can differ from the time the underlying change happened. Read the application for current status instead of copying a webhook status into your case. Serialize reconciliation for each clientId so concurrent reads cannot overwrite one another out of order. During recovery, inspect dead letters and sweep the application list with updatedSince.

Integration acceptance checklist

  • Verify the required scopes on your test tenant and use synthetic applicants for acceptance checks.
  • Create, repeat with the same identity, read the current status, and verify a conflicting email returns 409 without adding a member.
  • Open a private test link, verify single use, handle expiry and reissue to the intended current member.
  • Exercise a request/response round through the portal and verify needs_info, responded, reopened and decision handling.
  • Check membership limits, ownership handover, repeated removal and lock/unlock where your integration uses them.
  • Verify 401, 403, 404, 410, 429 and transient error handling without exposing secrets or applicant data in logs.
  • Verify real events, bad signatures, stale timestamps, duplicates, reversed order, receiver failure, secret overlap and dead-letter recovery.
  • Arrange credential rotation, monitoring and an operational contact. Check the changelog before enabling a new capability.