﻿---
name: fraud-detection-spi
description: >
  Instructs AI agents how to implement the Kyriba Fraud Detection SPI
  (Service Provider Interface). This is an INBOUND interface - Kyriba calls
  YOUR service. Implement these endpoints to integrate an external fraud
  screening engine into Kyriba's payment approval workflow.
version: 1.0.0
scopes: []
authors:
  - kyriba
tags:
  - kyriba
  - payments
  - fraud-detection
  - spi
  - webhook
---

> **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: Fraud Detection SPI

>  **This is NOT a standard API.** This is an SPI (Service Provider Interface).
> **Kyriba calls YOUR service.** You implement the server endpoints; Kyriba is the client.

---

## What is the Fraud Detection SPI?

When a payment is submitted in Kyriba, Kyriba can call an external fraud screening service before approving it. You implement this service. Kyriba sends payment details and expects a `PASS`, `BLOCK`, or `REVIEW` decision back within the timeout window.

---

## Integration Architecture

```
Payment submitted in Kyriba
        ↓
Kyriba calls YOUR service -> POST /fraud-screening
        ↓
YOUR service responds     -> { "decision": "PASS|BLOCK|REVIEW" }
        ↓
Kyriba continues or blocks the payment
```

---

## Endpoints YOUR Service Must Expose

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/health` | Health check - Kyriba polls this to verify your service is up |
| `POST` | `/fraud-screening` | Fraud screening - Kyriba sends payment data and expects a decision |

---

## Health Check

**Request from Kyriba:**
```
GET /health
```

**Expected response (`200 OK`):**
```json
{ "status": "UP" }
```

> If health check fails, Kyriba will not route payments to your service.

---

## Fraud Screening Request (Kyriba -> Your Service)

```http
POST /fraud-screening
Content-Type: application/json
Authorization: Basic base64(clientId:clientSecret)

{
  "correlationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "paymentData": {
    "amount": 10000.00,
    "currency": { "code": "EUR" },
    "debtor": {
      "bankAccount": { "code": "BNP_PARIS_01" },
      "company": { "code": "COMP_FR" }
    },
    "creditor": {
      "thirdParty": { "code": "SUPPLIER_A" },
      "bankAccountNumber": "FR7630006000011234567890189"
    },
    "paymentDate": "2025-07-08",
    "reference": "PAY-2025-001"
  },
  "options": {
    "timeoutMs": 5000
  }
}
```

---

## Fraud Screening Response (Your Service -> Kyriba)

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "correlationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "decision": "PASS",
  "details": "No fraud indicators detected"
}
```

| `decision` | Effect in Kyriba |
|---|---|
| `PASS` | Payment proceeds normally |
| `BLOCK` | Payment is blocked |
| `REVIEW` | Payment is flagged for manual review |

---

## Critical Rules

1. **Echo back `correlationId`** - always return the same `correlationId` from the request
2. **Respond within the timeout** - Kyriba will timeout if no response within `options.timeoutMs` (default: 5000ms)
3. **Always return 200** - even for `BLOCK` decisions; use non-200 only for actual server errors
4. **Apply idempotency** - the same `correlationId` may be received more than once; return the same decision
5. **Implement `/health`** - without it Kyriba cannot verify your service is reachable
6. **Authentication** - Kyriba sends `Basic` auth in the request; validate it in your service

---

## Configuration in Kyriba

Register your SPI endpoint in the Kyriba UI under:
**Administration -> Connectivity -> Fraud Detection -> Service Provider**

Required configuration:
- Service URL (your base URL)
- Client ID / Client Secret (for Basic auth)
- Timeout (ms)
- Activation toggle per payment format or approval workflow

---

## Error Reference

| Your response | Effect |
|---|---|
| `200` + valid decision | Processed normally |
| `200` + missing `decision` | Treated as `PASS` (default) |
| `4xx` / `5xx` | Kyriba treats as service unavailable - fallback to `PASS` or `BLOCK` per configuration |
| Timeout | Fallback per configuration |

---

## OpenAPI Spec

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