Quickstart
Make your first call to the Developer API the desktop app serves on your PC. Nothing here goes through a Genisys server; the API listens on 127.0.0.1 only.
- Enable the local API. In the Genisys desktop app, open the Developer console and turn on the local API. It is off until you do, and listens on
http://127.0.0.1:4319by default (the port can be changed there). - Create a test key. In the console, create an API key in test mode and give it only the scopes you need (for this guide:
projects:read,runs:write,runs:read,plugins:invoke). Optionally limit it to projects, and set a per-minute limit and daily or monthly token budgets. Test keys start withgsk_test_; their runs are marked test. Copy the secret when it is shown and keep it like a password. - Call the API. Every request sends
Authorization: Bearer <key>.
With curl
List the projects your key may use:
export GENISYS_KEY=gsk_test_… # your test key
curl http://127.0.0.1:4319/v1/projects \
-H "Authorization: Bearer $GENISYS_KEY"Start an agent run and wait for it to finish. The Idempotency-Key header is optional (up to 100 characters). Runs count against the key's token budget.
curl http://127.0.0.1:4319/v1/runs \
-X POST \
-H "Authorization: Bearer $GENISYS_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-1" \
-d '{ "projectId": "<a project id from /v1/projects>", "prompt": "Summarise the open tasks." }'Invoke a plugin tool (test keys can call draft, preview and production plugins):
curl http://127.0.0.1:4319/v1/plugins/word-tools/invoke \
-X POST \
-H "Authorization: Bearer $GENISYS_KEY" \
-H "Content-Type: application/json" \
-d '{ "tool": "word_count", "input": { "text": "hello plugin world" } }'From JavaScript
The @genisys/sdk package (packages/sdk in the Genisys repository) is not on npm yet. This dependency-free client covers every operation in the API reference; copy it into your project.
// genisys.mjs: a small client for the local Developer API (Node 22+ or any modern browser runtime).
const BASE = process.env.GENISYS_URL ?? 'http://127.0.0.1:4319';
const KEY = process.env.GENISYS_KEY; // gsk_test_… or gsk_live_…; never commit it
async function call(method, path, body, headers = {}) {
const response = await fetch(BASE + path, {
method,
headers: { authorization: `Bearer ${KEY}`, ...(body ? { 'content-type': 'application/json' } : {}), ...headers },
body: body ? JSON.stringify(body) : undefined,
});
const json = await response.json();
if (!response.ok) throw new Error(`${json.error.code}: ${json.error.message}`);
return json;
}
export const genisys = {
listProjects: () => call('GET', '/v1/projects'),
createRun: (projectId, prompt, idempotencyKey) => call('POST', '/v1/runs', { projectId, prompt }, idempotencyKey ? { 'idempotency-key': idempotencyKey } : {}),
getRun: (id) => call('GET', `/v1/runs/${encodeURIComponent(id)}`),
getUsage: () => call('GET', '/v1/usage'),
listPlugins: () => call('GET', '/v1/plugins'),
invokePlugin: (id, tool, input) => call('POST', `/v1/plugins/${encodeURIComponent(id)}/invoke`, { tool, input }),
};
// Example
const { data: projects } = await genisys.listProjects();
const run = await genisys.createRun(projects[0].id, 'Summarise the open tasks.', 'quickstart-1');
console.log(run.status, run.output, run.usage);When a call fails
Errors come back as { "error": { "code", "message" } }. A missing or revoked key is unauthorized; a missing scope or a project outside the key's limit is forbidden; a spent budget is budget_exceeded and too many requests in a minute is rate_limited. See all error codes.
Next: write a plugin or try one in the playground.