---
title: "API Overview and Authentication"
category: "api-and-integration"
canonical: "https://www.ai-go.app/en-US/docs/guide/api-overview"
locale: "en-US"
last_updated: "2026-08-10"
source: "AI GO 開發者文件（https://www.ai-go.app）"
---

# API Overview and Authentication

You do not have to use the Dashboard to operate AI GO. This chapter covers using the platform purely through its API — creating integrations, authorizing data, reading and writing ERP and custom tables, and driving approvals.

Good fits: connecting AI GO to an existing system, writing automation, running data synchronization, or having an external team build a front end with AI GO as the backend.

---

## Authentication methods

There are four identities, with non-overlapping purposes:

| Identity | How it's sent | Used by | Reach |
|---|---|---|---|
| **API key** | `X-API-Key: sk_live_...` | Third-party systems (Self-Built) | The integration's published reference scope |
| Platform JWT | `Authorization: Bearer ...` | Administrative operations | Per the user's roles |
| App token | Injected by the platform | Custom App runtime | The app's references + scopes |
| Anonymous | None | Public read-only endpoints | Public data |

This chapter focuses on the **API key** path, because that is the one requiring no human login.

---

## Zero to reading data: five steps

### Step 1: create an integration

```
POST /api/v1/integrations
```

| Field | Required | Notes |
|---|---|---|
| `name` | Required | 1–100 characters |
| `subdomain` | Optional | Custom subdomain, same rules as application naming |

Requires a platform JWT with `builder.access`. The response contains `id` and `slug`.

### Step 2: generate an API key

```
POST /api/v1/integrations/{app_id}/api-keys
```

The `api_key` field in the response (`sk_live_` + 64 characters) **appears exactly once**. Store it immediately.

One integration can hold several keys (production and staging), each independently revocable:

```
GET    /api/v1/integrations/{app_id}/api-keys      # list (prefixes only)
DELETE /api/v1/integrations/{app_id}/api-keys/{id} # revoke
```

### Step 3: discover referenceable tables and columns

```
GET /api/v1/refs/available-tables
GET /api/v1/refs/tables/{table_name}/columns
```

Column responses report type, nullability, and foreign key targets:

```json
[
  { "name": "name", "type": "VARCHAR", "nullable": false, "is_system": false },
  { "name": "customer_id", "type": "UUID", "nullable": true,
    "is_fk": true, "fk_target": "customers.id" }
]
```

**This is the authoritative source when planning data flows** — more reliable than any static documentation list.

### Step 4: create references

```
POST /api/v1/refs/apps/{app_id}
```

```json
{
  "table_name": "customers",
  "columns": ["id", "name", "email", "phone", "custom_data"],
  "permissions": ["read", "create", "update"]
}
```

Adjust with `PATCH /api/v1/refs/{ref_id}` or remove with `DELETE`.

### Step 5: publish

```
POST /api/v1/integrations/{app_id}/publish
```

**A Self-Built integration's references only take effect in the Open Proxy after publishing.** This is the key difference from internal and external apps, whose references apply immediately.

With `builder.publish` this publishes directly; otherwise it creates a pending request.

After publishing, the API key can read data.

---

## Reading and writing ERP tables: the Open Proxy

> Prefix `/api/v1/open/proxy`, authenticated with `X-API-Key`, automatically row-filtered to the key's organization

### Simple query

```bash
curl -H "X-API-Key: sk_live_xxx" \
  "https://api.ai-go.app/api/v1/open/proxy/customers?limit=100&offset=0"
```

### Advanced query

```
POST /api/v1/open/proxy/{table_name}/query
```

```json
{
  "filters": [
    { "column": "state", "op": "eq", "value": "sale" },
    { "column": "amount_total", "op": "gte", "value": 1000 }
  ],
  "order_by": [{ "column": "created_at", "direction": "desc" }],
  "search": "keyword",
  "search_columns": ["name", "email"],
  "select_columns": ["id", "name", "amount_total"],
  "limit": 50,
  "offset": 0,
  "count_only": false
}
```

