Amba

Quickstart

Get Amba running in your Expo app in 5 minutes.

1. Install the SDK

There are two paths. Path A is the reality right now; Path B lights up once the packages ship on npm.

@amba/cli, @amba/client, and @amba/expo are not yet published to npm. For now, clone the monorepo and consume the SDKs via the workspace:* protocol — pnpm symlinks live source, so any SDK edit reflects instantly.

git clone https://github.com/AppMachina/amba.git
cd amba
pnpm install
pnpm -r run build
 
# The kitchen-sink example is already wired up with workspace deps:
cd examples/expo-todo-kitchen-sink
pnpm install
npx expo start

Want a fresh Expo app? Create it inside examples/ so pnpm picks it up as a workspace member automatically:

cd examples
npx create-expo-app@latest my-app --template default
cd my-app
pnpm add @amba/expo@workspace:* @amba/client@workspace:* @amba/shared@workspace:*
pnpm add expo-notifications expo-device \
  expo-apple-authentication expo-auth-session \
  @react-native-async-storage/async-storage

examples/* is already listed in pnpm-workspace.yaml.

Path B — npm (coming soon)

Once the packages ship to npm, the standard flow will be:

# Not yet working — CLI + SDK aren't on npm.
npx create-expo-app@latest my-app --template default
cd my-app
npx amba init
npx expo install @amba/expo \
  expo-notifications expo-device \
  expo-apple-authentication expo-auth-session \
  @react-native-async-storage/async-storage

2. Create a project + API key

From the monorepo root, use the workspace CLI script:

pnpm amba init

This walks you through:

  • Creating an Amba account (or logging in).
  • Creating a project.
  • Generating API keys.
  • Writing .env.local, AMBA.md, and .cursor/rules/amba.mdc to your project.

Log in separately if you already have an account:

pnpm amba login

(Once published to npm: npx amba init / npx amba login.)

Rename env vars for Expo

Expo only exposes env vars prefixed with EXPO_PUBLIC_ to client code. Copy the CLI output into your app's .env.local with the prefix:

EXPO_PUBLIC_AMBA_PROJECT_ID=proj_xxx
EXPO_PUBLIC_AMBA_API_KEY=amb_dev_ck_xxx
EXPO_PUBLIC_AMBA_API_URL=https://api.amba.dev

3. Initialise the client

@amba/expo ships an Amba singleton that wires up AsyncStorage, push tokens, and social sign-in for you. Call init() once in your root layout:

// app/_layout.tsx
import { useEffect } from 'react';
import { Slot } from 'expo-router';
import { Amba } from '@amba/expo';
 
export default function RootLayout() {
  useEffect(() => {
    Amba.init({
      projectId: process.env.EXPO_PUBLIC_AMBA_PROJECT_ID!,
      apiKey: process.env.EXPO_PUBLIC_AMBA_API_KEY!,
    }).catch((err) => console.warn('Amba.init failed', err));
  }, []);
 
  return <Slot />;
}

init() restores the session from AsyncStorage, creates an anonymous id, fetches remote config, and (by default) registers the device push token.

4. Register the Expo config plugin

In app.json, add @amba/expo to the plugins array. The plugin wires up iOS aps-environment, Apple Sign In capability, URL schemes, and Android intent filters — no hand-editing Info.plist / AndroidManifest.xml.

{
  "expo": {
    "plugins": ["expo-router", ["@amba/expo", { "ios": { "pushNotifications": true } }]]
  }
}

Push on iOS requires a development build (not Expo Go) because custom entitlements aren't supported in Expo Go.

5. Track your first event

import { Amba } from '@amba/expo';
 
function HomeScreen() {
  return (
    <Button
      title="Complete Workout"
      onPress={() =>
        Amba.track('workout_completed', {
          duration_minutes: 30,
          type: 'strength',
        })
      }
    />
  );
}

Events are sent to POST /client/events and automatically:

  • Update the user's last_seen_at.
  • Qualify any matching streaks.
  • Trigger XP rules.
  • Generate activity feed items (if configured).

6. Create a push campaign via MCP

If you're using an AI agent (Cursor, Claude Code), add the Amba MCP server:

{
  "mcpServers": {
    "amba": {
      "command": "npx",
      "args": ["@amba/mcp"],
      "env": {
        "AMBA_API_KEY": "YOUR_ADMIN_API_KEY"
      }
    }
  }
}

Then ask your AI agent:

"Create a push notification campaign called 'Welcome Back' that targets users who haven't opened the app in 7 days"

The agent will use amba_create_segment and amba_create_push_campaign to set it up.

7. Check project status

pnpm amba status

This shows your project health: active users, push token count, segment count, and integration status.

Alternative: manual signup via the API

If you'd rather script signup (CI tasks, internal dashboards), the API exposes the same flow:

Sign up

POST /auth/developer/signup
Content-Type: application/json
 
{
  "email": "[email protected]",
  "password": "at-least-8-chars",
  "name": "Jane Dev"
}

Returns 201 with data.access_token, data.refresh_token, and data.developer. Passwords below 8 characters return WEAK_PASSWORD; duplicate emails return 409 EMAIL_EXISTS.

Log in

POST /auth/developer/login
 
{ "email": "[email protected]", "password": "..." }

Same response shape. Invalid creds return 401 INVALID_CREDENTIALS.

Rotate tokens

Refresh tokens live 30 days. Every refresh rotates both the access token and the refresh token — the old session is revoked atomically, so a replayed refresh is detected.

POST /auth/developer/refresh
 
{ "refresh_token": "<jwt>" }

Fetch the current developer

GET /auth/developer/me
Authorization: Bearer <access_token>

Log out

POST /auth/developer/logout
 
{ "refresh_token": "<jwt>" }

Logout is idempotent — an invalid token still returns { data: { success: true } }.

Create a project

POST /admin/projects
Authorization: Bearer <access_token>
 
{ "name": "My App", "environment": "development" }

Provisioning runs in the background — Amba spins up a dedicated database for your project, configures it, and seeds defaults. Poll the response until project status flips to active.

Mint an API key

Client SDKs authenticate with X-Api-Key. Keys are per-project and scoped to either development or production.

POST /admin/projects/:projectId/api-keys
Authorization: Bearer <access_token>
 
{ "name": "Expo dev key", "environment": "development" }

The response includes the plaintext key once — store it immediately. Rotating a key creates a new row and leaves the old key valid until you explicitly revoke it.

Rate limits

Developer auth is rate-limited per IP to catch credential stuffing:

EndpointPer minutePer day
signup550
login10100
refresh30

Exceeding any window returns 429.

What's next?