Reference
API Reference
REST API endpoints for integrating Hikigai agents into your frontend applications.
Base URL: https://backend.hikigaiplatform.io
Authentication
Authenticate using an API key to receive a JWT token for all subsequent requests.
/api/v1/auth/exchangeExchange your API key for a JWT access token.
Request Headers
X-API-Key: hikigai_your_api_key_herecURL Example
curl --location --request POST 'https://backend.hikigaiplatform.io/api/v1/auth/exchange' \
--header 'X-API-Key: your_api_key_here'Response
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 86400,
"scopes": ["deploy", "invoke", "read", "manage"],
"project_id": "project-id-here"
}Agent Deployment
/api/v1/agents/deployDeploy a new agent with optional MCP connector support.
Request Headers
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
X-Project-ID: YOUR_PROJECT_IDRequest Body
{
"name": "{agent-slug}",
"display_name": "Agent Display Name",
"version": "1.0.0",
"description": "Agent description",
"agent_type": "llm",
"model": "gemini-2.5-flash",
"instruction": "System Role: You are a helpful assistant...",
"timeout": 60,
"input_schema": {
"type": "object",
"properties": {
"message": { "type": "string", "description": "User message" }
},
"required": ["message"]
},
"output_schema": {
"type": "object",
"properties": {
"result": { "type": "string" }
}
},
"mcp_connectors": [
{
"slug": "connector-slug",
"tool_filter": ["*"],
"required": true
}
]
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/deploy' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--data '{
"name": "{agent-slug}",
"display_name": "Agent Display Name",
"version": "1.0.0",
"description": "Agent description",
"agent_type": "llm",
"model": "gemini-2.5-flash",
"instruction": "System Role: You are a helpful assistant..."
}'Response
{
"agent_id": "ag_abc123def456",
"name": "cpt2-code-agent-v2",
"slug": "cpt2-code-agent-v2",
"status": "deploying",
"endpoint": null,
"job_id": "job_abc123"
}Deploy is asynchronous. Poll the agent until status becomes active. Use GET /api/v1/agents/{agent_slug} for connector config and the live endpoint URL.
Agent Invocation
Request timeout (optional)
The timeout field is not required. Existing integrations keep working without any changes — if you omit it, the platform uses the agent's deploy-time timeout (console deploys default to 60 seconds; API/SDK deploys default to 30 unless you set one).
Deploying agents is unchanged: you do not need to set timeout at deploy time unless you want a different default for that agent. At invoke time, passtimeoutonly when you need a longer or shorter limit for a specific call (5–300 seconds).
There are two independent timeouts to be aware of:
- Request body (
"timeout": 300) — how long the Hikigai platform waits for the agent to finish processing. - HTTP client (e.g.
requests.post(..., timeout=300)) — how long your application waits for the API response. Set this to match or exceed the body timeout so your app does not give up before the server responds.
This matches SDK behavior: agent.invoke(..., timeout=300) is also optional and uses the same defaults when omitted. Console deploys default the agent timeout to 60 seconds; API/SDK deploy defaults to 30 seconds unless you set timeout at deploy time.
/api/v1/agents/{agent_slug}/invokeInvoke an agent to process a message with optional MCP connector data.
Request Headers
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
X-Project-ID: YOUR_PROJECT_IDRequest Body
{
"input": {
"query": "Show me my blood pressure data for today",
"userId": "android-user-010",
"deviceId": "056ac949aa621795"
},
"timeout": 300,
"connectors": {
"google-health-connect": {}
}
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/{agent-slug}/invoke' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--data '{
"input": {
"message": "Your message here"
},
"timeout": 300
}'Response
{
"output": {
"result": "Based on the health data, the patient shows stable vital signs..."
},
"agent_id": "ag_abc123def456",
"status": "success",
"session_id": "session-123",
"latency_ms": 1250,
"tokens_used": 342,
"request_id": "req_xyz789",
"tools_called": [],
"artifacts": []
}Structured results land in output (parsed against the agent's output schema when possible). status is one of success, partial, failed, or requires_human_review.
Streaming
/api/v1/agents/{agent_slug}/streamStream agent responses via Server-Sent Events (SSE). Useful for real-time UI updates.
Request Headers
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
Accept: text/event-streamAuth can also use X-API-Key. Project scope comes from the key or JWT — X-Project-ID is not required on this endpoint.
Request Body
{
"input": {
"query": "Your query here",
"userId": "user-id",
"deviceId": "device-id"
},
"timeout": 300,
"connectors": {
"connector-slug": {}
},
"session_id": "session-abc123"
}timeout is optional for streaming as well — see the explanation above.
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/{agent-slug}/stream' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Content-Type: application/json' \
--header 'Accept: text/event-stream' \
--data '{
"input": {
"query": "Your query here",
"userId": "user-id",
"deviceId": "device-id"
},
"connectors": {
"connector-slug": {}
}
}' \
--no-bufferResponse Format (SSE)
data: Based
data: on
data: the
data: health
data: data
data: [DONE]data: and followed by double newlines. The stream ends with data: [DONE].Agent Management
/api/v1/agentsList all agents with pagination. Includes mcp_connectors configuration.
Request Headers
Authorization: Bearer YOUR_TOKEN
X-Project-ID: YOUR_PROJECT_IDQuery Parameters
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
per_page | integer | Items per page (default: 20) |
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents?page=1&per_page=20' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'X-Project-ID: YOUR_PROJECT_ID'Response
{
"agents": [
{
"id": "ag_abc123",
"name": "agent-name",
"slug": "agent-slug",
"description": "Agent description",
"status": "active",
"request_count": 1542,
"mcp_connectors": [
{
"slug": "connector-slug",
"tool_filter": ["*"],
"required": true
}
]
}
],
"total": 5,
"page": 1,
"per_page": 20
}/api/v1/agents/{agent_slug}Get details of a specific agent, including mcp_connectors configuration.
Request Headers
Authorization: Bearer YOUR_TOKEN
X-Project-ID: YOUR_PROJECT_IDcURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/{agent-slug}' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'X-Project-ID: YOUR_PROJECT_ID'Response
{
"id": "ag_abc123def456",
"name": "agent-name",
"slug": "agent-slug",
"model": "gemini-2.5-flash",
"instruction": "You are a helpful assistant...",
"description": "Agent description",
"status": "active",
"endpoint": "https://....run.app",
"request_count": 1542,
"mcp_connectors": [
{
"slug": "connector-slug",
"tool_filter": ["*"],
"required": true
}
]
}/api/v1/agents/{agent_slug}/redeployRedeploy an agent with updated configuration and mcp_connectors.
Request Headers
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
X-Project-ID: YOUR_PROJECT_IDRequest Body
{
"instruction": "Updated system prompt",
"model": "gemini-2.5-flash",
"mcp_connectors": [
{
"slug": "connector-slug",
"tool_filter": ["*"],
"required": true
}
]
}cURL Example
curl --location --request POST 'https://backend.hikigaiplatform.io/api/v1/agents/{agent-slug}/redeploy' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Content-Type: application/json' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--data '{
"instruction": "Updated system prompt",
"model": "gemini-2.5-flash",
"mcp_connectors": [
{
"slug": "connector-slug",
"tool_filter": ["*"],
"required": true
}
]
}'Response
{
"agent_id": "ag_abc123def456",
"name": "agent-name",
"slug": "agent-slug",
"status": "deploying",
"endpoint": "https://....run.app",
"job_id": "job_abc123"
}Redeploy is asynchronous. Poll until status is active. Connector configuration is returned on GET /api/v1/agents/{agent_slug}.
End-User Identity
Give your app's end users — clinicians, patients, staff — their own signup, login, multi-factor auth, QR badge login, and single sign-on. Each app gets a dedicated AWS Cognito user pool that the platform provisions and runs for you, so you never touch AWS. Login returns standard OIDC tokens (ID, access, refresh).
managed keeps users in Hikigai's Cognito (zero setup). byo (bring-your-own) keeps them in your own AWS account, which the platform reaches through a cross-account IAM role you create.Base path: /api/v1/identity
Auth (server / SDK): X-API-Key: hikigai_…, X-Project-ID: YOUR_PROJECT_ID, and User-Agent: hikigai-sdk/… (required — the platform only accepts raw API keys from SDK user agents). The AppSDK sends the same values as Authorization: Bearer hikigai_… plus those headers.
Auth (JWT): Authorization: Bearer <jwt> from POST /api/v1/auth/exchange with X-Project-ID.
Scopes
Each endpoint requires one scope on your API key. End users hitting auth endpoints from your app use invoke; one-time setup uses manage / read.
| Scope | Used by | Endpoints |
|---|---|---|
invoke | Your app, per end user | signup, confirm, login, refresh, logout, forgot-password, reset-password, change-password, MFA, SSO sign-in, QR login |
manage | Setup & admin | enable, configure SSO, issue QR badge, BYO test, update end-user profile (role, etc.), disable MFA |
read | Setup & admin | get config, BYO setup |
Typical integration flow
Every call below uses the same three headers (see each endpoint for full cURL). Replace YOUR_PROJECT_ID, YOUR_APP_ID, and hikigai_your_api_key.
# 0. Check pool is active
GET /api/v1/identity/apps/YOUR_APP_ID
# 1. Sign up an end user
POST /api/v1/identity/signup
{ "app_id": "YOUR_APP_ID", "email": "clinician@hospital.com", "password": "Temp#Pass2026", "first_name": "Asha", "last_name": "Mehta", "role": "clinician", "attributes": { "phone_number": "+14155552671" }, "metadata": { "doctorID": "6278383837" } }
# 1b. Confirm (if the pool requires email verification)
POST /api/v1/identity/confirm
{ "app_id": "YOUR_APP_ID", "email": "clinician@hospital.com", "code": "123456" }
# 2. Log in → OIDC tokens (or MFA challenge)
POST /api/v1/identity/login
{ "app_id": "YOUR_APP_ID", "email": "clinician@hospital.com", "password": "Temp#Pass2026" }
# 2b. If login returns "status": "challenge", finish with:
POST /api/v1/identity/mfa/respond
{ "app_id": "YOUR_APP_ID", "email": "...", "session": "...", "code": "482913" }
# 3. MFA enrollment (uses access_token from login)
POST /api/v1/identity/mfa/associate → secret_code
POST /api/v1/identity/mfa/verify → { "status": "SUCCESS" }
POST /api/v1/identity/mfa/set-preference → { "enabled": true }
# 4. QR badge (admin issues, kiosk exchanges)
POST /api/v1/identity/apps/YOUR_APP_ID/users/clinician%40hospital.com/qr-login
POST /api/v1/identity/qr-login
{ "app_id": "YOUR_APP_ID", "qr_payload": "HKG2...." }
# Session maintenance
POST /api/v1/identity/refresh → { "refresh_token": "..." }
POST /api/v1/identity/logout → { "email": "..." }
# Forgot password (Cognito emails a verification code)
POST /api/v1/identity/forgot-password
{ "app_id": "YOUR_APP_ID", "email": "clinician@hospital.com" }
POST /api/v1/identity/reset-password
{ "app_id": "YOUR_APP_ID", "email": "clinician@hospital.com", "code": "123456", "new_password": "NewTemp#Pass2026" }
# Change password (user is logged in — uses access_token from login)
POST /api/v1/identity/change-password
{ "app_id": "YOUR_APP_ID", "access_token": "...", "current_password": "...", "new_password": "..." }
# Update profile / role (Cognito — path may be email or Cognito sub; app_id required)
PATCH /api/v1/end-users/clinician%40hospital.com?app_id=YOUR_APP_ID
{ "role": "doctor", "first_name": "Asha", "last_name": "Mehta" }
# Runtime verification (apps — Cognito/GCP source of truth)
POST /api/v1/identity/verify-qr
{ "app_id": "YOUR_APP_ID", "qr_payload": "HKG2...." }
POST /api/v1/identity/verify-pin
{ "app_id": "YOUR_APP_ID", "email": "clinician@hospital.com", "pin": "123456" }
POST /api/v1/identity/verify-sso
{ "app_id": "YOUR_APP_ID", "token": "eyJraWQiOi..." }
# Get one user's detail (console path — profile + Cognito status)
GET /api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/identity/users/clinician%40hospital.com# Shared headers for every curl (SDK / server-side only):
curl ... \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{ ... }'Setup & status
/api/v1/identity/apps/{app_id}/enableProvision the app's Cognito user pool. Run this once per app. Returns immediately with status 'provisioning' or 'active'.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"mode": "managed", // "managed" or "byo"
"enabled_methods": ["password", "mfa", "qr", "sso"],
"byo_role_arn": null, // required when mode = "byo"
"byo_account_id": null
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/apps/YOUR_APP_ID/enable' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{ "mode": "managed", "enabled_methods": ["password", "mfa", "qr"] }'Response
{
"app_id": "app_123",
"project_id": "proj_123",
"mode": "managed",
"status": "active",
"cognito_pool_id": "us-east-2_aBcD1234",
"cognito_client_id": "1h57kf5a2...",
"cognito_region": "us-east-2",
"enabled_methods": ["password", "mfa", "qr"],
"error_message": null
}/api/v1/identity/apps/{app_id}Get the app's identity config and provisioning status.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/apps/YOUR_APP_ID' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response
{
"app_id": "app_123",
"project_id": "proj_123",
"mode": "managed",
"status": "active",
"cognito_pool_id": "us-east-2_aBcD1234",
"cognito_client_id": "1h57kf5a2...",
"cognito_region": "us-east-2",
"enabled_methods": ["password", "mfa", "qr"],
"error_message": null
}End-user accounts
Console management path: /api/v1/projects/{project_id}/apps/{app_id}/identity
Permissions: apps:read to list users; apps:update to create, import, or delete.
Auth: API key (Authorization: Bearer hikigai_…) or session JWT from POST /api/v1/auth/exchange.
/api/v1/projects/{project_id}/apps/{app_id}/identity/usersList end users registered in the app's Cognito pool. Used by the Developer Console User Management tab.
Request Headers
Authorization: Bearer YOUR_TOKENQuery Parameters
| Parameter | Default | Description |
|---|---|---|
limit | 50 | Max 200 per page |
offset | 0 | Pagination offset |
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/identity/users' \
--header 'Authorization: Bearer YOUR_TOKEN'Response
{
"users": [
{
"id": "a1b2c3d4-....",
"project_id": "proj_123",
"first_name": "Asha",
"last_name": "Mehta",
"email": "clinician@hospital.com",
"role": "clinician",
"external_subject": "a1b2c3d4-....",
"is_active": true,
"qr_issued": false,
"metadata": { "doctorID": "6278383837" },
"created_at": "2026-06-11T12:00:00Z",
"last_verified_at": null
}
]
}id and external_subject are the Cognito subject (sub / user_sub) — the same value as the sub claim in the login id_token. Names, role, and metadata come from Cognito attributes (given_name, family_name, custom:role, custom:metadata). Prefer email as the stable handle in SDK/admin paths./api/v1/identity/signupRegister a new end user in the app's pool. If the pool requires confirmation, follow with /identity/confirm; otherwise the user can log in right away.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com",
"password": "Temp#Pass2026",
"first_name": "Asha", // optional
"last_name": "Mehta", // optional
"role": "clinician", // optional — app-domain role (Cognito custom:role)
"attributes": { // optional — Cognito user attributes (string values)
"phone_number": "+14155552671" // E.164 format; other Cognito attrs also allowed
},
"metadata": { "doctorID": "6278383837" } // optional — opaque app JSON → custom:metadata
}attributes— Cognito profile fields. Values must be strings. Keys must be Cognito attributes (or custom attributes defined on the pool), e.g.phone_number,given_name,custom:…. Unknown keys can cause Cognito to reject signup.metadata— opaque app-specific JSON object (any shape). Stored on Cognito ascustom:metadata(JSON string, max 2048 chars; GCP BYO uses custom claims). Use for things likedoctorID, clinic id, flags — not for Cognito identity fields like phone.
attributes, not metadata:{ "attributes": { "phone_number": "+14155552671" } }+ and country code). It is stored in Cognito and returned under cognito.phone_number on GET …/identity/users/{email}.role is stored on Cognito as custom:role (e.g. clinician, nurse, doctor). Pass it as a top-level field or inside attributes as role / custom:role (those keys are mapped to custom:role). To change role later, use PATCH /api/v1/end-users/{email}?app_id=… or the console PATCH …/identity/users/{email} path.metadata is an optional JSON object — pass any keys/values your app needs (e.g. doctorID, clinic id, flags). It is not for Cognito attributes like phone. Stored as Cognito custom:metadata (JSON string, max 2048 chars). Returned by the users list and GET .../identity/users/{email}. Update later via PATCH /api/v1/end-users/{email}?app_id=….cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/signup' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com",
"password": "Temp#Pass2026",
"first_name": "Asha",
"last_name": "Mehta",
"role": "clinician",
"attributes": { "phone_number": "+14155552671" },
"metadata": { "doctorID": "6278383837" }
}'Response (201)
{
"user_sub": "a1b2c3d4-....", // Cognito subject (sub); may be null until confirmed
"user_id": "a1b2c3d4-....", // same as user_sub (Cognito sub)
"email": "clinician@hospital.com",
"confirmed": false
}user_id and user_sub are both the Cognito subject. Prefer email as the handle for management APIs. user_sub may be null until the account is confirmed (auto-confirm pools return it right away). The same ids are returned by /identity/login and the users list./api/v1/identity/confirmConfirm a signup with the code emailed to the user.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com",
"code": "123456"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/confirm' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com",
"code": "123456"
}'Response (200)
{
"success": true,
"message": "Account confirmed"
}/api/v1/identity/loginAuthenticate an end user. Returns OIDC tokens, or an MFA challenge if multi-factor is required.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com",
"password": "Temp#Pass2026"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/login' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com",
"password": "Temp#Pass2026"
}'Response — success
{
"status": "authenticated",
"id_token": "eyJraWQiOi...",
"access_token": "eyJraWQiOi...",
"refresh_token": "eyJjdHkiOi...",
"expires_in": 3600,
"token_type": "Bearer",
"user_sub": "a1b2c3d4-....", // Cognito subject (same as the id_token 'sub' claim)
"user_id": "a1b2c3d4-...." // same as user_sub
}user_sub and user_id are the Cognito subject (equal to the sub claim inside the id_token). Prefer email for management APIs. They are only present when status is authenticated.Response — MFA required
{
"status": "challenge",
"challenge_name": "SOFTWARE_TOKEN_MFA",
"session": "AYABeF..."
}status is challenge or challenge_name is present, collect the user's TOTP code and call POST /api/v1/identity/mfa/respond with the returned session to finish the login and receive tokens./api/v1/identity/refreshExchange a refresh token for fresh access and ID tokens.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"refresh_token": "eyJjdHkiOi..."
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/refresh' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"refresh_token": "eyJjdHkiOi..."
}'Response
{
"status": "authenticated",
"id_token": "eyJraWQiOi...",
"access_token": "eyJraWQiOi...",
"refresh_token": "eyJjdHkiOi...",
"expires_in": 3600,
"token_type": "Bearer"
}/api/v1/identity/logoutGlobally sign the user out, revoking their refresh tokens.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/logout' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com"
}'Response
{
"success": true,
"message": "Logged out"
}Password management
Reset a forgotten password via email verification code (sent by Cognito), or change the password when the user is already logged in. All three endpoints require the invoke scope.
/api/v1/identity/forgot-passwordRequest a password-reset verification code. Cognito emails the code to the user if the account exists. Does not change the password yet.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/forgot-password' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com"
}'Response (200)
{
"success": true,
"message": "If an account exists for this email, a password reset code has been sent."
}POST /api/v1/identity/reset-password once the user enters the code./api/v1/identity/reset-passwordSet a new password using the verification code from the forgot-password email.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com",
"code": "123456",
"new_password": "NewTemp#Pass2026"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/reset-password' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com",
"code": "123456",
"new_password": "NewTemp#Pass2026"
}'Response (200)
{
"success": true,
"message": "Password reset successfully"
}/api/v1/identity/change-passwordChange password for a logged-in user who knows their current password. Requires the access_token from login.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"access_token": "eyJraWQiOi...",
"current_password": "Temp#Pass2026",
"new_password": "NewTemp#Pass2026"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/change-password' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"access_token": "eyJraWQiOi...",
"current_password": "Temp#Pass2026",
"new_password": "NewTemp#Pass2026"
}'Response (200)
{
"success": true,
"message": "Password changed successfully"
}Multi-factor auth (TOTP)
Enroll a user's authenticator app, then require it at login. The associate step returns a secret you render as an otpauth:// QR code for Google Authenticator, Authy, etc.
Typical enroll flow: POST /identity/login (user password) → POST /identity/mfa/associate → render QR → POST /identity/mfa/verify → POST /identity/mfa/set-preference with enabled: true.
Admin disable: POST /api/v1/end-users/{email}/mfa/disable?app_id=… (manage scope) when the user cannot sign in to turn MFA off themselves.
/api/v1/identity/mfa/associateBegin TOTP enrollment for a signed-in user. Returns the shared secret to display as a QR code.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"access_token": "eyJraWQiOi..." // from login
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/mfa/associate' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"access_token": "eyJraWQiOi..."
}'Response
{
"secret_code": "JBSWY3DPEHPK3PXP",
"session": null
}/api/v1/identity/mfa/verifyVerify the first TOTP code to finish enrollment.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"access_token": "eyJraWQiOi...",
"code": "482913",
"device_name": "iPhone Authenticator" // optional
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/mfa/verify' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"access_token": "eyJraWQiOi...",
"code": "482913",
"device_name": "iPhone Authenticator"
}'Response
{
"status": "SUCCESS"
}/api/v1/identity/mfa/set-preferenceTurn TOTP MFA on or off for a user.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"access_token": "eyJraWQiOi...",
"enabled": true
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/mfa/set-preference' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"access_token": "eyJraWQiOi...",
"enabled": true
}'Response
{
"success": true,
"message": "MFA preference updated"
}/api/v1/identity/mfa/respondComplete a login that returned an MFA challenge. Returns OIDC tokens.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com",
"session": "AYABeF...", // from the login challenge
"code": "482913"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/mfa/respond' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"email": "clinician@hospital.com",
"session": "AYABeF...",
"code": "482913"
}'Response
{
"status": "authenticated",
"id_token": "eyJraWQiOi...",
"access_token": "eyJraWQiOi...",
"refresh_token": "eyJjdHkiOi...",
"expires_in": 3600,
"token_type": "Bearer"
}QR badge login
Issue a per-user QR credential a clinician can scan to sign in without typing a password — ideal for shared workstations. Issue the badge once (admin), then exchange a scanned payload for tokens at the kiosk.
/api/v1/identity/apps/{app_id}/users/{email}/qr-loginIssue a QR badge credential for a user. No request body — email is in the path (URL-encode @ as %40). The payload is shown once — encode it into the badge.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1cURL Example
curl --location --request POST 'https://backend.hikigaiplatform.io/api/v1/identity/apps/YOUR_APP_ID/users/clinician%40hospital.com/qr-login' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response (201)
Returns qr_payload and qr_code_png_base64. May also return 200 on re-issue.
{
"credential_id": "qr-version-uuid",
"end_user_id": "a1b2c3d4-....",
"email": "clinician@hospital.com",
"qr_payload": "HKG2....",
"qr_code_png_base64": "iVBORw0KGgo..."
}/api/v1/identity/qr-code/renderRender a qr_payload (or any text) as a PNG QR image. Returns image/png.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{ "data": "HKG2...." }cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/qr-code/render' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{ "data": "HKG2...." }' \
-o badge-qr.pngResponse (200)
Binary PNG image (Content-Type: image/png).
/api/v1/identity/qr-loginExchange a scanned QR payload for OIDC tokens.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"qr_payload": "HKG2...."
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/qr-login' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"qr_payload": "HKG2...."
}'Response
{
"status": "authenticated",
"id_token": "eyJraWQiOi...",
"access_token": "eyJraWQiOi...",
"refresh_token": "eyJjdHkiOi...",
"expires_in": 3600,
"token_type": "Bearer"
}End-user profile & role
Cognito (or GCP Identity Platform) is the source of truth for end-user profile data. Fetch or update role, name, metadata, phone, and active status. Email is immutable — it is the Cognito login identity.
Console path (by email): GET /api/v1/projects/{project_id}/apps/{app_id}/identity/users/{email} — full detail including live Cognito status. Auth: Bearer; permission apps:read.
SDK path: GET or PATCH /api/v1/end-users/{email_or_sub}?app_id=… —app_id is required. Path may be the user's email or Cognito sub. Auth: SDK headers; scopes read (GET) or manage (PATCH). Do not use POST /api/v1/end-users to create users — use POST /api/v1/identity/signup.
/api/v1/projects/{project_id}/apps/{app_id}/identity/users/{email}Get full detail for one end user by email from Cognito/GCP (names, role, metadata) plus live pool status (MFA, enabled, email verified).
Request Headers
Authorization: Bearer YOUR_TOKEN
Content-Type: application/jsonPath Parameters
project_id, app_id — your project and app ids.email — the end user's email (URL-encode @, e.g. test1%40gmail.com).
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/identity/users/test1%40gmail.com' \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Content-Type: application/json'Response
{
"id": "a1b2c3d4-....",
"email": "test1@gmail.com",
"first_name": "Asha",
"last_name": "Mehta",
"role": "clinician",
"is_active": true,
"external_subject": "a1b2c3d4-....",
"qr_issued": false,
"created_at": "2026-06-11T12:00:00Z",
"last_login_at": null,
"metadata": { "doctorID": "6278383837" },
"cognito": {
"user_sub": "a1b2c3d4-....",
"status": "CONFIRMED",
"enabled": true,
"email_verified": true,
"mfa_enabled": false,
"mfa_methods": [],
"preferred_mfa": null,
"created_at": "2026-06-11T12:00:00Z",
"last_modified_at": "2026-06-12T08:30:00Z",
"phone_number": "+14155552671",
"metadata": { "doctorID": "6278383837" }
}
}given_name, family_name, custom:role, custom:metadata). The cognito object is live pool status. Phone from signup attributes appears under cognito.phone_number./api/v1/end-users/{email_or_sub}?app_id=Get an end user's Cognito profile by email or Cognito sub (SDK path). Query param app_id is required.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1Path & query
email_or_sub — user email or Cognito sub (URL-encode email).app_id (query, required) — app whose Cognito/GCP pool to use.
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/end-users/clinician%40hospital.com?app_id=YOUR_APP_ID' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response (200)
{
"id": "a1b2c3d4-....",
"project_id": "proj_123",
"first_name": "Asha",
"last_name": "Mehta",
"email": "clinician@hospital.com",
"role": "clinician",
"external_subject": "a1b2c3d4-....",
"is_active": true,
"qr_issued": false,
"metadata": { "doctorID": "6278383837" },
"created_at": "2026-06-11T12:00:00Z",
"last_verified_at": null
}/api/v1/end-users/{email_or_sub}?app_id=Update an end user's Cognito profile. All body fields are optional. Email cannot be updated. Query param app_id is required.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonPath & query
email_or_sub — user email or Cognito sub.app_id (query, required).
Request Body
{
"role": "doctor", // optional — Cognito custom:role
"first_name": "Asha", // optional — given_name
"last_name": "Mehta", // optional — family_name
"phone_number": "+14155552671", // optional — Cognito attribute (E.164); "" clears
"metadata": { "department": "cardiology" }, // optional — replaces custom:metadata
"is_active": true // optional — enable/disable in Cognito
}cURL Example
curl --location --request PATCH 'https://backend.hikigaiplatform.io/api/v1/end-users/clinician%40hospital.com?app_id=YOUR_APP_ID' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"role": "doctor"
}'Response (200)
{
"id": "a1b2c3d4-....",
"project_id": "proj_123",
"first_name": "Asha",
"last_name": "Mehta",
"email": "clinician@hospital.com",
"role": "doctor",
"external_subject": "a1b2c3d4-....",
"is_active": true,
"qr_issued": false,
"metadata": null,
"created_at": "2026-06-11T12:00:00Z",
"last_verified_at": null
}email, external_subject, password, and ids cannot be changed here. Sending them returns 422. To change a login email, create a new account (or delete + recreate). Use the password endpoints to change passwords. phone_number updates the Cognito attribute (E.164, e.g. +14155552671); send an empty string to clear it./api/v1/end-users/{email_or_sub}/mfa/disable?app_id=Admin-disable TOTP MFA for an end user (manage scope). Requires app_id query. Unlike POST /identity/mfa/set-preference, this does not require the user's access token.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonPath & query
email_or_sub — user email or Cognito sub.app_id (query, required).
cURL Example
curl --location --request POST 'https://backend.hikigaiplatform.io/api/v1/end-users/clinician%40hospital.com/mfa/disable?app_id=YOUR_APP_ID' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response (200)
{ "success": true, "message": "MFA disabled" }QR & PIN credentials (Cognito-backed)
QR badges and PINs live on the app's Cognito user (custom attributes / QR v2), not a separate DB table. Base path: /api/v1/end-users with required app_id query (or use /identity/apps/{app_id}/users/{email}/qr-login and …/pin).
Auth: SDK headers (X-API-Key, X-Project-ID, User-Agent: hikigai-sdk/…).
Scopes: read to list; manage to issue, rotate, or revoke.
Verify at runtime: POST /api/v1/identity/verify-qr, verify-pin, verify-sso — each requires app_id in the body.
/api/v1/end-users/{email_or_sub}/credentials?app_id=List synthesized credential metadata from Cognito (QR version id and/or pin). app_id query required.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1Path & query
email_or_sub — user email or Cognito sub.app_id (query, required).
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/end-users/clinician%40hospital.com/credentials?app_id=YOUR_APP_ID' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response
{
"credentials": [
{
"id": "qr-version-uuid",
"end_user_id": "a1b2c3d4-....",
"credential_type": "qr",
"status": "active",
"issued_at": "2026-06-11T12:00:00Z",
"expires_at": null,
"last_used_at": null
},
{
"id": "pin",
"end_user_id": "a1b2c3d4-....",
"credential_type": "pin",
"status": "active",
"issued_at": null,
"expires_at": null,
"last_used_at": null
}
]
}CREDENTIAL_ID: the id field on each object (QR version uuid, or pin). Also returned as credential_id from issue/rotate QR responses./api/v1/end-users/{email_or_sub}/credentials/{credential_id}?app_id=Revoke a Cognito QR badge (rotates version) or clear PIN hash. app_id query required.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1Path & query
email_or_sub — user email or Cognito sub.credential_id — from list credentials (credentials[].id).app_id (query, required).
cURL Example
curl --location --request DELETE 'https://backend.hikigaiplatform.io/api/v1/end-users/clinician%40hospital.com/credentials/CREDENTIAL_ID?app_id=YOUR_APP_ID' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response
{
"success": true,
"message": "Credential revoked"
}Runtime verification (QR / PIN / SSO)
Apps verify clinicians through the platform against the app's Cognito pool. Every verify call requires app_id. Scope: invoke.
/api/v1/identity/verify-qrVerify a scanned HKG2 QR badge against the app's Cognito pool.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"qr_payload": "HKG2...."
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/verify-qr' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{ "app_id": "app_123", "qr_payload": "HKG2...." }'Response (200)
{
"end_user_id": "a1b2c3d4-....",
"project_id": "proj_123",
"first_name": "Asha",
"last_name": "Mehta",
"role": "clinician",
"method": "qr",
"verified_at": "2026-06-12T08:30:00Z",
"metadata": { "doctorID": "6278383837" }
}/api/v1/identity/verify-pinVerify an end user's PIN stored on Cognito (custom:pin_hash).
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"email": "clinician@hospital.com",
"pin": "123456"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/verify-pin' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{ "app_id": "app_123", "email": "clinician@hospital.com", "pin": "123456" }'/api/v1/identity/verify-ssoVerify an SSO id token against the app's Cognito pool.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"token": "eyJraWQiOi..."
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/verify-sso' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{ "app_id": "app_123", "token": "eyJraWQiOi..." }'Single sign-on & social
Let users sign in with Google, Apple, Okta, Azure AD, SAML, or any OIDC provider. Configure the provider once, then run the standard authorize-redirect / code-exchange flow.
/api/v1/identity/apps/{app_id}/ssoAdd or update an SSO / social provider on the app's pool.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"provider_name": "Google",
"provider_type": "Google",
"provider_details": {
"client_id": "...",
"client_secret": "...",
"authorize_scopes": "openid email profile"
},
"callback_urls": ["https://yourapp.com/auth/callback"],
"attribute_mapping": { "email": "email" },
"scopes": ["openid", "email", "profile"]
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/apps/YOUR_APP_ID/sso' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"provider_name": "Google",
"provider_type": "Google",
"provider_details": {
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"authorize_scopes": "openid email profile"
},
"callback_urls": ["https://yourapp.com/auth/callback"],
"attribute_mapping": { "email": "email" },
"scopes": ["openid", "email", "profile"]
}'Response
{
"app_id": "app_123",
"project_id": "proj_123",
"mode": "managed",
"status": "active",
"cognito_pool_id": "us-east-2_aBcD1234",
"cognito_client_id": "1h57kf5a2...",
"cognito_region": "us-east-2",
"enabled_methods": ["password", "mfa", "qr", "sso"],
"error_message": null
}/api/v1/identity/sso/authorize-urlBuild the hosted-UI authorize URL to redirect the user to for sign-in.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"redirect_uri": "https://yourapp.com/auth/callback",
"provider": "Google", // optional
"scopes": ["openid", "email", "profile"] // optional
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/sso/authorize-url' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"redirect_uri": "https://yourapp.com/auth/callback",
"provider": "Google"
}'Response
{
"authorize_url": "https://app-123.auth.us-east-2.amazoncognito.com/oauth2/authorize?..."
}/api/v1/identity/sso/tokenExchange the authorization code from the callback for OIDC tokens.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"app_id": "app_123",
"code": "auth-code-from-callback",
"redirect_uri": "https://yourapp.com/auth/callback"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/sso/token' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"app_id": "app_123",
"code": "auth-code-from-callback",
"redirect_uri": "https://yourapp.com/auth/callback"
}'Response
{
"status": "authenticated",
"id_token": "eyJraWQiOi...",
"access_token": "eyJraWQiOi...",
"refresh_token": "eyJjdHkiOi...",
"expires_in": 3600,
"token_type": "Bearer"
}Bring-your-own Cognito
To keep users in your own AWS account, create a cross-account IAM role from the template below, then enable the app with mode: "byo" and the role ARN.
/api/v1/identity/byo/setupGet the CloudFormation template and the trust values (Hikigai account ID + ExternalId) to create the cross-account role.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/byo/setup' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1'Response
{
"hikigai_account_id": "439563881130",
"external_id": "hikigai-app-123",
"template": "AWSTemplateFormatVersion: '2010-09-09' ..."
}/api/v1/identity/byo/testVerify the platform can assume your cross-account role before enabling BYO.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
User-Agent: hikigai-sdk/0.0.1
Content-Type: application/jsonRequest Body
{
"role_arn": "arn:aws:iam::123456789012:role/HikigaiIdentityProvisioningRole",
"region": "us-east-2" // optional
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/identity/byo/test' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'User-Agent: hikigai-sdk/0.0.1' \
--header 'Content-Type: application/json' \
--data '{
"role_arn": "arn:aws:iam::123456789012:role/HikigaiIdentityProvisioningRole",
"region": "us-east-2"
}'Response
{
"ok": true,
"account_id": "123456789012",
"error": null
}Object Storage
Platform-managed object storage for deployed apps. Upload PDFs, images, audio, and other documents scoped to a project and app. Files are stored in a private AWS S3 bucket — they are never public. Access is via time-limited signed URLs generated by the platform API.
/storage/{object_id}/url, the API returns a Hikigai URL under /api/v1/storage/public/{object_id} with exp and sig query params. That URL redirects (302) to S3. Your app hits Hikigai first; file bytes still come from S3 until the link expires.Base path: /api/v1/projects/{project_id}/apps/{app_id}/storage
Permissions: apps:read for list, get, stats, and signed URLs; apps:update for upload and delete.
Auth: API key (Authorization: Bearer hikigai_…) or session JWT.
/api/v1/projects/{project_id}/apps/{app_id}/storage/uploadUpload a file to platform storage. Returns object metadata and a 1-hour signed URL for immediate use.
Request Headers
Authorization: Bearer hikigai_your_api_key
Content-Type: multipart/form-data
X-Project-ID: YOUR_PROJECT_IDForm Fields
| Field | Type | Description |
|---|---|---|
file | binary | Required. Max 100MB. PDF, images, audio, zip, etc. |
metadata | JSON string | Optional key-value metadata stored with the object. Common keys: description, agent_id, generated_by. Shown in the Developer Portal Documents tab. |
ttl | integer | Optional auto-expiry in seconds (omit = permanent) |
filename | string | Optional display name override |
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/storage/upload' \
--header 'Authorization: Bearer hikigai_your_api_key' \
--form 'file=@report.pdf' \
--form 'metadata={"description":"Monthly report","agent_id":"pdf-generator"}' \
--form 'ttl=86400'Response (201)
{
"object_id": "uuid",
"object_key": "projects/{pid}/apps/{aid}/{object_id}/report.pdf",
"original_filename": "report.pdf",
"content_type": "application/pdf",
"size_bytes": 245120,
"signed_url": "https://hikigai-apps-storage-....s3.amazonaws.com/...?X-Amz-...",
"expires_at": null,
"created_at": "2026-06-11T12:00:00Z"
}/api/v1/projects/{project_id}/apps/{app_id}/storageList stored objects for an app (paginated).
Query Parameters
| Parameter | Default | Description |
|---|---|---|
page | 1 | Page number |
limit | 20 | Max 100 per page |
status | active | active | expired | all |
content_type | — | Filter by exact MIME type (e.g. application/pdf) |
content_type_prefix | — | Filter by MIME prefix (e.g. image/ or audio/) |
search | — | Filename search |
sort | created_at | created_at | size_bytes | original_filename |
order | desc | asc | desc |
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/storage?status=active&limit=20' \
--header 'Authorization: Bearer hikigai_your_api_key'Response
{
"objects": [
{
"id": "uuid",
"original_filename": "report.pdf",
"content_type": "application/pdf",
"size_bytes": 245120,
"metadata": { "description": "Monthly report", "agent_id": "pdf-generator" },
"status": "active",
"upload_source": "sdk",
"expires_at": null,
"created_at": "2026-06-11T12:00:00Z"
}
],
"total": 1,
"page": 1,
"limit": 20,
"total_pages": 1
}/api/v1/projects/{project_id}/apps/{app_id}/storage/{object_id}Get metadata for a single stored object (does not return file bytes).
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/storage/OBJECT_ID' \
--header 'Authorization: Bearer hikigai_your_api_key'/api/v1/projects/{project_id}/apps/{app_id}/storage/{object_id}/urlMint a time-limited download URL. Default TTL 1 hour; max 7 days. The returned URL is a Hikigai public link that redirects to S3.
Query Parameters
ttl=3600 # seconds (min 60, max 604800)cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/storage/OBJECT_ID/url?ttl=3600' \
--header 'Authorization: Bearer hikigai_your_api_key'Response
{
"object_id": "uuid",
"signed_url": "https://backend.hikigaiplatform.io/api/v1/storage/public/uuid?exp=...&sig=...",
"expires_in": 3600,
"expires_at": "2026-06-11T13:00:00Z"
}/api/v1/projects/{project_id}/apps/{app_id}/storage/{object_id}/downloadRedirect (302) to a fresh S3 signed URL — convenient for browser downloads.
Query Parameters
ttl=3600 # optional; seconds (min 60, max 604800). Defaults to platform signed-URL TTL.cURL Example
curl -L --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/storage/OBJECT_ID/download' \
--header 'Authorization: Bearer hikigai_your_api_key' \
-o report.pdf/api/v1/projects/{project_id}/apps/{app_id}/storage/{object_id}Delete an object from S3 and mark it deleted in the platform database.
cURL Example
curl --location --request DELETE 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/storage/OBJECT_ID' \
--header 'Authorization: Bearer hikigai_your_api_key'Response (200)
{
"success": true,
"message": "Storage object deleted"
}/api/v1/projects/{project_id}/apps/{app_id}/storage/statsStorage usage stats for the app (file count, total size, PDF count, expiring soon).
Response
{
"total_objects": 5,
"active_objects": 4,
"expired_objects": 1,
"total_size_bytes": 12582912,
"total_size_human": "12.0 MB",
"pdf_count": 3,
"expiring_soon_count": 0
}upload_source on list/get responses is sdk when the request uses an API key (Authorization: Bearer hikigai_…), otherwise portal (browser session upload).
AppSDK & AgentSDK
Both SDKs expose the same client.storage client from a deployed app or agent:
from hikigai.appsdk import AppClient
client = AppClient(api_key="hikigai_...", project_id="...")
# Upload
with open("report.pdf", "rb") as f:
result = client.storage.upload(
app_id="your-app-id",
file=f,
filename="report.pdf",
content_type="application/pdf",
metadata={
"description": "Monthly report",
"agent_id": "pdf-generator",
},
ttl=86400,
)
print(result.signed_url) # short-lived download URL from upload
# Fresh signed URL later (Hikigai public link that redirects to S3)
url = client.storage.signed_url(app_id="your-app-id", object_id=result.object_id, ttl=3600)
# List, get, delete
objects = client.storage.list(app_id="your-app-id")
info = client.storage.get(app_id="your-app-id", object_id=result.object_id)
client.storage.delete(app_id="your-app-id", object_id=result.object_id)Live Sessions
Bidirectional realtime audio over WebSocket (protocol v2). A typical live transcription client exchanges an API key for a platform token, mints a short-lived session, opens the WebSocket URL returned by mint, streams raw PCM microphone audio, and renders caption frames as they arrive.
How the two endpoints work together
Both calls are required, in order. Step 2 (/live/session) mints credentials over HTTPS. Step 3 (/live) is the WebSocket that carries audio and transcription — connect with the wss_url returned by mint.
| Call | Path | Role |
|---|---|---|
POST (HTTPS) | /api/v1/agents/{agent_slug}/live/session | Mint wss_url, live_token, and session_id. This path is not a WebSocket endpoint. |
WS | wss_url from mint (ends in /live) | Open the socket with the exact wss_url returned by mint. Authenticate with the first JSON frame using live_token. |
Typical integration flow
Replace YOUR_PROJECT_ID, hikigai_your_api_key, and {agent_slug} with your values. Audio must be mono signed 16-bit LE PCM at 16 kHz (binary WebSocket frames, not base64 JSON).
# 1. Exchange API key → platform access_token (once at app start; cache until expiry)
POST /api/v1/auth/exchange
Headers: X-API-Key, X-Project-ID
Body: {}
# 2. Mint live session (every connect / reconnect)
POST /api/v1/agents/{agent_slug}/live/session
Headers: Authorization: Bearer <access_token>, X-API-Key, X-Project-ID
Body: { "session_id": "<fresh UUID>", "user_id": "app-transcriber" }
→ wss_url, live_token, session_id
# 3. Open WebSocket(wss_url) // exact URL from step 2; path ends in /live
# First frame:
{ "type": "auth", "live_token": "…", "session_id": "…", "protocol_version": 2 }
# 4. Start mic capture
{ "type": "start", "modality": "audio", "mime_type": "audio/pcm;rate=16000", "protocol_version": 2 }
→ stream binary PCM frames while recording
# 5. Receive captions (source: input_transcription); replace UI text on partials
{ "type": "data", "modality": "text", "content": "…", "source": "input_transcription", "finished": false|true }
# 6. Stop capture / disconnect
{ "type": "end" }
{ "type": "disconnect" }
→ close WebSocketStep 1 — Auth exchange
Call once when the app starts and cache the token for mint requests. This is a platform access token for API calls, not an end-user login token. Send it as Authorization: Bearer <access_token> on the mint request in Step 2.
/api/v1/auth/exchangeExchange your project API key for a platform access token.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
Content-Type: application/jsonRequest Body
{}cURL Example
curl --location --request POST 'https://backend.hikigaiplatform.io/api/v1/auth/exchange' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'Content-Type: application/json' \
--data '{}'Response
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 86400,
"scopes": ["deploy", "invoke", "read", "manage"],
"project_id": "YOUR_PROJECT_ID"
}Step 2 — Mint live session (/live/session)
HTTPS only — this call issues credentials; it does not open the stream. Mint before every connect and reconnect. The app creates a fresh UUID for session_id and an opaque user_id for your client. The response includes wss_url, live_token, and session_id, which you pass into Step 3.
/api/v1/agents/{agent_slug}/live/sessionMint wss_url and live_token for a live WebSocket session.
Request Headers
Authorization: Bearer <access_token from Step 1>
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID
Content-Type: application/jsonRequest Body
{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "app-transcriber"
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/{agent_slug}/live/session' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'Content-Type: application/json' \
--data '{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "app-transcriber"
}'Response
{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"wss_url": "wss://backend.hikigaiplatform.io/api/v1/agents/<agent_id>/live",
"live_token": "<live_token>",
"protocol_version": 2,
"expires_in": 3600,
"agent_id": "ag_…",
"direct_connect": true
}wss_url is the Step 3 WebSocket address (path ends in /live). Use it unchanged — host and path are set by the platform (gateway or direct container).Step 3 — Connect and authenticate (/live)
After Step 2 succeeds, open a WebSocket to the wss_url in that response. That URL is the live stream endpoint (path ends in /live). Both Step 2 and Step 3 are required: mint issues credentials; this socket carries audio and captions. Authenticate with the first JSON frame using the minted live_token and the same session_id. The project API key is not sent on this socket.
/api/v1/agents/{agent_id}/liveLive stream WebSocket. Connect using the exact wss_url from Step 2.
URL
Use wss_url from the Step 2 response as-is. Example shape (host may be the platform gateway or a direct agent endpoint):
wss://backend.hikigaiplatform.io/api/v1/agents/<agent_id>/liveBrowser example (mint → /live → captions)
Assumes accessToken from Step 1. Mint over HTTPS, then open wss_url (the /live socket). Stream PCM from an AudioWorklet downsampled to 16 kHz; replace transcript text on partials.
const PROTOCOL_VERSION = 2;
const PCM_MIME = "audio/pcm;rate=16000";
let sessionId = crypto.randomUUID();
// Step 2 — mint (/live/session)
const mint = await fetch(`${baseUrl}/api/v1/agents/${agentSlug}/live/session`, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"X-API-Key": apiKey,
"X-Project-ID": projectId,
"Content-Type": "application/json",
},
body: JSON.stringify({ session_id: sessionId, user_id: "browser-transcriber" }),
});
const { wss_url, live_token, session_id } = await mint.json();
sessionId = session_id || sessionId;
// Step 3 — connect + auth (/live via wss_url)
const ws = new WebSocket(wss_url);
ws.binaryType = "arraybuffer";
ws.onopen = () => {
ws.send(JSON.stringify({
type: "auth",
live_token,
session_id: sessionId,
protocol_version: PROTOCOL_VERSION,
}));
};
// Step 4 — after getUserMedia + AudioWorklet → 16 kHz PCM
ws.send(JSON.stringify({
type: "start",
modality: "audio",
mime_type: PCM_MIME,
protocol_version: PROTOCOL_VERSION,
}));
// workletPort.onmessage = (e) => ws.send(e.data); // binary PCM frames
// Step 5 — captions
ws.onmessage = (event) => {
if (typeof event.data !== "string") return;
const msg = JSON.parse(event.data);
if (msg.type === "data" && msg.modality === "text" && msg.content) {
if (msg.source === "input_transcription" || !msg.source) {
transcriptEl.textContent = msg.content; // replace on partials
}
}
if (msg.type === "error") {
console.error(msg.message);
ws.close();
}
};
// Step 6
ws.send(JSON.stringify({ type: "end" }));
ws.send(JSON.stringify({ type: "disconnect" }));
ws.close();First frame — auth
{
"type": "auth",
"live_token": "<live_token from Step 2>",
"session_id": "<session_id from Step 2>",
"protocol_version": 2
}Step 4 — Stream audio
When capture starts, send a start frame, then continuous binary PCM. When capture stops, send end. Resample microphone input to mono PCM16 at 16 kHz before sending (browsers often capture at 44.1/48 kHz).
{ "type": "start", "modality": "audio", "mime_type": "audio/pcm;rate=16000", "protocol_version": 2 }
// binary WebSocket frames: raw PCM16 mono @ 16 kHz
// …
{ "type": "end" }- Optional: send one short silent PCM frame (~40 ms) immediately after
startto prime the session. - While paused: stop microphone PCM, keep the socket open, and send silent PCM periodically (for example every 15 s) to keep the session alive.
Step 5 — Handle transcription frames
Captions arrive as text data frames with source: "input_transcription". Transcription often emits data without a preceding server start. Silence may produce no frames.
- On each
datawith non-emptycontent, update the current pending caption. - Partials are cumulative: replace the pending line rather than appending.
- When
finishedistrue(or the server sendsend), commit the pending line. - An
errorframe ends the session; disconnect and stop reconnecting for that attempt.
{ "type": "data", "modality": "text", "content": "hello how are", "source": "input_transcription", "partial": true, "finished": false }
{ "type": "data", "modality": "text", "content": "hello how are you", "source": "input_transcription", "partial": false, "finished": true }
{ "type": "end" }
{ "type": "error", "message": "…" }Step 6 — Close
Stop capture with end, optionally send disconnect, then close the WebSocket. Closing the socket alone is sufficient; sending both frames before close is recommended.
{ "type": "end" }
{ "type": "disconnect" }
// then ws.close()Text turns
Non-transcription live agents can send text turns on the same socket after auth:
{ "type": "start", "modality": "text", "protocol_version": 2 }
{ "type": "data", "modality": "text", "content": "Summarize the last turn." }
{ "type": "end" }Troubleshooting
| Symptom | Likely cause |
|---|---|
| WS closes with 1008 / auth failure | Mint skipped, API key sent on the socket, or live_token / session_id mismatched. |
| 404 / failed WebSocket upgrade | Socket URL was constructed manually instead of using wss_url, or /live/session was opened as a WebSocket. |
| No captions after N ms | Incorrect URL, base64 JSON audio instead of binary PCM, wrong sample rate, waiting only for a server start, or silence (no transcription emitted). |
| Garbled or empty transcript | Microphone not resampled to 16 kHz mono PCM; verify mime_type on start. |
input_modality / output_modality (and optional vad) configure the live model. Transcription agents typically use audio in → text out.Speech
Real-time speech-to-speech translation and speech-to-text transcription over dedicated WebSockets. These are gateway-native endpoints, not agents — there is nothing to deploy, and they do not appear in the model registry.
credentials_missing. Connect GCP under Cloud accounts.Audio format
Input is raw little-endian 16-bit mono PCM at 16 kHz. Translate output is the same at 24 kHz. Chunks of about 100 ms are the recommended balance of throughput and latency. Both SDKs convert from μ-law, Float32, and other sample rates for you.
Step 1 — Mint a speech token
/api/v1/speech/tokensExchange a project credential for a short-lived, browser-safe speech pass.
Call this from your backend so your API key never reaches an untrusted client. Credentials and entitlement are validated here, so a misconfigured organization fails with an actionable error rather than a socket that dies on first audio.
Request
{
"endpoint": "translate",
"config": {
"target_language_code": "es",
"echo_target_language": true,
"input_transcription": true,
"output_transcription": true
},
"locked": false,
"ttl_seconds": 600
}Set locked: true to forbid configure frames, pinning the session to this exact config — useful for a kiosk or a phone line.
Response
{
"speech_token": "<jwt>",
"expires_in": 600,
"session_id": "spch_4f1c9a2b8e0d7c65",
"endpoint": "translate",
"config": { "target_language_code": "es", ... },
"locked": false
}/api/v1/speech/languagesSupported BCP-47 codes per endpoint. Unauthenticated.
Translate takes bare language subtags (es, pt-BR); transcribe takes full locales (es-ES, en-US). Sending the wrong shape returns unsupported_language with a suggestion.
{
"translate": { "field": "target_language_code", "codes": ["af", "ak", ...] },
"transcribe": { "field": "language_codes", "codes": ["af-ZA", "am-ET", ...] }
}Step 2 — Connect
Both endpoints speak the same protocol: JSON control frames plus raw binary PCM, identical in grammar to the live agent tunnel. The first frame must be auth, within 10 seconds.
Authentication
Any one of three credentials:
{"type": "auth", "speech_token": "<from step 1>"}
{"type": "auth", "api_key": "hikigai_your_project_api_key"}
{"type": "auth", "access_token": "YOUR_JWT", "project_id": "YOUR_PROJECT_ID"}Server frames
| Frame | Meaning |
|---|---|
ready | Setup acknowledged upstream. Carries session_id, model, resolved config, audio formats, and a resume_token. Wait for this before sending audio — the model discards anything that arrives earlier. |
transcript | source is input or output; final distinguishes interim from settled text. |
| binary | Translated audio, 24 kHz PCM. Translate only. |
reconfigured | A configure was applied; echoes the new config. |
turn_complete / interrupted | Turn boundaries. |
error | Typed code plus a human-readable message. |
/api/v1/speech/translateSpeech-to-speech translation across 80+ languages. Emits translated audio and transcripts.
Model
gemini-3.5-live-translate-previewConfiguration
| Field | Default | Description |
|---|---|---|
target_language_code | "en" | BCP-47 output language. One per session. |
echo_target_language | true | When the speaker already uses the target language, echo them through rather than staying silent. |
input_transcription | true | Transcribe the source audio. |
output_transcription | true | Transcribe the translated audio (subtitles). |
The last three defaults differ from Google's, which default echo off and both transcriptions off.
Full exchange
--> {"type": "auth", "speech_token": "<token>"}
--> {"type": "start", "modality": "audio", "mime_type": "audio/pcm;rate=16000"}
<-- {"type": "ready", "session_id": "spch_...", "model": "gemini-3.5-live-translate-preview",
"config": {"target_language_code": "es", "echo_target_language": true, ...},
"audio": {"input": {"encoding": "pcm_s16le", "sample_rate": 16000, "channels": 1},
"output": {"encoding": "pcm_s16le", "sample_rate": 24000, "channels": 1}}}
--> <binary PCM @ 16 kHz>
<-- {"type": "transcript", "source": "input", "text": "Good morning", "language_code": "en", "final": true}
<-- <binary PCM @ 24 kHz>
<-- {"type": "transcript", "source": "output", "text": "Buenos días", "final": true}
<-- {"type": "turn_complete"}Changing language mid-session
Send configure at any time. The gateway brings up a replacement model session before retiring the old one, so audio keeps flowing and the listener hears no gap. No reconnect, no new token.
--> {"type": "configure", "config": {"target_language_code": "fr"}}
<-- {"type": "reconfigured", "changed": true, "config": {"target_language_code": "fr", ...}}Rejected if the token was minted with locked: true.
/api/v1/speech/transcribeSpeech-to-text across 85+ locales, with interim results as the speaker talks.
Model
gemini-3.5-transcribe-live-previewConfiguration
| Field | Default | Description |
|---|---|---|
language_codes | auto-detect | Up to 8 full locales (en-US, not en) to bias recognition. |
custom_vocabulary | — | Up to 1000 names, jargon, or product terms to bias towards. |
Full exchange
--> {"type": "auth", "speech_token": "<token>"}
--> {"type": "start", "modality": "audio", "mime_type": "audio/pcm;rate=16000"}
<-- {"type": "ready", "session_id": "spch_...", "model": "gemini-3.5-transcribe-live-preview"}
--> <binary PCM @ 16 kHz>
<-- {"type": "transcript", "source": "input", "text": "the quarterly", "language_code": "en-US", "final": false}
<-- {"type": "transcript", "source": "input", "text": "the quarterly report", "language_code": "en-US", "final": true}Errors
| Code | Cause and fix |
|---|---|
credentials_missing | Personal organization, or no GCP connected. Speech is team-only and bills to your own cloud project. |
unsupported_language | Wrong code shape for the endpoint. The message suggests the right one. |
stream_cap_exceeded | Organization is at its concurrent-session cap (50 by default, raisable by an admin). Reconnecting with the same resume_token reclaims the original slot rather than competing for a new one. |
config_invalid | A config field failed validation; the message names it. |
forbidden | A configure was sent on a token minted with locked: true. |
session_duration_exceeded | Session passed the 1 hour wall-clock ceiling. |
upstream_unavailable | The model was unreachable. Retry with backoff. |
Rooms
Project-scoped realtime collaboration over a single WebSocket endpoint WS /api/v1/rooms/ws. Two complementary protocols share that socket:
- WebSocket rooms — JSON pub/sub (join, publish, presence, replay). Use for text events like live transcripts.
- WebRTC signalling —
rtc_*frames for mesh A/V calls. The platform relays SDP/ICE only; media is peer-to-peer.
Rooms are namespaced server-side as {project_id}:{room} so members of one project never see another project's traffic. Use a project-scoped API key, a JWT from POST /api/v1/auth/exchange, or a short-lived room_token.
Room naming, creation & lifecycle
There is no separate "create room" API. You choose a room name in your application and send a join frame — the platform creates the room implicitly the first time anyone joins that name within your project.
| Question | Answer |
|---|---|
| Who picks the room name? | Your application — pass any valid string in join (e.g. consultation-42). |
| When is a room created? | On the first join to that name. No pre-registration. |
| How do two apps find each other? | Agree on the same room string outside the protocol (config, URL, DB). The platform does not auto-route clients. |
| When does a room go away? | When the last member leaves (implicit GC). Leaving also drops any WebRTC peer on that connection. |
consultation-42 — they are separate rooms keyed as {project_id}:consultation-42.WebSocket rooms (pub/sub)
JSON event fan-out for text / structured data. Typical flow: App A publishes transcript lines; App B only joins and displays them.
Example flow — publisher → subscriber
Publisher (App A) Subscriber (App B)
───────────────── ──────────────────
1. connect WS (idle)
2. auth (api_key | access_token) (idle)
3. ← ready (idle)
4. join "consultation-42" ←── creates room if new
5. ← joined
6. publish transcript.* 1. connect WS
2. auth (same project)
3. ← ready
4. join "consultation-42"
5. ← joined
6. ← message { event, data, seq }Both clients must use the same project and same room name. Order does not matter — whichever joins first creates the room.
/api/v1/rooms/wsRooms WebSocket protocol. First frame must be auth; then join, publish, and receive broadcasts. WebRTC rtc_* frames use this same socket (see WebRTC section below).
Connection URL
wss://backend.hikigaiplatform.io/api/v1/rooms/wsProtocol summary
| Direction | Frames |
|---|---|
| Client → server | auth (first only) → join → publish / leave / who / ping / refresh. Optional: kick / close_room (manage) / disconnect. |
| Server → client | ready → joined / left → message, presence, who, pong, refreshed, or error |
| Room names | 1–128 characters: letters, digits, _, ., :, -. Must start with a letter or digit. |
Step 1 — Connect and authenticate
{"type": "auth", "api_key": "hikigai_your_project_api_key"}Or JWT from auth/exchange:
{"type": "auth", "access_token": "YOUR_JWT_TOKEN", "project_id": "YOUR_PROJECT_ID"}Or minted room token:
{"type": "auth", "room_token": "YOUR_ROOM_TOKEN"}Success reply (API keys include rtc):
{"type": "ready", "connection_id": "conn_a1b2c3d4e5f6", "project_id": "YOUR_PROJECT_ID", "capabilities": ["manage", "publish", "subscribe", "rtc"]}Step 2 — Join a room
{"type": "join", "room": "consultation-42"}Rejoin with replay cursor:
{"type": "join", "room": "consultation-42", "last_seq": 12}{"type": "joined", "room": "consultation-42", "capabilities": ["manage", "publish", "subscribe", "rtc"], "seq": 0, "members": [{"id": "conn_a1b2c3d4e5f6", "principal": "..."}]}Step 3 — Publish
{"type": "publish", "room": "consultation-42", "event": "transcript.partial", "data": {"text": "Patient reports mild headache", "turn": 1, "finished": false}}{"type": "publish", "room": "consultation-42", "event": "transcript.final", "data": {"text": "Patient reports mild headache since yesterday.", "turn": 1, "finished": true}}Set echo: true to also receive your own publish (default false).
Step 4 — Receive
{"type": "message", "room": "consultation-42", "event": "transcript.partial", "data": {"text": "...", "turn": 1, "finished": false}, "seq": 3, "sender": "conn_xyz", "ts": "2026-07-29T12:00:00.000Z"}Step 5 — Leave / disconnect
{"type": "leave", "room": "consultation-42"}
{"type": "disconnect"}End-to-end example (wscat)
# Tab 1 — publisher
wscat -c "wss://backend.hikigaiplatform.io/api/v1/rooms/ws"
{"type": "auth", "api_key": "hikigai_your_project_api_key"}
{"type": "join", "room": "consultation-42"}
{"type": "publish", "room": "consultation-42", "event": "transcript.final", "data": {"text": "Hello", "turn": 1, "finished": true}}
# Tab 2 — subscriber (same key + room)
{"type": "auth", "api_key": "hikigai_your_project_api_key"}
{"type": "join", "room": "consultation-42"}
# ← message { "event": "transcript.final", "data": { "text": "Hello", ... } }JavaScript client pattern
const ws = new WebSocket("wss://backend.hikigaiplatform.io/api/v1/rooms/ws");
ws.onopen = () => {
ws.send(JSON.stringify({ type: "auth", api_key: "hikigai_your_project_api_key" }));
};
ws.onmessage = (ev) => {
const frame = JSON.parse(ev.data);
if (frame.type === "ready") {
ws.send(JSON.stringify({ type: "join", room: "consultation-42" }));
} else if (frame.type === "message") {
console.log(frame.event, frame.data);
}
};
function publish(event, data) {
ws.send(JSON.stringify({ type: "publish", room: "consultation-42", event, data }));
}Error codes (WebSocket rooms)
| Code | Meaning |
|---|---|
unauthorized | Invalid credentials, auth timeout, or project mismatch |
forbidden | Not allowed to join or publish |
bad_frame | Malformed JSON or invalid room name |
payload_too_large | Exceeds size limit (128 KB default) |
rate_limited | Join or publish rate exceeded |
room_full | Member cap reached |
cursor_expired | Replay buffer no longer covers last_seq |
job.completed) fan out to the project notifications room automatically./api/v1/rooms/tokensMint a short-lived room token for end-user clients (scoped room patterns and capabilities).
Request Headers
X-API-Key: hikigai_your_project_api_key
X-Project-ID: YOUR_PROJECT_ID
Content-Type: application/jsonRequest Body
{
"rooms": ["consultation-*"],
"capabilities": ["subscribe", "publish"],
"principal": "end-user-123",
"ttl_seconds": 600
}For WebRTC, add "rtc" to capabilities. API-key / JWT principals already have rtc.
/api/v1/rooms/{room}/publishServer-side publish without holding a WebSocket — for backends, workers, or services.
Request Headers
X-API-Key: hikigai_your_project_api_key
X-Project-ID: YOUR_PROJECT_ID
Content-Type: application/jsonRequest Body
{
"event": "appointment.reminder",
"data": {"patient_id": "p-001", "slot": "2026-07-30T09:00:00Z"}
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/rooms/consultation-42/publish' \
--header 'X-API-Key: hikigai_your_project_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'Content-Type: application/json' \
--data '{"event": "note.updated", "data": {"text": "Labs ordered"}}'/api/v1/rooms/statsHub statistics including backplane health (project-scoped API key required).
Request Headers
X-API-Key: hikigai_your_project_api_key
X-Project-ID: YOUR_PROJECT_IDWebRTC signalling (mesh)
Peer-to-peer audio/video calls negotiated over the same /api/v1/rooms/ws socket. The platform is a signalling authority only— it relays SDP and ICE. Media never traverses Hikigai services.
Structure — WebSocket vs WebRTC
WebRTC rooms are a layer on rooms WebSocket, not a replacement for it. The WebSocket is always required for setup; WebRTC carries media after peers connect.
Rooms WebSocket (/api/v1/rooms/ws) ← always needed
• auth / join / leave
• publish / message (JSON events, e.g. transcript text)
• rtc_* signalling (SDP + ICE — how the call is set up)
Hikigai sees these frames. It does NOT see mic/camera bytes.
WebRTC (browser ↔ browser) ← after rtc_join succeeds
• audio / video tracks (P2P)
• optional DataChannel (P2P text via sendText)
Media never goes through Hikigai.| Layer | Carries | Through Hikigai? |
|---|---|---|
| Rooms WebSocket | Auth, membership, publish, rtc_* | Yes — always |
| WebRTC media | Mic / camera | No (P2P after connect) |
| WebRTC DataChannel | sendText / sendData | No (P2P after connect) |
Why WebSocket is required: peers must exchange SDP/ICE before a call exists. That cannot use WebRTC itself (chicken-and-egg). Hikigai’s rooms socket is that signalling channel. After the call is up, optional DataChannel text can stay P2P.
An RTC peer must already be a room member: join first, then rtc_join. Requires the rtc capability (included for API keys / JWTs; must be requested on room_token).
Example flow — two peers
Peer A (first) Peer B (second)
────────────── ───────────────
1. WS connect + auth (later)
2. join "call-1"
3. rtc_join "call-1"
4. ← rtc_joined { peers: [], ice_servers }
1. WS connect + auth
2. join "call-1"
3. rtc_join "call-1"
4. ← rtc_joined { peers: [A], initiator: false }
5. ← rtc_peer_joined { id: B, initiator: true }
6. createOffer → rtc_offer → B
5. ← rtc_offer
6. createAnswer → rtc_answer → A
7. ← rtc_answer
8. ↔ rtc_candidate (ICE trickle) ↔ rtc_candidate
9. P2P media connected P2P media connectedThe server tells the existing peer to create the offer (initiator: true). The newcomer waits. Each pair also gets a polite flag for perfect-negotiation glare recovery.
Client → server frames
| Frame | Fields | Purpose |
|---|---|---|
rtc_join | room, mode?, agent_id?, metadata? | Announce as an RTC peer (idempotent) |
rtc_leave | room | Leave the call; stay in the room |
rtc_offer / rtc_answer | room, target, sdp | Directed SDP (exactly one peer) |
rtc_candidate | room, target, candidate | ICE trickle; empty candidate = end-of-candidates |
rtc_who | room | List current RTC peers |
Server → client frames
| Frame | Carries |
|---|---|
rtc_joined | peer_id, session_id, mode, peers[], ice_servers[], max_peers |
rtc_peer_joined | id, initiator, polite, metadata |
rtc_peer_left | id, reason |
rtc_offer / rtc_answer / rtc_candidate | Relayed to target only, plus sender |
JavaScript example (signalling + RTCPeerConnection)
const ws = new WebSocket("wss://backend.hikigaiplatform.io/api/v1/rooms/ws");
const pcs = new Map();
let iceServers = [];
ws.onopen = () => ws.send(JSON.stringify({ type: "auth", api_key: "hikigai_your_project_api_key" }));
ws.onmessage = async (ev) => {
const f = JSON.parse(ev.data);
if (f.type === "ready") {
ws.send(JSON.stringify({ type: "join", room: "call-1" }));
} else if (f.type === "joined") {
ws.send(JSON.stringify({ type: "rtc_join", room: "call-1", metadata: { display: "Ada" } }));
} else if (f.type === "rtc_joined") {
iceServers = f.ice_servers || [];
} else if (f.type === "rtc_peer_joined" && f.initiator) {
const pc = ensurePc(f.id);
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
ws.send(JSON.stringify({ type: "rtc_offer", room: "call-1", target: f.id, sdp: offer.sdp }));
} else if (f.type === "rtc_offer") {
const pc = ensurePc(f.sender);
await pc.setRemoteDescription({ type: "offer", sdp: f.sdp });
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
ws.send(JSON.stringify({ type: "rtc_answer", room: "call-1", target: f.sender, sdp: answer.sdp }));
} else if (f.type === "rtc_answer") {
await pcs.get(f.sender)?.setRemoteDescription({ type: "answer", sdp: f.sdp });
} else if (f.type === "rtc_candidate" && f.candidate?.candidate) {
await pcs.get(f.sender)?.addIceCandidate(f.candidate);
}
};
function ensurePc(peerId) {
if (pcs.has(peerId)) return pcs.get(peerId);
const pc = new RTCPeerConnection({ iceServers });
pc.onicecandidate = (e) => {
if (!e.candidate) return;
ws.send(JSON.stringify({
type: "rtc_candidate", room: "call-1", target: peerId, candidate: e.candidate.toJSON()
}));
};
pcs.set(peerId, pc);
return pc;
}Browser helper — WebRtcRoom
The console ships a mesh client at frontend/lib/webrtc-room.ts(and useWebRtcRoom). It owns signalling + RTCPeerConnections; you attach streams and optionally send text.
import { WebRtcRoom } from "@/lib/webrtc-room";
const room = new WebRtcRoom({
room: "call-1",
auth: { roomToken },
remoteAudioEnabled: true, // false = join muted on remote playback
onLocalStream: (stream) => { /* <video>/<audio muted> */ },
onRemoteStream: (peerId, stream) => { /* attach */ },
onMessage: (frame) => { /* rooms publish fan-out */ },
onDataMessage: (peerId, msg) => { /* P2P DataChannel */ },
});
await room.start({ audio: true, video: true }); // or start(false) receive-only
room.setMicrophoneEnabled(false);
room.setCameraEnabled(true);
room.setRemoteAudioEnabled(false); // mute remote tracks, stay in call
// Text — rooms WebSocket (any member, even without rtc_join on the other side):
room.publish("note", { text: "hello" });
// Text — RTCDataChannel (connected RTC peers only; not rooms publish):
room.sendText("hello");
room.sendData("chat", { text: "hi" });
await room.stop();publish / onMessage = rooms WebSocket.sendText / sendData / onDataMessage = peer DataChannel. Signalling always uses the rooms socket.
Combining WebRTC + live transcription
Media stays P2P. For ASR, stream mic PCM to a live agent session in parallel, then publish transcript events into the same room so text-only subscribers see them:
1. App A: rooms auth → join → rtc_join (optional agent_id) + live-transcription-agent PCM
2. App A: on ASR text → publish { event: "transcript.final", data: { text, turn } }
3. App B: rooms auth → join only (no rtc_join) → render message frames as textPass agent_id on rtc_join to also emit stream.started / stream.stopped with transport="webrtc" on the platform event bus.
WebRTC error codes
| Code | Meaning |
|---|---|
rtc_disabled | WebRTC rooms disabled or SFU mode without config |
rtc_not_joined | Sent signalling before rtc_join |
rtc_room_full | Peer cap reached (default 6 for mesh) |
peer_not_found | Directed frame target is gone |
forbidden | Missing rtc capability or not a room member |
RoomSession in AgentSDK / AppSDK (Python) or @hikigai/agent-sdk / @hikigai/app-sdk (Node) for signalling helpers. Browsers can drive RTCPeerConnection from these frames or use the platform WebRtcRoom helper.Multi-Cloud
Catalog-driven deployment targets for agents, apps, and MCP servers on GCP or AWS. Optional BYOC credentials are managed under /api/v1/cloud/credentials.
/api/v1/cloud/catalogList providers, services, regions, zones, and per-service JSON Schema. Optional workload filter: app | agent | mcp.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_IDcURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/cloud/catalog?workload=agent' \
--header 'X-API-Key: hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID'/api/v1/cloud/targets/validateDry-run a deployment target (service, region, config) before deploy.
Request Body
{
"workload": "app",
"service_id": "gcp-cloud-run",
"region": "us-central1",
"config": {"cpu": "1", "memory": "512Mi"}
}Webhooks (Event Bus)
Project-scoped webhook subscriptions for platform CloudEvents (agent deploy/delete, jobs, invocations, storage). Deliveries are HMAC-SHA256 signed.
/api/v1/webhooksList webhook subscriptions for the project.
Request Headers
X-API-Key: hikigai_your_api_key
X-Project-ID: YOUR_PROJECT_ID/api/v1/webhooksCreate a webhook subscription. The signing secret is returned once.
Request Body
{
"url": "https://ci.example.com/hooks/hikigai",
"event_types": ["agent.deployed", "agent.deleted"],
"description": "deploy notifications"
}/api/v1/webhooks/{id}/testSend a synthetic webhook.test ping to verify the endpoint.
Also supports rotate-secret, deliveries list, and redelivery.
Even Realities G2 Glasses
Architecture
Even Realities G2 glasses have a 640×350 green monochrome display, mic, and touch temples — but no browser. The Even phone app loads your page in a WebView and drives the lenses over Bluetooth via @evenrealities/even_hub_sdk. Hikigai deploys that page like any other app (framework even-g2), builds the Even Hub .ehpk package, and exposes console APIs for info, QR testing, package download, and manifest validation.
- Dev mode: scan the QR (live URL) in the Even app — no store review.
- Even Hub store: download the
.ehpkand upload it manually in the Even Hub portal (no public upload API). - Agent calls: keep the API key on a server proxy (see
templates/even-g2). Use normal agent invoke — not a separate glasses runtime API. - Voice: agent must allow audio in its input modalities; list/text questions work with any text agent.
Proxy environment (your app server)
Not console API fields — these are what the deployed G2 proxy reads:
HIKIGAI_API_KEY/HIKIGAI_PROJECT_ID— injected on Hikigai deploy; set locally in.env.HIKIGAI_AGENT_ID— required; set under Environment in the console (slug or id).HIKIGAI_PLATFORM_URL(optional) — API base URL override.GLASSES_PAGE_CHARS(optional) — page size for answers (starter default 420).
app.json: name ≤ 20, tagline ≤ 50; unique reverse-DNS package_id; typical permissions network + g2-microphone. Starter: templates/even-g2 (check / qr / pack).
Base path: /api/v1/projects/{project_id}/apps/{app_id}/even-g2
Permission: apps:read on all four endpoints.
Auth: project session JWT or API key with project scope (same as other app routes).
Detection: framework is even-g2 when the repo has both app.json and @evenrealities/even_hub_sdk. SDK helpers: Node AppSDK · Python AppSDK.
/api/v1/projects/{project_id}/apps/{app_id}/even-g2Console panel payload: whether the app is even-g2, live URL, QR payload, validated manifest, package state, and Even Hub package/portal links.
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/even-g2' \
--header 'Authorization: Bearer hikigai_your_api_key'Response (200)
{
"app_id": "app_...",
"enabled": true,
"framework": "even-g2",
"live_url": "https://your-app.example.com",
"dev_mode_qr_payload": "https://your-app.example.com",
"manifest": {
"package_id": "ai.hikigai.demo",
"edition": "g2",
"name": "Demo",
"version": "0.1.0",
"min_sdk_version": "0.0.15",
"entrypoint": "index.html",
"permissions": [{ "name": "network", "desc": "...", "whitelist": [] }],
"supported_languages": ["en"]
},
"deployment_id": "dep_...",
"deployment_status": "active",
"package_available": true,
"package_size_bytes": 184320,
"package_filename": "ai.hikigai.demo-0.1.0.ehpk",
"package_error": null,
"cli_version": "0.1.14",
"portal_url": "https://hub.evenrealities.com",
"docs_url": "https://hub.evenrealities.com/docs/get-started/overview",
"sdk_package": "@evenrealities/even_hub_sdk",
"cli_package": "@evenrealities/evenhub-cli",
"simulator_package": "@evenrealities/evenhub-simulator"
}enabled is true only when framework == "even-g2".dev_mode_qr_payload is the live URL string (same as evenhub qr --url). Package fields come from artifacts.even_g2 on the latest active deployment.
/api/v1/projects/{project_id}/apps/{app_id}/even-g2/qr.pngDev-mode QR as PNG. Scanning it in the Even phone app opens the live URL on the glasses.
Query Parameters
| Param | Type | Description |
|---|---|---|
scale | int 2–20 | Pixel scale for the QR modules. Default 8. |
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/even-g2/qr.png?scale=8' \
--header 'Authorization: Bearer hikigai_your_api_key' \
--output even-g2-dev-mode.pngResponse
200 — image/png, Cache-Control: no-store.
409 — app has no live URL yet (deploy first). 404 — app not found.
/api/v1/projects/{project_id}/apps/{app_id}/even-g2/packageStream the packed .ehpk for manual upload in the Even Hub developer portal. The backend fetches it from the live host under an unguessable path.
Query Parameters
| Param | Type | Description |
|---|---|---|
deployment_id | string | Optional. Defaults to the latest active deployment with an even_g2 artifact. |
cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/even-g2/package' \
--header 'Authorization: Bearer hikigai_your_api_key' \
--output ai.hikigai.demo-0.1.0.ehpkResponse
200 — application/octet-stream with Content-Disposition: attachment; filename="…ehpk".
400 — not an even-g2 app. 404 — no package built yet.413 — over size cap. 502 — live host did not return the package.
/api/v1/projects/{project_id}/apps/{app_id}/even-g2/validate-manifestValidate a parsed app.json with the same rules the deploy pipeline (and Even Hub CLI) apply. Always returns 200; check valid.
Request Body
{
"manifest": {
"package_id": "ai.hikigai.demo",
"edition": "g2",
"name": "Demo",
"version": "0.1.0",
"min_sdk_version": "0.0.15",
"entrypoint": "index.html",
"permissions": [
{ "name": "network", "desc": "Talk to your Hikigai agent", "whitelist": [] },
{ "name": "g2-microphone", "desc": "Capture voice questions" }
],
"supported_languages": ["en"],
"tagline": "Ask an agent from your glasses",
"description": "Optional longer description (max 1024 chars)."
}
}cURL Example
curl --location 'https://backend.hikigaiplatform.io/api/v1/projects/YOUR_PROJECT_ID/apps/YOUR_APP_ID/even-g2/validate-manifest' \
--header 'Authorization: Bearer hikigai_your_api_key' \
--header 'Content-Type: application/json' \
--data @manifest-body.jsonResponse (200)
{ "valid": true, "error": null, "manifest": { /* normalised */ } }
// or
{ "valid": false, "error": "app.json: name must be 1 to 20 characters", "manifest": null }Required fields: package_id, edition, name (≤20), version (x.y.z), min_sdk_version, entrypoint, permissions[], supported_languages[]. Permissions: network, g2-microphone, phone-microphone, album, location, camera (whitelist only on network). Languages: en, de, fr, es, it, zh, ja, ko.
Talking to agents from a G2 app
There is no glasses-specific invoke route. Your WebView talks to your proxy (credentials never ship in the public page). The proxy uses the standard agent invoke API. For voice, send WAV as an attachments entry — the agent must allow audio in its input modalities; list/text questions work with any text agent.
# Text question (from your proxy)
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/YOUR_AGENT_SLUG/invoke' \
--header 'Authorization: Bearer hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'Content-Type: application/json' \
--data '{
"input": "What are the contraindications?",
"session_id": "wearer-123"
}'
# Voice (WAV attachment — same shape the starter template uses)
curl --location 'https://backend.hikigaiplatform.io/api/v1/agents/YOUR_AGENT_SLUG/invoke' \
--header 'Authorization: Bearer hikigai_your_api_key' \
--header 'X-Project-ID: YOUR_PROJECT_ID' \
--header 'Content-Type: application/json' \
--data '{
"input": "Answer the question in this recording.",
"session_id": "wearer-123",
"attachments": [
{ "data_base64": "<BASE64_WAV>", "mime_type": "audio/wav" }
]
}'Paginate the answer for the 640×350 display with the SDK helpers (default char budget is 2000; the starter template uses 420 via GLASSES_PAGE_CHARS):
import { normalizeForGlasses, paginateForGlasses } from '@hikigai/app-sdk'
const pages = paginateForGlasses(response.content, { maxChars: 420 })
// pages → string[] ready for TextContainerProperty on the glassesNeed more help? Check the Getting Started guide or review the Platform API Reference.