﻿---
name: data-permissions
description: >
  Instructs AI agents how to manage data permissions in Kyriba. Data permissions
  control which entities (bank accounts, companies, third parties, currencies)
  a specific API client or user can access. Used for tenant-level access control.
version: 1.0.0
scopes:
  - data-permission-scope
authors:
  - kyriba
tags:
  - kyriba
  - platform
  - data-permissions
  - api
---

> **Auth** — POST {AUTH_BASE_URL}/oauth/token · Basic base64(CLIENT_ID:CLIENT_SECRET) · no scope.
> Use token_type verbatim — do not hardcode `Bearer`. On 401: retry once with the other scheme (`token` vs `Bearer`). On 429: wait Kyriba-Customer-Rate-Limit-Reset.

# Kyriba API Skill: Data Permissions

---

## Required Kyriba Permission

```
data-permission-scope
```

This is a Kyriba access permission — not an OAuth scope parameter. Do NOT add `scope=` to the token request.

---

## What are Data Permissions?

Data permissions define which entities (accounts, companies, third parties, etc.) an API client or user profile is allowed to access. They work as allow-lists: only entities explicitly listed are accessible.

---

##  Non-Standard Base URL

```
https://api.demo.kyriba.com/api/core/data-permissions/v2
```

This API uses `/api/core/data-permissions/v2` - not the standard `/api/v1/...`.

---

##  Non-Standard Pagination

Use `limit`/`offset` - **not** `page.limit`/`page.offset`.

---

## Endpoints

`{ref}` accepts either `uuid` or `code`.

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/data-permissions` | List data permissions |
| `POST` | `/data-permissions` | Create a new data permission |
| `GET` | `/data-permissions/{ref}` | Get a specific permission |
| `PUT` | `/data-permissions/{ref}` | Update a permission (`If-Match` required) |
| `DELETE` | `/data-permissions/{ref}` | Delete a permission (`If-Match` required) |
| `GET` | `/data-permissions/{ref}/entities` | List entities in a permission |
| `POST` | `/data-permissions/{ref}/entities` | Add an entity to a permission |
| `DELETE` | `/data-permissions/{ref}/entities/{entityRef}` | Remove an entity |
| `GET` | `/data-permissions/documented-fields/entityType` | Get valid `entityType` values |

---

## Filterable & Sortable Fields

```
code, uuid, description, entityType, ownershipCompany.code, ownershipCompany.uuid
```

---

## `entityType` Values

>  The full list is returned by `GET /data-permissions/documented-fields/entityType`. Known real values from the sandbox:

| Value | What it restricts |
|---|---|
| `ACCESS_PROFILE` | Access profiles |
| `ACCOUNT` | Bank accounts |
| `COMPANY` | Companies |
| `COMPANY_GROUP` | Company groups |
| `CURRENCY` | Currencies |
| `FLOW_CODE` | Cash flow codes |
| `THIRDPARTY` | Third parties (note: no underscore) |
| `TRANSACTION_CODE` | Transaction codes |
| `USER_GROUP` | User groups |

---

## Example Requests

**List all data permissions:**
```
GET /data-permissions?limit=100&offset=0&sort=entityType,code
```

**Filter by entity type:**
```
GET /data-permissions?filter=entityType==COMPANY
```

**List response:**
```json
{
  "metadata": { "total": 29, "count": 29, "limit": 100, "offset": 0 },
  "results": [
    {
      "code": "COMPANY",
      "uuid": "...",
      "description": "Company",
      "entityType": "COMPANY",
      "ownershipCompany": { "code": "COMP_FR", "uuid": "..." }
    }
  ]
}
```

>  The list response does **NOT** include the `entities` array. To see which entities belong to a permission, call `GET /data-permissions/{ref}/entities`.

**Get entities for a permission:**
```
GET /data-permissions/COMPANY/entities
```
```json
{
  "results": [
    { "code": "COMP_FR", "uuid": "..." },
    { "code": "COMP_DE", "uuid": "..." }
  ]
}
```

**Add an entity to a permission:**
```http
POST /data-permissions/COMPANY/entities
Content-Type: application/json

{ "code": "COMP_ES" }
```

**Create a permission:**
```http
POST /data-permissions
Content-Type: application/json

{
  "code": "PERM_COMP_EU",
  "description": "EU companies only",
  "entityType": "COMPANY"
}
```

**Create response:** `{ "uuid": "..." }`

---

## Key Fields

| Field | Description |
|---|---|
| `code` | Unique permission code |
| `uuid` | System-generated identifier |
| `description` | Human-readable label. **Can be `null`**. |
| `entityType` | Entity type being restricted (see table above) |
| `ownershipCompany` | Company that owns this permission `{ "code": "...", "uuid": "..." }` |

---

## Critical Rules

1. `uuid` is auto-generated - do not include in POST body
2. **Add entities via `POST /data-permissions/{ref}/entities`** - not via PUT
3. `PUT` and `DELETE` require `If-Match` header (ETag from GET response) - missing it returns `428`
4. Entities are **not embedded** in the list response - use the `/entities` sub-resource
5. `entityType` is **immutable** after create - cannot be changed via PUT
6. Always call `GET /data-permissions/documented-fields/entityType` to get the complete real list of types

---

## Error Reference

| Status | Meaning |
|---|---|
| `201` | Created - returns `{ "uuid": "..." }` |
| `400` | Missing required fields |
| `403` | Required Kyriba permission not configured on your API client |
| `404` | Permission not found |
| `409` | Code already exists or entity already a member |
| `412` | `If-Match` version mismatch (concurrent edit) |
| `428` | `If-Match` header missing on PUT/DELETE |

---

## OpenAPI Spec & Postman Collection

- OpenAPI: `https://developer.kyriba.com/static/apis/data-permissions/data-permissions.yaml`
- Postman: `https://developer.kyriba.com/static/apis/data-permissions/data-permissions-postman-collection.json`