Integration API
The Integration API lets server-side systems read and write a scoped slice of Research-ly on behalf of the administrator who issued the key. Keys are created by a super admin in the admin console; each key carries an explicit set of scopes and an optional expiry, and can be revoked at any time.
Send the key on every request as Authorization: Bearer <key> or x-api-key: <key>. Requests and responses are JSON.
curl -H "Authorization: Bearer rk_live_..." \ https://research-ly.com/api/v1/me
Scopes
| Scope | Grants |
|---|---|
| projects:read | Read project metadata and non-sensitive project summaries. |
| projects:write | Create or update project records through integration endpoints. |
| support:read | Read support ticket metadata allowed for integrations. |
| support:write | Create or update support tickets through integration endpoints. |
| notifications:write | Queue in-app notifications through integration endpoints. |
| analytics:read | Read high-level product analytics and usage summaries. |
Endpoints
| Method | Path | Scope | Summary |
|---|---|---|---|
| GET | /api/v1/me | any valid key | Confirm which key and owner account a credential resolves to. |
| GET | /api/v1/projects | projects:read | List the projects the key owner is an active collaborator on. |
| POST | /api/v1/projects | projects:write | Create a project owned by the key owner. |
| GET | /api/v1/projects/{projectRef} | projects:read | Read one project by id or slug; a project the key owner is not a member of is 404. |
| PATCH | /api/v1/projects/{projectRef} | projects:write | Update a project's title, description, study design, status, or slug. |
| GET | /api/v1/support/tickets | support:read | List the most recent support tickets opened by the key owner. |
| POST | /api/v1/support/tickets | support:write | Open a support ticket on behalf of the key owner. |
| GET | /api/v1/support/tickets/{ticketId} | support:read | Read one support ticket opened by the key owner. |
| POST | /api/v1/notifications | notifications:write | Queue an in-app notification for a user audience. |
| GET | /api/v1/analytics/summary | analytics:read | Read the aggregate product analytics summary. |
Request and response schemas for every endpoint are in the OpenAPI document.
Rate limits and headers
Limits are applied per key per minute. Analytics endpoints count against a separate, smaller bucket because they aggregate across the whole product. The default limits are 120 requests per minute (general) and 10 per minute (analytics); the OpenAPI document reports the values configured for this deployment.
| Header | Meaning |
|---|---|
| x-request-id | Correlation id for the request. |
| x-ratelimit-limit | Requests allowed per minute for this key and bucket. |
| x-ratelimit-remaining | Requests left in the current window. |
| x-ratelimit-reset | Unix time (seconds) when the window resets. |
| retry-after | On 429 only: seconds to wait before retrying. |
Response envelope and errors
Successful responses wrap the payload in data (plus meta for lists). Errors always use the same shape with a stable code.
{
"success": true,
"data": { "id": "clx...", "slug": "cohort-study", "title": "Cohort study", ... },
"meta": { "count": 1 }
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The request payload is invalid.",
"details": { "title": ["String must contain at least 3 character(s)"] }
}
}| Code | Status | When |
|---|---|---|
| AUTHENTICATION_REQUIRED | 401 | No key, or the key is invalid, expired, revoked, or its owner account is not active. |
| AUTHORIZATION_FAILED | 403 | The key does not include the endpoint's scope, or the owner lacks the underlying permission. |
| NOT_FOUND | 404 | The resource does not exist or is not visible to the key owner. |
| VALIDATION_ERROR | 422 | The body or query is invalid; details lists the field errors. |
| RATE_LIMITED | 429 | The per-key limit was exceeded; retry after Retry-After seconds. |
| INTERNAL_SERVER_ERROR | 500 | Unexpected failure; quote x-request-id when reporting it. |