﻿---
name: third-parties
description: >
  Instructs AI agents how to create, read, update, and delete third parties
  in Kyriba. Third parties are suppliers, customers, and financial institutions
  used in payments, transactions, and supply chain finance.
version: 1.0.0
scopes:
  - third-party-scope
authors:
  - kyriba
tags:
  - kyriba
  - platform
  - third-parties
  - 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: Third Parties

---

## Required Kyriba Permission

```
third-party-scope
```

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

---

## Base Path

```
/v1/third-parties
```

---

## Endpoints

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/v1/third-parties` | List third parties |
| `POST` | `/v1/third-parties` | Create a new third party |
| `POST` | `/v1/third-parties/details` | Get full details for multiple third parties by refs |
| `GET` | `/v1/third-parties/{ref}` | Get a specific third party by uuid or code |
| `PUT` | `/v1/third-parties/{ref}` | Update a specific third party |
| `DELETE` | `/v1/third-parties/{ref}` | Delete a specific third party |

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

---

## Filterable & Sortable Fields

Use RSQL `filter` query parameter. Fields confirmed as filterable:

```
code, uuid, name, name2,
businessIdentifiers.otherIdentifierType,
businessIdentifiers.otherIdentifierValue,
address.country.code, address.country.uuid,
companyOwnership.code, companyOwnership.uuid,
creationDate, updateDate
```

>  `creditor` and `debtor` are **NOT filterable** via RSQL.
> To filter by creditor/debtor status, fetch all matching records and filter client-side.

**`activeStatus`** can be passed as either:
- A standalone query parameter: `?activeStatus=OPENED`
- Or an RSQL filter field: `?filter=activeStatus==OPENED`

**`activeStatus` values:** `OPENED`, `CLOSED`

---

## `thirdPartyType` Values

| Value | Description |
|---|---|
| `ORGANIZATION` | Legal entity, company, or institution (**default**) |
| `INDIVIDUAL` | Natural person |

> For `ORGANIZATION`: use `name` and `name2`.
> For `INDIVIDUAL`: use `firstName` and `lastName` (required). `name` and `name2` are ignored.

---

## Example Requests

**List all active third parties:**
```
GET /v1/third-parties?activeStatus=OPENED&page.limit=100&page.offset=0
```

**Filter by code prefix (active only):**
```
GET /v1/third-parties?activeStatus=OPENED&filter=code==SUPP*&sort=code&page.limit=100&page.offset=0
```

**Combined filter - active + name contains "Corp":**
```
GET /v1/third-parties?activeStatus=OPENED&filter=code==SUPP*;name==*Corp*
```

**Get multiple third parties by refs (bulk):**
```http
POST /v1/third-parties/details
Content-Type: application/json

{
  "refs": ["SUPPLIER_001", "a1b2c3d4-e5f6-7890-abcd-ef1234567890"]
}
```

**Bulk response (207 Multi-Status):**
```json
{
  "results": [
    {
      "details": {
        "code": "SUPPLIER_001",
        "name": "Acme Corp",
        "uuid": "a1b2c3d4-...",
        "thirdPartyType": "ORGANIZATION",
        "creditor": true,
        "debtor": false,
        "thirdPartyCategories": [{ "code": "SUPPLIER" }]
      }
    }
  ]
}
```

**Create an organization third party:**
```http
POST /v1/third-parties
Content-Type: application/json

{
  "code": "SUPPLIER_001",
  "thirdPartyType": "ORGANIZATION",
  "name": "Acme Corp",
  "creditor": true,
  "debtor": false,
  "address": {
    "country": { "code": "FR" }
  }
}
```

**Create an individual third party:**
```http
POST /v1/third-parties
Content-Type: application/json

{
  "code": "PERSON_001",
  "thirdPartyType": "INDIVIDUAL",
  "firstName": "Jean",
  "lastName": "Dupont",
  "creditor": false,
  "debtor": true,
  "address": {
    "country": { "code": "FR" }
  }
}
```

**Create response:**
```json
{ "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
```

---

## List Response Schema

The `GET /v1/third-parties` list response returns full records - no separate detail call needed:

```json
{
  "metadata": {
    "total": 10,
    "count": 3,
    "limit": 3,
    "offset": 0,
    "links": { "prev": "...", "current": "...", "next": "..." }
  },
  "results": [
    {
      "code": "SUPPLIER_001",
      "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "thirdPartyType": "ORGANIZATION",
      "name": "Acme Corp",
      "name2": "Acme",
      "hidden": false,
      "closureDate": null,
      "creditor": true,
      "debtor": false,
      "corpIDCode": "Corp.BB-FR1",
      "nonResident": false,
      "thirdPartyCategories": [{ "code": "SUPPLIER", "uuid": "..." }],
      "address": {
        "country": { "code": "FR", "uuid": "..." },
        "city": "Paris",
        "street1": "1 Rue de la Paix",
        "zipCode": "75001"
      }
    }
  ]
}
```

---

## Key Fields

| Field | Type | Description |
|---|---|---|
| `code` | string | Unique third party code |
| `uuid` | string | System-generated unique identifier |
| `thirdPartyType` | string | `ORGANIZATION` (default) or `INDIVIDUAL` |
| `name` | string | Organization name (ORGANIZATION only) |
| `name2` | string | Secondary name (ORGANIZATION only) |
| `firstName` | string | First name (INDIVIDUAL only, required) |
| `lastName` | string | Last name (INDIVIDUAL only, required) |
| `creditor` | boolean | Can receive payments. **Default: `true`** |
| `debtor` | boolean | Can make payments. **Default: `true`** |
| `thirdPartyCategories` | array | List of `{ "code": "..." }` category refs |
| `address.country` | object | `{ "code": "ISO2" }` - required on create |
| `corpIDCode` | string | Corporate ID code (max 14 chars) |
| `nonResident` | boolean | Non-resident for tax purposes. Default: `false` |
| `hidden` | boolean | Hide from all lists. Default: `false` |
| `closureDate` | date | Closure date (ISO format) |

---

## Critical Rules

1. `uuid` is auto-generated - do not pass it in `POST` body
2. `address.country` is required on create
3. `creditor` is **not** RSQL-filterable - filter client-side after fetching
4. Use `activeStatus` as a query param (not RSQL filter) for best compatibility
5. Use `POST /v1/third-parties/details` for bulk retrieval - returns `207` Multi-Status
6. For `INDIVIDUAL` type: `firstName` and `lastName` are required; `name` is ignored
7. Uniqueness is enforced on `code`

---

## Error Reference

| Status | Meaning |
|---|---|
| `201` | Third party created - returns `{ "uuid": "..." }` |
| `207` | Multi-status - bulk details response (check each result individually) |
| `400` | Bad request - missing required fields or invalid data |
| `401` | Authentication required or token expired |
| `403` | Required Kyriba permission not configured on your API client |
| `404` | Third party not found for given `{ref}` |
| `409` | Conflict - code already exists or third party in use |
| `415` | Wrong Content-Type (must be `application/json`) |

---

## OpenAPI Spec & Postman Collection

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