Skip to main content

Request methods

The HelpGenie API supports two ways to make requests: the ApiService.invoke() pattern (recommended for TypeScript projects) and direct HTTP requests. The ApiService class handles authentication, request formatting, and response unwrapping automatically:
import { ApiService } from "@/services/api/ApiService";

const genies = await ApiService.invoke({
  resource: "genies",
  action: "all",
});
The invoke method accepts an options object with these fields:
resource
string
required
The API resource to target. Must be one of the 13 supported resources.
action
string
required
The action to perform. Common actions: all, list, get, create, update, delete.
id
string | number
The record identifier. Required for get, update, and delete actions.
data
object
The request payload. Used with create and update actions. Structure varies by resource.

Direct HTTP requests

You can also call the Edge Function directly. The API accepts both a body-based resource/action pattern and standard REST-style HTTP methods.
Send the resource, action, and data in the request body:
curl -X POST https://<project-ref>.supabase.co/functions/v1/api \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "genies",
    "action": "get",
    "id": "abc-123"
  }'

Common actions

Most resources support a standard set of actions. Some resources add custom actions specific to their domain.
ActionDescriptionRequires idRequires data
allFetch all records with full details and relationsNoNo
listFetch a compact list of records (for dropdowns and selectors)NoNo
getFetch a single record by IDYesNo
createCreate a new recordNoYes
updateUpdate an existing recordYesYes
deleteDelete a recordYesNo

list vs all

The API distinguishes between two fetching actions:
  • all returns full records with related data (joins, counts, nested objects). Use this when you need complete information.
  • list returns minimal records with only key fields (typically id and name). Use this for populating dropdowns, selectors, or anywhere you need a lightweight list.
// Full records with all relations — use for detail views
const allGenies = await ApiService.invoke({
  resource: "genies",
  action: "all",
});

// Compact records — use for dropdowns and selectors
const genieList = await ApiService.invoke({
  resource: "genies",
  action: "list",
});
Pagination differs between all and list.
  • The all action on genies uses cursor-based pagination. The response includes nextCursor and hasMore fields. Pass cursor in the request data to fetch the next page.
  • Most other resources use offset-based pagination. The response includes count, and you control paging with limit and offset in the request data.

Request examples

Create a resource

const newGenie = await ApiService.invoke({
  resource: "genies",
  action: "create",
  data: {
    genieName: "Support Agent",
    voiceId: "voice-abc-123",
    firstMessage: "Hi, how can I help you today?",
  },
});

Get a single resource

const genie = await ApiService.invoke({
  resource: "genies",
  action: "get",
  id: "abc-123",
});

Update a resource

const updated = await ApiService.invoke({
  resource: "genies",
  action: "update",
  id: "abc-123",
  data: {
    genieName: "Updated Agent Name",
  },
});

Delete a resource

await ApiService.invoke({
  resource: "genies",
  action: "delete",
  id: "abc-123",
});

Response structure

All responses use a consistent envelope:

Success response

{
  "success": true,
  "data": {
    "id": "abc-123",
    "genieName": "Support Agent",
    "voiceId": "voice-abc-123",
    "created_at": "2025-01-15T10:30:00Z"
  }
}
For list and all actions, data is an array:
{
  "success": true,
  "data": [
    { "id": "abc-123", "genieName": "Support Agent" },
    { "id": "def-456", "genieName": "Sales Agent" }
  ]
}
When using ApiService.invoke(), the response is automatically unwrapped. You receive the data value directly, not the full envelope.

Error response

{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Resource not found",
    "status": 404
  }
}
See Error handling for all error codes.

Admin mode and impersonation

Users with the internal_admin role can operate on behalf of other users by including an impersonatedUserId in the request data. This is used for provisioning trial agents, bulk operations, and testing.
const trialGenie = await ApiService.invoke({
  resource: "genies",
  action: "create",
  data: {
    genieName: "Trial Genie",
    voiceId: "voice-123",
    impersonatedUserId: "user-456",
  },
});
Impersonation is only available to internal_admin users. Non-admin requests that include impersonatedUserId will be ignored or rejected.

Query parameters

When using REST-style HTTP requests, query parameters are automatically extracted and passed to handlers:
GET /functions/v1/api/genies?limit=30&cursor=abc123
When using the body-based approach, include pagination and filter parameters in the data object:
const genies = await ApiService.invoke({
  resource: "genies",
  action: "all",
  data: {
    limit: 30,
    cursor: "abc123",
  },
});