> ## Documentation Index
> Fetch the complete documentation index at: https://docs.equa.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Guide

> Getting started with the Equa API using JavaScript fetch calls

> **Source:** Cross-reference guide — endpoint paths verified against `equa-server/modules/api/src/endpoints/`

# SDK Guide

The Equa API is a standard REST API that can be consumed from any HTTP client. This guide covers common patterns using the browser `fetch` API.

## Setup

Browser clients should use the same-origin API path exposed by the current SPA host:

```javascript theme={null}
const API_BASE = '/api/v1'
```

If you need an absolute URL outside the browser, use `https://app.equa.cc/api/v1` unless a direct API hostname has been freshly re-verified. Every request must include `credentials: 'include'` so the session cookie is sent automatically.

## Helper Function

A reusable API helper simplifies repeated patterns:

```javascript theme={null}
async function equaApi(path, options = {}) {
  const url = `${API_BASE}${path}`
  const response = await fetch(url, {
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      ...options.headers,
    },
    ...options,
  })

  if (!response.ok) {
    const error = await response.json().catch(() => ({ error: response.statusText }))
    throw new Error(error.error || `HTTP ${response.status}`)
  }

  return response.json()
}
```

## Authentication

### Login

```javascript theme={null}
const user = await equaApi('/user/login', {
  method: 'POST',
  body: JSON.stringify({
    email: 'user@example.com',
    password: 'your-password',
  }),
})

console.log('Logged in as:', user.email)
```

### Google OAuth Login

```javascript theme={null}
const user = await equaApi('/user/google-auth', {
  method: 'POST',
  body: JSON.stringify({
    token: googleIdToken,
  }),
})
```

### Magic Link Login

<Warning>
  Magic link endpoints (`/user/magic-link` and `/user/magic-link/verify`) are implemented in the auth module but not yet registered as REST endpoints. This example shows the planned usage.
</Warning>

```javascript theme={null}
// Step 1: Request magic link (planned)
await equaApi('/user/magic-link', {
  method: 'POST',
  body: JSON.stringify({ email: 'user@example.com' }),
})

// Step 2: Verify token from the email link (planned)
const user = await equaApi('/user/magic-link/verify', {
  method: 'POST',
  body: JSON.stringify({ token: tokenFromEmail }),
})
```

### Get Current User

```javascript theme={null}
const currentUser = await equaApi('/user/current')
```

### Logout

```javascript theme={null}
await equaApi('/user/logout', { method: 'POST' })
```

## Organizations

### List Organizations

```javascript theme={null}
const orgs = await equaApi('/organization')
```

### Get Organization Details

```javascript theme={null}
const org = await equaApi(`/organization/${orgId}`)
```

### Create Organization

```javascript theme={null}
const newOrg = await equaApi('/organization', {
  method: 'POST',
  body: JSON.stringify({
    name: 'My Company',
    type: 'corporation',
  }),
})
```

## Cap Table

### List Shareholdings

```javascript theme={null}
const shareholdings = await equaApi(`/organization/${orgId}/shareholding`)
```

### Create a Shareholding

```javascript theme={null}
const shareholding = await equaApi(`/organization/${orgId}/shareholding`, {
  method: 'POST',
  body: JSON.stringify({
    member: memberId,
    security: securityId,
    shares: 10000,
    issueDate: '2025-01-15',
  }),
})
```

### Get Securities

```javascript theme={null}
const securities = await equaApi(`/organization/${orgId}/security`)
```

## Members

### List Organization Members

```javascript theme={null}
const members = await equaApi(`/organization/${orgId}/member`)
```

### Invite Members

```javascript theme={null}
await equaApi(`/organization/${orgId}/member/invite`, {
  method: 'POST',
  body: JSON.stringify({
    emails: ['alice@example.com', 'bob@example.com'],
  }),
})
```

## Documents (Data Room)

### List Documents

```javascript theme={null}
const docs = await equaApi(`/organization/${orgId}/document`)
```

### Upload a Document

```javascript theme={null}
const formData = new FormData()
formData.append('file', fileInput.files[0])

const response = await fetch(`${API_BASE}/organization/${orgId}/document`, {
  method: 'POST',
  credentials: 'include',
  body: formData,
  // Do not set Content-Type header; the browser sets it with the boundary
})
```

### Download a Document

```javascript theme={null}
const response = await fetch(
  `${API_BASE}/organization/${orgId}/document/${docId}/content`,
  { credentials: 'include' }
)
const blob = await response.blob()
```

## Billing

### Get Products

```javascript theme={null}
const products = await equaApi('/billing/product')
```

### Get Organization Subscriptions

```javascript theme={null}
const subs = await equaApi(`/organization/${orgId}/subscription`)
```

## Agent (Equanaut)

### Chat with the Agent

```javascript theme={null}
const response = await equaApi('/agent/chat', {
  method: 'POST',
  body: JSON.stringify({
    organization: orgId,
    message: 'How many shareholders does this company have?',
    conversationId: conversationId,
  }),
})
```

## Error Handling

See [Error Codes](/api/error-codes) for the complete list of status codes. A common pattern:

```javascript theme={null}
try {
  const data = await equaApi('/organization')
  // handle success
} catch (err) {
  if (err.message.includes('401')) {
    // Session expired, redirect to login
  } else {
    // Display error to user
    console.error('API error:', err.message)
  }
}
```
