API reference
API Reference
Welcome to the Okta Partners platform API reference. Once your app is approved and a tenant installs it, this API lets your app read and write Okta data — strictly within the scopes that tenant explicitly granted.
The runtime API is hosted by **okta-web** (the core platform app); every request hits the `/apps` path under the base URL. The partner platform (okta-partners) is where you register your app, pick scopes, and manage versions and webhooks.
The API is REST over HTTPS, exchanges JSON (UTF-8), and uses standard HTTP status codes. Every read and write is isolated per tenant and protected by a named scope.
Your first call
curl https://getokta.io/api/apps/whoami \
-H "Authorization: Bearer $OKTA_PARTNER_TOKEN" \
-H "Accept: application/json"
Base URL
The runtime API is hosted by okta-web under the following path:
https://getokta.io/api/apps
Sandbox environment:
https://dev.getokta.io/api/apps
Authentication
Every request authenticates with a per-installation **Bearer token**. The token is issued automatically when a tenant installs your app; it is bound to a (tenant, app) pair and carries the granted scopes.
Authorization: Bearer <installation_token>
- Never embed the token in front-end code or a public repo — store it as a server-side secret (e.g. `OKTA_PARTNER_TOKEN`).
- The token is rotatable from the partner dashboard; external apps receive the new token over the bridge without a redeploy.
- A missing or invalid token returns `401 Unauthorized`. A valid token lacking the required scope returns `403 Forbidden`.
Verify your token
curl https://getokta.io/api/apps/whoami \
-H "Authorization: Bearer $OKTA_PARTNER_TOKEN"
# → { "tenant_id": 42, "module": "your-app", "scopes": [ ... ] }
Scopes
Every piece of data is protected by a scope shaped `
| Scope | Description |
|---|---|
education.students.read |
Read students |
education.students.write |
Create / update students |
education.guardians.read |
Read guardians |
education.subjects.read |
Read subjects |
education.grades.read |
Read grades |
education.sections.read |
Read sections |
education.academic_years.read |
Read academic years |
education.terms.read |
Read terms |
employees.directory.read |
Read employee directory |
reports.builder.read |
Report catalog / run, list the school’s letterheads and print on them |
reports.builder.write |
Propose an app-authored letterhead (arrives as a draft) |
notifications.providers.send |
Send via a notification provider |
realtime.messages.write |
Publish an instant message to your app's surfaces (listening needs no scope) |
Endpoints
All paths are relative to the base URL above. Write endpoints (POST/PATCH) require the matching scope.
Identity
/whoami
no scope
Current installation info (tenant, app, scopes).
https://getokta.io/api/apps/whoami
Current installation info (tenant, app, scopes).
Students
/education/students
education.students.read
List students (paginated).
https://getokta.io/api/apps/education/students
List students (paginated).
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/education/students/{id}
education.students.read
A single student.
https://getokta.io/api/apps/education/students/{id}
A single student.
Path Params
The resource id in Okta.
/education/students
education.students.write
Create a student.
https://getokta.io/api/apps/education/students
Create a student.
Body Params
Student's full name.
National / residency id.
Birth date (YYYY-MM-DD).
male or female.
Grade id.
Section id.
Guardian id.
/education/students/{id}
education.students.write
Update a student.
https://getokta.io/api/apps/education/students/{id}
Update a student.
Path Params
The resource id in Okta.
Body Params
Student's full name.
National / residency id.
Birth date (YYYY-MM-DD).
male or female.
Grade id.
Section id.
Guardian id.
Guardians
/education/guardians
education.guardians.read
List guardians.
https://getokta.io/api/apps/education/guardians
List guardians.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/education/guardians/{id}
education.guardians.read
A single guardian.
https://getokta.io/api/apps/education/guardians/{id}
A single guardian.
Path Params
The resource id in Okta.
/education/guardians
education.guardians.write
Create a guardian.
https://getokta.io/api/apps/education/guardians
Create a guardian.
Body Params
Guardian's full name.
Phone in E.164 format.
Email address.
father | mother | other.
/education/guardians/{id}
education.guardians.write
Update a guardian.
https://getokta.io/api/apps/education/guardians/{id}
Update a guardian.
Path Params
The resource id in Okta.
Body Params
Guardian's full name.
Phone in E.164 format.
Email address.
father | mother | other.
Curriculum
/education/subjects
education.subjects.read
Subjects.
https://getokta.io/api/apps/education/subjects
Subjects.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/education/subjects
education.subjects.write
Create a subject (idempotent).
https://getokta.io/api/apps/education/subjects
Create a subject (idempotent).
Body Params
Subject name.
Subject code.
/education/grades
education.grades.read
Grades.
https://getokta.io/api/apps/education/grades
Grades.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/education/sections
education.sections.read
Sections.
https://getokta.io/api/apps/education/sections
Sections.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/education/academic-years
education.academic_years.read
Academic years.
https://getokta.io/api/apps/education/academic-years
Academic years.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/education/terms
education.terms.read
Terms.
https://getokta.io/api/apps/education/terms
Terms.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
Employees
/employees/directory
employees.directory.read
Employee directory.
https://getokta.io/api/apps/employees/directory
Employee directory.
Query Params
Page number (1-based).
Items per page (max 100).
Optional free-text search.
/employees/directory/{id}
employees.directory.read
A single employee.
https://getokta.io/api/apps/employees/directory/{id}
A single employee.
Path Params
The resource id in Okta.
/employees/directory
employees.directory.write
Add an employee (idempotent).
https://getokta.io/api/apps/employees/directory
Add an employee (idempotent).
Body Params
Employee's full name.
Job title.
Email address.
Reports
/reports/builder
reports.builder.read
Catalog of available reports.
https://getokta.io/api/apps/reports/builder
Catalog of available reports.
/reports/builder/{key}/run
reports.builder.read
Run a report (idempotent).
https://getokta.io/api/apps/reports/builder/{key}/run
Run a report (idempotent).
Path Params
Report key from the catalog.
Body Params
Report parameters (report-specific).
/reports/templates
reports.builder.read
The school’s approved letterheads.
https://getokta.io/api/apps/reports/templates
The school’s approved letterheads.
/reports/templates/{id}/render
reports.builder.read
Print your content on a letterhead — returns a PDF.
https://getokta.io/api/apps/reports/templates/{id}/render
Print your content on a letterhead — returns a PDF.
Path Params
The opaque template id exactly as the listing returned it — not a number.
Body Params
The document body — blocks: heading, text, table, info-row, divider, spacer, image. An unknown type is refused, not skipped.
Values for the template’s declared variables. An undeclared key is dropped; platform variables cannot be overwritten.
/reports/templates
reports.builder.write
Propose a template (arrives as a draft, idempotent).
https://getokta.io/api/apps/reports/templates
Propose a template (arrives as a draft, idempotent).
Body Params
Template name in Arabic.
Template name in English.
A description shown to whoever picks the template.
administrative | general.
portrait | landscape.
a4 | a3 | letter.
Show the header band.
Show the footer band.
Right header slot — text accepting {{variables}}.
Center header slot.
Left header slot.
Right footer slot.
Center footer slot.
Left footer slot.
Watermark text.
Watermark opacity (0–100).
Top margin in mm (0–40).
Right margin in mm (0–40).
Bottom margin in mm (0–40).
Left margin in mm (0–40).
Print the signature block at the foot.
Signature block columns (1–4).
Signature block title.
Signatories: title_ar (required), title_en, name, show_line. An empty array removes them all; omitting the key leaves them alone.
Template fields: key (required), label_ar (required), label_en, type (text|date|number|currency), required, default_value. A key shadowing a platform variable is dropped silently.
/reports/templates/{id}
reports.builder.write
Edit a template your app authored (revokes approval).
https://getokta.io/api/apps/reports/templates/{id}
Edit a template your app authored (revokes approval).
Path Params
The opaque template id exactly as the listing returned it — not a number.
Body Params
Template name in Arabic.
Template name in English.
A description shown to whoever picks the template.
administrative | general.
portrait | landscape.
a4 | a3 | letter.
Show the header band.
Show the footer band.
Right header slot — text accepting {{variables}}.
Center header slot.
Left header slot.
Right footer slot.
Center footer slot.
Left footer slot.
Watermark text.
Watermark opacity (0–100).
Top margin in mm (0–40).
Right margin in mm (0–40).
Bottom margin in mm (0–40).
Left margin in mm (0–40).
Print the signature block at the foot.
Signature block columns (1–4).
Signature block title.
Signatories: title_ar (required), title_en, name, show_line. An empty array removes them all; omitting the key leaves them alone.
Template fields: key (required), label_ar (required), label_en, type (text|date|number|currency), required, default_value. A key shadowing a platform variable is dropped silently.
/reports/templates/{id}
reports.builder.write
Delete a draft your app authored.
https://getokta.io/api/apps/reports/templates/{id}
Delete a draft your app authored.
Path Params
The opaque template id exactly as the listing returned it — not a number.
Notifications
/notifications/capabilities
notifications.providers.send
Notification channel capabilities.
https://getokta.io/api/apps/notifications/capabilities
Notification channel capabilities.
/notifications/send
notifications.providers.send
Send a message (idempotent).
https://getokta.io/api/apps/notifications/send
Send a message (idempotent).
Body Params
Recipient (phone or user id).
Message body.
Specific channel (optional).
Realtime
/realtime/publish
realtime.messages.write
Push an instant message to your app's own surfaces in this tenant (not idempotent).
https://getokta.io/api/apps/realtime/publish
Pushes a message to your app's channel in this tenant only. Listening needs no scope — the installation is the permission, and there is no `realtime.messages.read`.
Body Params
Your own event name — `^[a-z][a-z0-9_.:-]{0,63}$`. It never becomes the broadcast event name: that is the fixed `app.message`, and yours travels inside the payload.
The message payload, at most 8192 bytes of JSON. Anything needing data is read by the surface from the API with its usual scope.
The full, always-current list lives in the auto-generated OpenAPI 3.1 spec:/docs/openapi.json·/docs/postman_collection.json
Pagination
List endpoints are paginated. Use `?page=2&per_page=50` (max 100 per page).
{
"data": [ ... ],
"total": 1242,
"per_page": 20,
"current_page": 1,
"last_page": 63
}
Idempotency
Write operations (POST/PATCH) accept an optional header. The same key within 24 hours replays the same stored response — so if your side times out, retrying will not create a duplicate record.
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Errors
Errors are returned as a consistent JSON envelope with the appropriate HTTP status code.
{
"message": "The given scope is not granted for this installation.",
"error": "scope_not_granted",
"scope": "education.students.write"
}
| Status | Name | Description |
|---|---|---|
400 |
Bad Request | Malformed or missing request body. |
401 |
Unauthorized | Missing or invalid token. |
403 |
Forbidden | Valid token, but the required scope is not granted. |
404 |
Not Found | Resource not found within the tenant scope. |
409 |
Conflict | Idempotency conflict or inconsistent state. |
422 |
Unprocessable Entity | Field validation failed. |
429 |
Too Many Requests | Rate limit exceeded. |
5xx |
Server Error | Transient error — retry with backoff. |
Rate limits
Every response carries headers telling you the remaining budget. On exceed, you get `429` with `Retry-After` (seconds). Honor exponential backoff on retry.
| Header | Description |
|---|---|
X-RateLimit-Limit |
Ceiling for the window. |
X-RateLimit-Remaining |
Remaining in the current window. |
Retry-After |
Seconds until a new request is allowed (with 429). |
Webhooks
External apps receive platform events via signed webhooks. Each webhook is an HTTP POST with a JSON body, signed with HMAC-SHA256 over the envelope `
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "education.students.created",
"tenant_id": 42,
"created_at": "2026-04-26T10:30:15+03:00",
"data": { "student": { "id": 123, "full_name": "..." } }
}
| Header | Description |
|---|---|
X-Okta-Event |
Event name. |
X-Okta-Delivery-Id |
UUID stable across retries (for dedup). |
X-Okta-Timestamp |
Unix timestamp at signing. |
X-Okta-Signature |
HMAC-SHA256 signature (hex). |
Verify the signature
$expected = hash_hmac(
'sha256',
$request->header('X-Okta-Timestamp').'.'.$request->getContent(),
$YOUR_WEBHOOK_SECRET,
);
if (! hash_equals($expected, $request->header('X-Okta-Signature'))) {
return response('invalid signature', 401);
}
- Check `X-Okta-Timestamp` is within the last 5 minutes, and store `X-Okta-Delivery-Id` for at least 15 minutes to reject replays.
- Respond 2xx within 10 seconds. For long work, accept with 202 immediately and process asynchronously.
- Retry backoff: 30s → 2m → 10m → 1h → 6h, after which the delivery is marked failed and surfaces on the Webhook Deliveries page in the partner dashboard.
More resources
This reference is a practical summary. For the full picture (integration types, app lifecycle, the manifest, the policy scanner) see the developer guide.
- Full developer guide
- Raw markdown source
- llms.txt — AI-friendly site index
- Apply to become a partner