**Filter operators**:

| Operator | Meaning | value |
|---|---|---|
| `eq` / `ne` | Equal / not equal | any |
| `gt` / `gte` / `lt` / `lte` | Comparison | number or string |
| `like` / `ilike` | Pattern match (the latter case-insensitive) | string |
| `is_null` / `is_not_null` | Null checks | not required |
| `in` | Member of a list | array |

**Combination limits** (important):

- Filters are combined with **AND** only
- **OR is not supported** (exception: `search` ORs across search columns)
- **Nested grouping is not supported** (`(A AND B) OR (C AND D)`)
- For BETWEEN, combine `gte` and `lte`

**`count_only`**: set to `true` to return just the matching total, `{"total": 42}`, with filters and search applied. Useful for pagination and statistics.

### Writes

```
POST   /api/v1/open/proxy/{table_name}            # insert
PATCH  /api/v1/open/proxy/{table_name}/{row_id}   # update
DELETE /api/v1/open/proxy/{table_name}/{row_id}   # delete
```

`tenant_id`, `id`, `created_at`, and `updated_at` are handled automatically.

### Automatic type coercion

| Input | Becomes |
|---|---|
| `YYYY-MM-DD` (exactly 10 characters) | date |
| ISO string containing `T` | timestamp |
| JSON object or array | JSONB |

---

## The three proxies compared

One query engine, three authentication modes:

| | Internal Proxy | External Proxy | Open Proxy |
|---|---|---|---|
| Prefix | `/api/v1/proxy/{app_id}/` | `/api/v1/ext/proxy/` | `/api/v1/open/proxy/` |
| Authentication | Member JWT | App token | **API key** |
| `app_id` in path | Yes | (token carries it) | (key carries it) |
| Reference version | Live | Live | **Published snapshot** |
| `limit` ceiling | 500 | 1000 | **1000** |
| Advanced query | Yes | Yes | Yes |

The Open Proxy has **full** advanced query support — not just `limit` and `offset`.

---

## Approval API

```
GET  /api/v1/approvals/record/{res_model}/{res_id}    # status
POST /api/v1/approvals/{request_line_id}/approve      # approve
POST /api/v1/approvals/{request_line_id}/reject       # reject
POST /api/v1/approvals/{request_id}/retry             # retry callback
```

The status query returns each stage's state, approver, comment, and timestamp. Approve and reject verify that the caller is a qualified approver; approving the final stage automatically executes the intercepted operation.

See Chapter 13.

---

## Public read-only endpoint

```
GET /api/v1/pub/templates
```

Anonymous, returning the platform's published application template catalog. Useful for surfacing available templates on your own site or tooling.

---

## Error handling

| Status | Common cause |
|---|---|
| `401` | Invalid or revoked API key |
| `403` | The integration isn't authorized for this table, or lacks the operation |
| `404` | Doesn't exist — **or exists but belongs to another organization** (deliberately indistinguishable) |
| `409` | Uniqueness conflict, or unmet publish prerequisites |
| `422` | Malformed parameters |
| `429` | Quota or rate limit exceeded |

The `404` semantics are worth noting: cross-organization access always reports "not found" and never reveals whether the resource exists. That is deliberate, preventing probing via error codes.

---

## Security recommendations

- Keep API keys in environment variables or a secret manager — **never in source code or version control**
- Use separate keys for production and staging
- Rotate regularly (create new → cut over → revoke old)
- Declare only the columns and operations you actually use — **least privilege**
- Don't grant `delete` to ordinary integrations

---

## API or Custom App?

| Situation | Recommendation |
|---|---|
| An existing system needs to read/write AI GO data | **API** (Self-Built integration) |
| Scheduled sync, batch processing | **API** or a Custom App schedule |
| A human-facing interface | **Custom App** |
| Need the platform's ERP business engines | **Custom App** (`ctx.erp` exists only in actions) |
| Need approvals and AI retrieval | **Custom App** (fuller SDK) |

A simple rule of thumb: **for data, use the API; for capabilities, use a Custom App.**