grafena. API
Programmatic access to your employees and schedules. Available on the Full plan.
Base URL
https://grafena.pl/api/v1
Response format
All responses are JSON. Successful responses wrap the result in a data field. Errors return an error string.
API keys are managed in Settings → API Keys inside the app. You need a Full plan to generate keys and use the API.
Authentication
Pass your API key as a Bearer token in the Authorization header on every request.
Authorization: Bearer grafena_your_key_here
API keys are shown once at creation and cannot be recovered. Store them securely. If lost, delete the key and generate a new one.
Errors
| Status | Meaning |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Missing or invalid API key |
| 403 | Plan limit reached or feature not available on your plan |
| 404 | Resource not found (or belongs to another account) |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
Error response shape
{ "error": "Employee not found" }Rate Limits
60 requests per minute per API key. The response includes standard RateLimit-* headers so you can track your usage.
Employees
GET
/api/v1/employees
List all employees
POST
/api/v1/employees
Create an employee
PUT
/api/v1/employees/:id
Update an employee
DELETE
/api/v1/employees/:id
Delete an employee
Employee object
| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier |
| name | string | Full name |
| maxHours | number | Monthly contracted hours |
| shiftType | string | day | night | both | short | custom ID |
| shortHours | string | For short shifts: 2h | 5h | 8h |
| unavailable | object | Map of "YYYY-M": [day, ...] |
| contract | string | uop (employment contract) | zlecenie (civil contract; labour-code checks are skipped) |
| createdAt | string | ISO 8601 timestamp |
POST /api/v1/employees — request body
{
"name": "Anna Kowalska", // required
"maxHours": 160, // optional, default 160
"shiftType": "day", // optional, default "day"
"shortHours": "5h", // optional, default "5h"
"contract": "uop" // optional, default "uop"; left unchanged by PUT when omitted
}Example response — GET /api/v1/employees
{
"data": [
{
"id": "clxyz123",
"name": "Anna Kowalska",
"maxHours": 160,
"shiftType": "day",
"shortHours": "5h",
"unavailable": {},
"contract": "uop",
"createdAt": "2026-01-15T10:00:00.000Z"
}
]
}Schedules
GET
/api/v1/schedules
List published schedules (metadata only). Schedules that were never published are left out.
GET
/api/v1/schedules/:id
Get the published version of a schedule with its full grid; 404 when it was never published. Unpublished edits are not included.
DELETE
/api/v1/schedules/:id
Delete a schedule
Schedule object (list)
| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier |
| name | string | Schedule name |
| year | number | Year |
| month | number | Month (1–12) |
| employeeCount | number | Number of employees in this schedule |
| createdAt | string | ISO 8601 timestamp |
Grid format — GET /api/v1/schedules/:id
The grid is a map of day → employeeId → cell. Each cell describes the shift assigned to that employee on that day.
{
"data": {
"id": "clxyz456",
"name": "Marzec 2026",
"year": 2026,
"month": 3,
"employeeCount": 12,
"grid": {
"1": {
"clxyz123": { "type": "day", "hours": 12, "label": "07:00–19:00", "start": "07:00" }
},
"2": {
"clxyz123": { "type": "off", "hours": 0, "label": "" }
}
},
"employees": [ ... ],
"createdAt": "2026-03-01T08:00:00.000Z"
}
}Cell types
| type | Meaning |
|---|---|
| day | Day shift |
| night | Night shift |
| both | Day or night shift |
| short | Short shift |
| off | Day off |
| rest | Legacy: a day off in schedules saved before October 2026. Treat it as off. |
| unavail | Employee unavailable (marked in advance) |
| custom_* | Custom shift type defined in settings |