API info and organization
Check what an API key can do, and read or update your organization's profile.
| Method | Path | Scope |
|---|---|---|
GET |
/api/v1 |
None |
GET |
/api/v1/organization |
organization:read |
PATCH |
/api/v1/organization |
organization:write |
None of these endpoints fires a webhook.
The JavaScript examples on this page assume a headers object holding your key:
const headers = {
'X-API-Key': process.env.GPS_API_KEY_ID,
'X-API-Secret': process.env.GPS_API_SECRET,
};
Get API info#
GET /api/v1
Returns the API version, the organization and scopes of the key you called with, the rate limit, and a map of every endpoint. Any valid key can call it, so it's a good first request when you set up an integration.
Unlike other endpoints, the fields are at the top level, not under data.
Parameters: none.
curl https://plan.empiraa.app/api/v1 \
-H "X-API-Key: $GPS_API_KEY_ID" \
-H "X-API-Secret: $GPS_API_SECRET"
const res = await fetch('https://plan.empiraa.app/api/v1', {
headers: {
'X-API-Key': process.env.GPS_API_KEY_ID,
'X-API-Secret': process.env.GPS_API_SECRET,
},
});
const info = await res.json();
console.log(info.scopes);
Response 200
| Field | Type | Notes |
|---|---|---|
version |
string | Always v1. |
organization |
string | The key's organization ID. |
subAccountId |
string or null | Reserved; null for keys created in Settings. |
role |
string | The key's role. Keys created in Settings are scoped: their access is set by scopes. |
keyName |
string | The name given to the key. |
scopes |
string[] | The key's scopes. |
rateLimit.requestsPerMinute |
integer | 100. |
endpoints |
object | Every endpoint, grouped by resource. |
documentation |
string | A link to the API documentation. |
{
"version": "v1",
"organization": "9b2f4e1a-6c3d-4e8f-a1b2-c3d4e5f6a7b8",
"subAccountId": null,
"role": "scoped",
"keyName": "Production integration",
"scopes": ["goals:read", "objectives:read", "progress:write"],
"rateLimit": { "requestsPerMinute": 100 },
"endpoints": {
"organization": {
"get": "GET /api/v1/organization",
"update": "PATCH /api/v1/organization"
},
"goals": {
"list": "GET /api/v1/goals",
"get": "GET /api/v1/goals/:id",
"create": "POST /api/v1/goals",
"update": "PATCH /api/v1/goals/:id",
"delete": "DELETE /api/v1/goals/:id",
"objectives": "GET /api/v1/goals/:goalId/objectives",
"actions": "GET /api/v1/goals/:goalId/actions"
},
"objectives": {
"list": "GET /api/v1/objectives",
"get": "GET /api/v1/objectives/:id",
"create": "POST /api/v1/objectives",
"update": "PATCH /api/v1/objectives/:id",
"delete": "DELETE /api/v1/objectives/:id",
"actions": "GET /api/v1/objectives/:objectiveId/actions"
},
"actions": {
"list": "GET /api/v1/actions",
"get": "GET /api/v1/actions/:id",
"create": "POST /api/v1/actions",
"update": "PATCH /api/v1/actions/:id",
"delete": "DELETE /api/v1/actions/:id"
},
"meetings": {
"list": "GET /api/v1/meetings",
"get": "GET /api/v1/meetings/:id",
"create": "POST /api/v1/meetings",
"update": "PATCH /api/v1/meetings/:id",
"delete": "DELETE /api/v1/meetings/:id"
},
"ideas": {
"list": "GET /api/v1/ideas",
"get": "GET /api/v1/ideas/:id",
"create": "POST /api/v1/ideas",
"update": "PATCH /api/v1/ideas/:id",
"delete": "DELETE /api/v1/ideas/:id"
},
"comments": {
"listOnGoal": "GET /api/v1/goals/:goalId/comments",
"createOnGoal": "POST /api/v1/goals/:goalId/comments",
"deleteOnGoal": "DELETE /api/v1/goals/:goalId/comments/:commentId",
"listOnObjective": "GET /api/v1/objectives/:objectiveId/comments",
"createOnObjective": "POST /api/v1/objectives/:objectiveId/comments",
"deleteOnObjective": "DELETE /api/v1/objectives/:objectiveId/comments/:commentId",
"listOnMeeting": "GET /api/v1/meetings/:meetingId/comments",
"createOnMeeting": "POST /api/v1/meetings/:meetingId/comments",
"deleteOnMeeting": "DELETE /api/v1/meetings/:meetingId/comments/:commentId",
"listOnAction": "GET /api/v1/actions/:actionId/comments",
"createOnAction": "POST /api/v1/actions/:actionId/comments",
"deleteOnAction": "DELETE /api/v1/actions/:actionId/comments/:commentId",
"listOnIdea": "GET /api/v1/ideas/:ideaId/comments",
"createOnIdea": "POST /api/v1/ideas/:ideaId/comments",
"delete": "DELETE /api/v1/comments/:id?type=goal|objective|meeting|action|idea"
},
"progress": {
"list": "GET /api/v1/objectives/:objectiveId/progress",
"create": "POST /api/v1/objectives/:objectiveId/progress"
},
"users": {
"list": "GET /api/v1/users",
"get": "GET /api/v1/users/:id",
"create": "POST /api/v1/users",
"update": "PATCH /api/v1/users/:id",
"delete": "DELETE /api/v1/users/:id"
}
},
"documentation": "https://empiraa.com/docs/api"
}
Errors: only the authentication errors and 429.
Get the organization#
GET /api/v1/organization
Returns your organization's profile, including its vision statement and the name of its GPS plan.
Scope: organization:read · Parameters: none.
curl https://plan.empiraa.app/api/v1/organization \
-H "X-API-Key: $GPS_API_KEY_ID" \
-H "X-API-Secret: $GPS_API_SECRET"
const res = await fetch('https://plan.empiraa.app/api/v1/organization', { headers });
const { data: org } = await res.json();
Response 200
| Field | Type | Notes |
|---|---|---|
id |
string | Organization ID. |
name |
string | Organization name. |
vision |
string or null | Vision statement. |
industry |
string or null | Industry. |
website |
string or null | Website URL. |
plan |
string or null | Name of the organization's GPS plan, or null if none is found. |
createdAt |
string | ISO 8601 timestamp. |
updatedAt |
string | ISO 8601 timestamp. |
{
"data": {
"id": "9b2f4e1a-6c3d-4e8f-a1b2-c3d4e5f6a7b8",
"name": "Northwind Advisory",
"vision": "Every client leaves with a plan they actually run.",
"industry": "Professional services",
"website": "https://northwind.example.com",
"plan": "Growth",
"createdAt": "2025-02-03T22:10:04.512Z",
"updatedAt": "2026-10-28T05:41:19.007Z"
}
}
Errors: 404 NOT_FOUND if the organization can't be found.
Update the organization#
PATCH /api/v1/organization
Updates one or more profile fields. Send at least one field.
Scope: organization:write
Request body
| Field | Type | Required | Allowed values | Notes |
|---|---|---|---|---|
name |
string | No | 1–200 characters after trimming | Organization name. |
vision |
string or null | No | Up to 5,000 characters | Vision statement. null clears it. |
industry |
string or null | No | Up to 200 characters | null clears it. |
website |
string or null | No | A valid URL, up to 500 characters | null clears it. |
curl -X PATCH https://plan.empiraa.app/api/v1/organization \
-H "X-API-Key: $GPS_API_KEY_ID" \
-H "X-API-Secret: $GPS_API_SECRET" \
-H "Content-Type: application/json" \
-d '{ "vision": "Every client leaves with a plan they actually run." }'
const res = await fetch('https://plan.empiraa.app/api/v1/organization', {
method: 'PATCH',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({ vision: 'Every client leaves with a plan they actually run.' }),
});
const { data: org } = await res.json();
Response 200: the same fields as Get the organization, without plan.
{
"data": {
"id": "9b2f4e1a-6c3d-4e8f-a1b2-c3d4e5f6a7b8",
"name": "Northwind Advisory",
"vision": "Every client leaves with a plan they actually run.",
"industry": "Professional services",
"website": "https://northwind.example.com",
"createdAt": "2025-02-03T22:10:04.512Z",
"updatedAt": "2026-11-12T03:20:11.940Z"
}
}
Errors
| Status | code |
When |
|---|---|---|
| 422 | VALIDATION_ERROR |
No fields sent, a value is too long, or website isn't a URL. |
| 404 | NOT_FOUND |
The organization can't be found. |

