# Open Mercato API

Version: 0.8.0

Auto-generated OpenAPI definition for all enabled modules.

## Servers
- https://makeitflow.90210.pl/api – Default environment

## GET `/agency_operations/cases`

List agency cases

Returns agency cases visible in the authenticated employee organization scope.

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated agency cases

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "customerEntityId": "00000000-0000-4000-8000-000000000000",
      "submittedByCustomerUserId": "00000000-0000-4000-8000-000000000000",
      "title": "string",
      "agentWorkerId": "string",
      "hasMaterial": true,
      "materialFileName": null,
      "materialMimeType": null,
      "materialFileSize": null,
      "workflowInstanceId": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_operations/cases?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agency_operations/cases/{id}`

Read persisted client submission processes for an employee case

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Latest 100 submissions with native execution and visible pending tasks

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "submissions": [
    {
      "submissionId": "string",
      "eventId": "string",
      "createdAt": "string",
      "original": {
        "eventId": "string",
        "scaffoldScenario": "clarify"
      },
      "workflow": null,
      "disposition": null,
      "interpretation": null,
      "briefRevisionHandoff": null,
      "strategyHandoff": null,
      "strategyExecution": null,
      "strategyReviewHandoff": null,
      "strategyPairContinuation": null,
      "planningExecution": null,
      "planningReviewHandoff": null,
      "postInstruction": null,
      "postExecution": null,
      "postReviewHandoff": null,
      "postRevision": null,
      "postRevisionHandoff": null,
      "materialRevision": null,
      "materialRevisionHandoff": null,
      "publicationPreparation": null,
      "tasks": [
        {
          "id": "string",
          "status": "string",
          "assignedTo": null,
          "assignedToRoles": [
            "string"
          ],
          "claimedBy": null
        }
      ]
    }
  ],
  "hasMore": true,
  "analysis": null
}
```

**400** – Invalid case id

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

**403** – Insufficient permissions

Content-Type: `application/json`

**404** – Case not found in scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_operations/cases/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agency_operations/cases/{id}/escalate`

Escalate a case to the native employee work inbox

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "reason": "string",
  "evidence": ""
}
```

### Responses

**200** – Existing open attention workflow reused

Content-Type: `application/json`

**201** – Native human attention workflow started

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "workflowInstanceId": "string",
  "deduplicated": true
}
```

**400** – Invalid request

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

**403** – Insufficient permissions

Content-Type: `application/json`

**404** – Case not found in scope

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/cases/string/escalate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"reason\": \"string\",
  \"evidence\": \"\"
}"
```

## GET `/agency_operations/cases/{id}/material`

Read material attached to an agency case

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Agency case material bytes

Content-Type: `application/json`

**400** – Invalid agency case id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Agency case or attachment scope is forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Agency case material not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Attachment partition is unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_operations/cases/00000000-0000-4000-8000-000000000000/material" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agency_operations/cases/{id}/publication-consent`

Request separate consent for an approved post at its current destination; no sending

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "postVersionId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "workflowInstanceId": "string",
  "taskId": "string",
  "replayed": true,
  "canSend": false
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "workflowInstanceId": "string",
  "taskId": "string",
  "replayed": true,
  "canSend": false
}
```

**400** – Invalid request

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Staff permissions required

Content-Type: `application/json`

**404** – Case outside scope

Content-Type: `application/json`

**409** – Current approved post and configured target required, or consent already valid

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/cases/string/publication-consent" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"postVersionId\": \"string\"
}"
```

## POST `/agency_operations/cases/{id}/publication-destination`

Save an explicit Discord destination without verifying access, granting consent or sending

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "nativeChannelId": "string",
  "discordChannelId": "string",
  "displayName": "string"
}
```

### Responses

**200** – Existing configuration or explicit unmet prerequisite

Content-Type: `application/json`

```json
{
  "status": "configured",
  "orderRef": "string",
  "configVersionId": "string",
  "target": {
    "configVersionId": "string",
    "platform": "string",
    "accountId": null,
    "channelId": null,
    "displayName": "string"
  },
  "readiness": "not_verified",
  "canSend": false,
  "replayed": true
}
```

**201** – Immutable destination configuration saved; sending remains disabled

Content-Type: `application/json`

```json
{
  "status": "configured",
  "orderRef": "string",
  "configVersionId": "string",
  "target": {
    "configVersionId": "string",
    "platform": "string",
    "accountId": null,
    "channelId": null,
    "displayName": "string"
  },
  "readiness": "not_verified",
  "canSend": false,
  "replayed": true
}
```

**400** – Invalid request

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient native permissions

Content-Type: `application/json`

**404** – Case or native channel outside scope

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/cases/string/publication-destination" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"nativeChannelId\": \"string\",
  \"discordChannelId\": \"string\",
  \"displayName\": \"string\"
}"
```

## GET `/agency_operations/cases/{id}/questions`

Read employee questions and native task state for an owned case

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Questions linked to visible employee tasks

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_operations/cases/string/questions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agency_operations/cases/{id}/questions`

Ask the customer without resolving the employee exception

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "parentTaskId": "string",
  "question": "string",
  "eventId": "string"
}
```

### Responses

**200** – Existing question returned

Content-Type: `application/json`

**201** – Native customer task created

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/cases/string/questions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"parentTaskId\": \"string\",
  \"question\": \"string\",
  \"eventId\": \"string\"
}"
```

## POST `/agency_operations/cases/{id}/resume-source-analysis`

Resume source analysis after a saved customer source correction

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "workflowInstanceId": "string"
}
```

### Responses

**200** – Source analysis resumed under its original configured policy

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "previousWorkflowInstanceId": null,
  "workflowInstanceId": "string",
  "status": "string",
  "currentStep": "string"
}
```

**400** – Invalid request

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient native permissions

Content-Type: `application/json`

**404** – Case outside scope

Content-Type: `application/json`

**409** – Source correction is absent, stale or no longer resumable

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/cases/string/resume-source-analysis" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"workflowInstanceId\": \"string\"
}"
```

## POST `/agency_operations/tov-discovery`

Discover candidate public sources for a paid agency case tone-of-voice intake

Staff-only. Runs the native agency_tov source scout and saves its case-scoped candidate targets. It does not collect a corpus, accept sources, start the specialist, or create a business spend approval; native runtime permissions and configured limits still govern execution.

**Tags:** Agency Operations

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "eventId": "string",
  "brand": "string",
  "people": [
    {
      "name": "string",
      "knownUrls": [
        "string"
      ]
    }
  ],
  "websiteUrl": null,
  "outputLanguage": "en"
}
```

### Responses

**200** – Saved discovery result or exact idempotent replay

Content-Type: `application/json`

```json
{
  "discoveryRunId": "string",
  "caseId": "string",
  "customerEntityId": "string",
  "runStatus": "running",
  "state": "running",
  "replayed": true,
  "brand": "string",
  "outputLanguage": "en",
  "minimumConfidence": 0.6,
  "notes": null,
  "targets": [
    {
      "source": "linkedin",
      "url": "string",
      "owner": "string",
      "material": "string",
      "confidence": 1,
      "evidenceUrl": "string",
      "targetId": "string",
      "collectorSupported": true,
      "meetsMinimumConfidence": true
    }
  ],
  "collectorAvailable": true,
  "collectorCandidateCount": 1,
  "handoff": {
    "state": "awaiting_staff_corpus",
    "corpusReady": false,
    "intakeStarted": false,
    "reason": "source_scout_returns_targets_not_normalized_corpus",
    "nextAction": "review_targets_collect_and_upload_normalized_corpus",
    "suppliedCorpusEndpoint": "/api/agency_operations/tov-intakes"
  }
}
```

**400** – Invalid discovery request

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient case, agent-run, web-search, or web-fetch permissions

Content-Type: `application/json`

**404** – Paid case not found in scope

Content-Type: `application/json`

**409** – Case is not backed by the canonical paid analysis workflow

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/tov-discovery" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"caseId\": \"string\",
  \"eventId\": \"string\",
  \"brand\": \"string\",
  \"people\": [
    {
      \"name\": \"string\",
      \"knownUrls\": [
        \"string\"
      ]
    }
  ],
  \"websiteUrl\": null,
  \"outputLanguage\": \"en\"
}"
```

## GET `/agency_operations/tov-discovery/{id}`

Read a saved case-scoped tone-of-voice source discovery result

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "discoveryRunId": "string",
  "caseId": "string",
  "customerEntityId": "string",
  "runStatus": "running",
  "state": "running",
  "replayed": true,
  "brand": "string",
  "outputLanguage": "en",
  "minimumConfidence": 0.6,
  "notes": null,
  "targets": [
    {
      "source": "linkedin",
      "url": "string",
      "owner": "string",
      "material": "string",
      "confidence": 1,
      "evidenceUrl": "string",
      "targetId": "string",
      "collectorSupported": true,
      "meetsMinimumConfidence": true
    }
  ],
  "collectorAvailable": true,
  "collectorCandidateCount": 1,
  "handoff": {
    "state": "awaiting_staff_corpus",
    "corpusReady": false,
    "intakeStarted": false,
    "reason": "source_scout_returns_targets_not_normalized_corpus",
    "nextAction": "review_targets_collect_and_upload_normalized_corpus",
    "suppliedCorpusEndpoint": "/api/agency_operations/tov-intakes"
  }
}
```

**400** – Invalid discovery run reference

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient staff permissions

Content-Type: `application/json`

**404** – Discovery run or paid case not found in scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_operations/tov-discovery/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agency_operations/tov-discovery/{id}/collect`

Collect explicitly selected source-scout targets into the existing ToV intake

Staff-only and disabled by default. Revalidates exact target IDs from the saved discovery run, uses the configured agency_tov corpus scraper with fixed limits, then hands normalized posts to the existing case-bound ToV intake.

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "eventId": "string",
  "targetIds": [
    "string"
  ]
}
```

### Responses

**200** – Saved collection handoff, replay, or actionable terminal result

Content-Type: `application/json`

```json
{
  "collectionId": "string",
  "discoveryRunId": "string",
  "caseId": "string",
  "customerEntityId": "string",
  "state": "running",
  "replayed": true,
  "selectedTargetIds": [
    "string"
  ],
  "postCount": 1,
  "reason": "collection_in_progress",
  "intake": null
}
```

**400** – Invalid discovery collection request

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient case, agent-run, or web-egress permissions

Content-Type: `application/json`

**404** – Discovery run or paid case not found in scope

Content-Type: `application/json`

**409** – Collection is disabled, unavailable, already unresolved, mismatched, or the intake already exists

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/tov-discovery/string/collect" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"caseId\": \"string\",
  \"eventId\": \"string\",
  \"targetIds\": [
    \"string\"
  ]
}"
```

## POST `/agency_operations/tov-intakes`

Start the configured native tone-of-voice specialist for a paid agency case

Staff-only. Pins a normalized public-post corpus to the existing paid case without replacing its original material or impersonating its customer.

**Tags:** Agency Operations

**Requires authentication.**

### Request Body

Content-Type: `multipart/form-data`

```text
caseId=string
eventId=string
brand=string
outputLanguage=en
file=string
```

### Responses

**200** – Existing idempotent intake returned

Content-Type: `application/json`

```json
{
  "intakeId": "string",
  "caseId": "string",
  "customerEntityId": "string",
  "workflowInstanceId": "string",
  "workflowStatus": "string",
  "currentStep": null,
  "state": "accepted",
  "replayed": true,
  "result": null
}
```

**202** – Native workflow accepted

Content-Type: `application/json`

```json
{
  "intakeId": "string",
  "caseId": "string",
  "customerEntityId": "string",
  "workflowInstanceId": "string",
  "workflowStatus": "string",
  "currentStep": null,
  "state": "accepted",
  "replayed": true,
  "result": null
}
```

**400** – Invalid normalized corpus or request

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient staff permissions

Content-Type: `application/json`

**404** – Paid case not found in scope

Content-Type: `application/json`

**409** – Paid case or native ToV workflow is not eligible/configured

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency_operations/tov-intakes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: multipart/form-data" \
  -d "{
  \"caseId\": \"string\",
  \"eventId\": \"string\",
  \"brand\": \"string\",
  \"outputLanguage\": \"en\",
  \"file\": \"string\"
}"
```

## GET `/agency_operations/tov-intakes/{id}`

Read the saved native tone-of-voice intake status and exact result references

**Tags:** Agency Operations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "intakeId": "string",
  "caseId": "string",
  "customerEntityId": "string",
  "workflowInstanceId": "string",
  "workflowStatus": "string",
  "currentStep": null,
  "state": "accepted",
  "replayed": true,
  "result": null
}
```

**400** – Invalid workflow reference

Content-Type: `application/json`

**401** – Staff authentication required

Content-Type: `application/json`

**403** – Insufficient staff permissions

Content-Type: `application/json`

**404** – Intake not found in scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_operations/tov-intakes/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agency_research/document-versions`

Read a research document version, or list the versions of a document

With `id`: the envelope, typed data, internal markdown and client projection of one version. With `order_ref` + `template_id`: the version list (envelopes only).

**Tags:** Agency Research

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| order_ref | query | any | Optional |
| template_id | query | any | Optional |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "id": "string",
  "document_id": "string",
  "template_id": "string",
  "schema_version": "string",
  "order_id": "string",
  "version": "string",
  "version_no": 1,
  "status": "string",
  "simulation_flag": true,
  "task_run_id": "string",
  "qa_result": null,
  "created_at": "string",
  "rendered_md": "string",
  "client_view_md": null
}
```

**400** – Invalid query

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

**403** – Organization scope required

Content-Type: `application/json`

**404** – Version not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/document-versions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agency_research/documents`

List the research documents of an order

One row per document template (WEW-ZRODLA, WEW-AUDYT, … KLI-BRIEF) with its current version reference, in the authenticated employee organization scope.

**Tags:** Agency Research

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| order_ref | query | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "orderRef": "string",
      "brand": "string",
      "templateId": "string",
      "outputId": "string",
      "status": "string",
      "currentVersionId": null,
      "currentVersionNo": null,
      "currentVersionStatus": null,
      "issues": 1,
      "hasClientView": true,
      "updatedAt": null
    }
  ],
  "total": 1
}
```

**400** – order_ref missing

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

**403** – Organization scope required

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/documents?order_ref=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agency_research/orders`

List the orders that have research documents or task runs

One row per order reference in the authenticated employee organization scope: document count, task runs, the last step and its status, spend and activity timestamps.

**Tags:** Agency Research

**Requires authentication.**

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "orderRef": "string",
      "brand": "string",
      "documents": 1,
      "taskRuns": 1,
      "lastStep": null,
      "lastStatus": null,
      "totalPln": 1,
      "firstRunAt": null,
      "lastActivityAt": null
    }
  ],
  "total": 1
}
```

**401** – Authentication required

Content-Type: `application/json`

**403** – Organization scope required

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/orders" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agency_research/portal/brief`

Read the current brief of the signed-in customer's order

The client projection of KLI-BRIEF (≤ 700 words) and the questions of the first contact (≤ 8). No internal data.

**Tags:** Agency Research

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| order_ref | query | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "order_ref": "string",
  "version": "string",
  "status": "string",
  "client_view_md": null,
  "questions": [
    {
      "question_id": "string",
      "question": "string",
      "hint": "string",
      "reason": "string",
      "brief_field": "string",
      "priority": "string"
    }
  ]
}
```

**400** – order_ref missing

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Customer account not linked or order not owned

Content-Type: `application/json`

**404** – Brief not ready

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/portal/brief?order_ref=string" \
  -H "Accept: application/json"
```

## GET `/agency_research/portal/documents`

Read the client documents of the signed-in customer's order

The client projection of the current KLI-STRATEGIA / KLI-TOV / KLI-PLAN / KLI-POST / KLI-PAKIET (`output`), or the list of the order's client documents with status and version. No internal data; `simulation` says the document was built on inputs the customer has not approved yet.

**Tags:** Agency Research

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| order_ref | query | any | Required |
| output | query | any | Optional |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "order_ref": "string",
  "output_id": "string",
  "version": "string",
  "status": "string",
  "simulation": true,
  "client_view_md": null
}
```

**400** – order_ref missing or output unknown

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Customer account not linked or order not owned

Content-Type: `application/json`

**404** – Document not ready

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/portal/documents?order_ref=string" \
  -H "Accept: application/json"
```

## GET `/agency_research/portal/progress`

Progress of the research and production steps of the customer's own case

Native customer session required; ownership through the spine's case query. Step ids, attempts, verdicts, timestamps and agent ids with outcomes only — no prompts, outputs, evidence or costs.

**Tags:** Agency Research

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| order_ref | query | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "order_ref": "string",
  "runs": [
    {
      "step_id": "string",
      "attempt": 1,
      "status": "string",
      "runner": "string",
      "verdict": null,
      "started_at": "string",
      "finished_at": null,
      "agents": [
        {
          "agent_id": "string",
          "status": "string"
        }
      ]
    }
  ]
}
```

**400** – order_ref is not a case id

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Customer account not linked

Content-Type: `application/json`

**404** – Case not found in the customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/portal/progress?order_ref=string" \
  -H "Accept: application/json"
```

## GET `/agency_research/task-runs`

Read the process state and spend of an order

**Tags:** Agency Research

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| order_ref | query | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "orderRef": "string",
  "totalPln": 1,
  "sources": 1,
  "documents": [
    {
      "templateId": "string",
      "outputId": "string",
      "status": "string",
      "versionNo": null,
      "versionId": null,
      "updatedAt": null
    }
  ],
  "taskRuns": [
    {
      "id": "string",
      "stepId": "string",
      "attempt": 1,
      "status": "string",
      "runner": "string",
      "costPln": 1,
      "qaResult": null,
      "agentRuns": 1,
      "outputVersionId": null,
      "error": null,
      "createdAt": "string",
      "finishedAt": null
    }
  ],
  "agentRuns": [
    {
      "id": "string",
      "agentId": "string",
      "stepId": null,
      "status": "string",
      "model": null,
      "inputTokens": null,
      "outputTokens": null,
      "costMinor": null,
      "createdAt": "string",
      "completedAt": null
    }
  ]
}
```

**400** – order_ref missing

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

**403** – Organization scope required

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency_research/task-runs?order_ref=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agency/cases/{id}/requests`

Receive one version-bound brief response through shared client intake

Records the original client request; never directly approves a brief. Requires an actual native invitation for this contact and current version. Stable externalEventId replays return the stored receipt.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "channel": "portal",
  "kind": "approval",
  "documentId": "string",
  "versionId": "string",
  "externalEventId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**400** – Invalid response

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Portal task completion permission required

Content-Type: `application/json`

**404** – Case, version or invitation not owned

Content-Type: `application/json`

**409** – Stale, unavailable, conflicting or incomplete response continuation

Content-Type: `application/json`

**413** – Request exceeds 100 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/cases/string/requests" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"channel\": \"portal\",
  \"kind\": \"approval\",
  \"documentId\": \"string\",
  \"versionId\": \"string\",
  \"externalEventId\": \"string\"
}"
```

## GET `/agency/plan-reviews/{id}`

Read the exact invited plan, topics and recommendation

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "ok": true,
  "review": {
    "caseId": "string",
    "plan": {
      "caseId": "string",
      "documentId": "string",
      "versionId": "string",
      "version": "string",
      "templateId": "WZR-BRIEF",
      "title": "string",
      "html": "string",
      "status": "ready_for_review",
      "isCurrent": true,
      "mode": "content"
    },
    "topics": [
      {
        "topicId": "string",
        "title": "string",
        "recommended": true
      }
    ],
    "recommendedTopicId": "string"
  },
  "canRespond": true
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Review task or plan not visible to this customer

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/plan-reviews/string" \
  -H "Accept: application/json"
```

## POST `/agency/plan-reviews/{id}`

Receive an original plan response through shared intake; not document acceptance

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "channel": "portal",
  "kind": "approval",
  "plan": {
    "documentId": "string",
    "versionId": "string"
  },
  "externalEventId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**400** – Invalid plan response

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Review task or plan not visible to this customer

Content-Type: `application/json`

**409** – Stale plan, invalid topic or QA or response conflict

Content-Type: `application/json`

**413** – Request exceeds 100 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/plan-reviews/string" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"channel\": \"portal\",
  \"kind\": \"approval\",
  \"plan\": {
    \"documentId\": \"string\",
    \"versionId\": \"string\"
  },
  \"externalEventId\": \"string\"
}"
```

## GET `/agency/portal/cases`

List cases owned by the signed-in customer

Native customer session required. Customer, tenant and organization scope come only from the session and current account linkage. Newest first; workflow is the current native status, or null if no scoped run is available. Internal context, traces and errors are never returned.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "caseId": "string",
      "title": "string",
      "materialFileName": "string",
      "materialMimeType": "string",
      "materialFileSize": 1,
      "createdAt": "string",
      "updatedAt": null,
      "workflow": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Invalid pagination

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer account

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases?page=1&pageSize=20" \
  -H "Accept: application/json"
```

## GET `/agency/portal/cases/{id}`

Read a case owned by the signed-in customer

Native customer session required. A nonexistent case and another customer’s, tenant’s or organization’s case both return 404. Workflow is a safe native status projection; no employee-only data is exposed.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "title": "string",
  "materialFileName": "string",
  "materialMimeType": "string",
  "materialFileSize": 1,
  "createdAt": "string",
  "updatedAt": null,
  "workflow": null
}
```

**400** – Invalid case id

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer account

Content-Type: `application/json`

**404** – Case not found in the customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases/string" \
  -H "Accept: application/json"
```

## GET `/agency/portal/cases/{id}/artifacts`

List exact client-facing ToV versions linked to an owned case

Native customer session required. Empty items means no linked KLI-TOV version is available; it does not imply completion. Internal per-author evidence documents are excluded. No review invitation, current-version or approval state is inferred.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "caseId": "string",
      "documentId": "string",
      "versionId": "string",
      "versionNo": 1,
      "kind": "KLI-TOV",
      "title": "string",
      "createdAt": "string"
    }
  ]
}
```

**400** – Invalid case id

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer account

Content-Type: `application/json`

**404** – Case not found in customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases/string/artifacts" \
  -H "Accept: application/json"
```

## GET `/agency/portal/cases/{id}/artifacts/{versionId}`

Read a case-linked KLI-TOV version as client-safe structured content

Requires an owned case and its exact persisted workflow result reference. Returns an allowlisted JSON projection, not raw research, Markdown or HTML. Treat strings as untrusted text. This is not the agencyReview task/approval envelope; provider traces, corpus, citations and QA payloads are excluded.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| versionId | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "documentId": "string",
  "versionId": "string",
  "versionNo": 1,
  "kind": "KLI-TOV",
  "title": "string",
  "createdAt": "string",
  "contentFormat": "tov-brand-json",
  "content": {
    "brand": "string",
    "summary": "string",
    "positioning": "string",
    "personality": "string",
    "voicePillars": [
      {
        "name": "string",
        "description": "string",
        "doThis": "string",
        "notThat": "string"
      }
    ],
    "sharedTraits": [
      "string"
    ],
    "tensions": [
      "string"
    ],
    "register": {
      "formality": 1,
      "warmth": 1,
      "confidence": 1,
      "humor": 1,
      "technicality": 1,
      "summary": "string"
    },
    "addressingTheReader": "string",
    "emotions": "string",
    "boundaries": [
      "string"
    ],
    "languagePolicy": "string",
    "vocabulary": {
      "signaturePhrases": [
        "string"
      ],
      "favouredWords": [
        "string"
      ],
      "avoided": [
        "string"
      ],
      "jargonLevel": "string"
    },
    "postFormats": [
      {
        "name": "string",
        "whenToUse": "string",
        "skeleton": "string"
      }
    ],
    "closers": {
      "patterns": [
        "string"
      ],
      "ctaStyle": "string"
    },
    "formatting": {
      "emoji": "string",
      "hashtags": "string",
      "mentions": "string",
      "links": "string",
      "capsAndPunctuation": "string"
    },
    "doList": [
      "string"
    ],
    "dontList": [
      "string"
    ],
    "counterExamples": [
      {
        "rule": "string",
        "wrong": "string",
        "right": "string"
      }
    ],
    "hooks": {
      "patterns": [
        "string"
      ]
    },
    "personaVariants": [
      {
        "displayName": "string",
        "howTheyDiffer": "string",
        "whenToWriteAsThem": "string"
      }
    ]
  }
}
```

**400** – Invalid case or version id

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer account

Content-Type: `application/json`

**404** – Case or client-facing version not found in this case scope

Content-Type: `application/json`

**409** – Stored version cannot be projected to supported client content

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases/string/artifacts/string" \
  -H "Accept: application/json"
```

## GET `/agency/portal/cases/{id}/submissions`

Read the latest 100 submissions for a customer-owned case

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "submissionId": "string",
      "caseId": "string",
      "eventId": "string",
      "channel": "portal",
      "submittedByCustomerUserId": "string",
      "createdAt": "string",
      "original": {
        "eventId": "string",
        "scaffoldScenario": "clarify"
      },
      "workflow": null,
      "disposition": null
    }
  ]
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer

Content-Type: `application/json`

**404** – Case not found in customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases/string/submissions" \
  -H "Accept: application/json"
```

## POST `/agency/portal/cases/{id}/submissions`

Save immutable client input for the configured native triage process

Native customer session required. Retrying eventId within the same case returns the stored original and disposition without running again. Missing native configuration leaves the original saved and waiting, never interpreted by a deterministic fallback. Only this case material may be referenced; a documentVersionReference is an unverified caller reference, not approval. Clarification waits for a native client reply signal; the reply endpoint is a separate capability.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "eventId": "string",
  "scaffoldScenario": "clarify"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "item": {
    "submissionId": "string",
    "caseId": "string",
    "eventId": "string",
    "channel": "portal",
    "submittedByCustomerUserId": "string",
    "createdAt": "string",
    "original": {
      "eventId": "string",
      "scaffoldScenario": "clarify"
    },
    "workflow": null,
    "disposition": null
  },
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "item": {
    "submissionId": "string",
    "caseId": "string",
    "eventId": "string",
    "channel": "portal",
    "submittedByCustomerUserId": "string",
    "createdAt": "string",
    "original": {
      "eventId": "string",
      "scaffoldScenario": "clarify"
    },
    "workflow": null,
    "disposition": null
  },
  "replayed": true
}
```

**400** – Invalid submission

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer

Content-Type: `application/json`

**404** – Case or material not found in customer scope

Content-Type: `application/json`

**413** – Request exceeds 100 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/cases/string/submissions" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"eventId\": \"string\",
  \"scaffoldScenario\": \"clarify\"
}"
```

## GET `/agency/portal/cases/{id}/submissions/{submissionId}/replies`

Read accepted clarification replies for a customer-owned submission

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| submissionId | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "replyId": "string",
      "caseId": "string",
      "submissionId": "string",
      "channel": "portal",
      "submittedByCustomerUserId": "string",
      "createdAt": "string",
      "original": {
        "eventId": "string",
        "text": "string"
      },
      "outcome": "clarification_received"
    }
  ]
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer

Content-Type: `application/json`

**404** – Case or submission not found in customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases/string/submissions/string/replies" \
  -H "Accept: application/json"
```

## POST `/agency/portal/cases/{id}/submissions/{submissionId}/replies`

Reply to the fixed clarification request on a customer-owned submission

Accepts only eventId and original reply text. Server derives the native wait and signal from the owned submission. Replaying eventId returns the accepted reply without signaling again; a new event against a no-longer-waiting request returns 409. No artifact approval, reclassification, or employee task is created. Follow current status through the submission API.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| submissionId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "eventId": "string",
  "text": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "item": {
    "replyId": "string",
    "caseId": "string",
    "submissionId": "string",
    "channel": "portal",
    "submittedByCustomerUserId": "string",
    "createdAt": "string",
    "original": {
      "eventId": "string",
      "text": "string"
    },
    "outcome": "clarification_received"
  },
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "item": {
    "replyId": "string",
    "caseId": "string",
    "submissionId": "string",
    "channel": "portal",
    "submittedByCustomerUserId": "string",
    "createdAt": "string",
    "original": {
      "eventId": "string",
      "text": "string"
    },
    "outcome": "clarification_received"
  },
  "replayed": true
}
```

**400** – Invalid reply

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer

Content-Type: `application/json`

**404** – Case or submission not found in customer scope

Content-Type: `application/json`

**409** – Submission is not waiting for this clarification

Content-Type: `application/json`

**413** – Request exceeds 100 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/cases/string/submissions/string/replies" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"eventId\": \"string\",
  \"text\": \"string\"
}"
```

## GET `/agency/portal/cases/{id}/tasks`

Read visible open customer tasks bound to this agency case

Uses native customer task visibility. No tasks means no open customer task, not that the case is complete. Task pages retain decision authority.

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "state": "customer_tasks",
  "tasks": [
    {
      "id": "string",
      "title": "string",
      "status": "PENDING",
      "assignedToYou": true
    }
  ]
}
```

**400** – Invalid case id

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Task visibility feature or active company link required

Content-Type: `application/json`

**404** – Case not found in customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/cases/string/tasks" \
  -H "Accept: application/json"
```

## POST `/agency/portal/materials`

Save supplementary material to an existing customer-owned case

Preserves the original purchase receipt. Saves a native private attachment and immutable client submission, then dispatches to native triage when configured. Does not start research or create another case.

**Tags:** Agency

### Request Body

Content-Type: `multipart/form-data`

```text
caseId=string
eventId=string
file=string
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "attachmentId": "string",
  "submissionId": "string",
  "replayed": true,
  "state": "submitted_to_native_triage"
}
```

**202** – Response

Content-Type: `application/json`

```json
{
  "caseId": "string",
  "attachmentId": "string",
  "submissionId": "string",
  "replayed": true,
  "state": "submitted_to_native_triage"
}
```

**400** – Invalid case, event or material

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Inactive or unlinked customer

Content-Type: `application/json`

**404** – Case not owned by this customer

Content-Type: `application/json`

**413** – Attachment upload limit exceeded

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/materials" \
  -H "Accept: application/json" \
  -H "Content-Type: multipart/form-data" \
  -d "{
  \"caseId\": \"string\",
  \"eventId\": \"string\",
  \"file\": \"string\"
}"
```

## POST `/agency/portal/onboarding`

Link a verified new customer to their own new demo company

**Tags:** Agency

### Request Body

Content-Type: `application/json`

```json
{
  "brandDisplayName": "string",
  "brandWebsiteUrl": "string",
  "billingLegalName": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "customerEntityId": "string",
  "replayed": true
}
```

**400** – Invalid company inputs

Content-Type: `application/json`

**401** – Customer session required

Content-Type: `application/json`

**403** – Verified active account required

Content-Type: `application/json`

**409** – Demo onboarding unavailable

Content-Type: `application/json`

**413** – Request exceeds 20 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/onboarding" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"brandDisplayName\": \"string\",
  \"brandWebsiteUrl\": \"string\",
  \"billingLegalName\": \"string\"
}"
```

## GET `/agency/portal/purchases`

Read the server-owned demo offer and versioned terms

**Tags:** Agency

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "enabled": true,
  "demoOnly": true,
  "sku": "string",
  "name": "string",
  "amount": 1,
  "currency": "string",
  "offerVersion": "string",
  "termsVersion": "string",
  "terms": {
    "en": "string",
    "pl": "string"
  },
  "provider": "string"
}
```

**401** – Customer session required

Content-Type: `application/json`

**403** – Verified active customer required

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/purchases" \
  -H "Accept: application/json"
```

## POST `/agency/portal/purchases`

Start a zero-charge native demo order and test payment

**Tags:** Agency

### Request Body

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "offerVersion": "string",
  "termsVersion": "string",
  "acceptedTerms": true,
  "buyer": {
    "brandDisplayName": "string",
    "brandWebsiteUrl": "string",
    "market": "string",
    "language": "string",
    "contactName": "string",
    "contactEmail": "string",
    "billingBuyerType": "company",
    "billingLegalName": "string",
    "billingCountry": "string",
    "billingAddress": "string",
    "billingTaxId": "string",
    "officialSocialUrl": "string",
    "purchaseGoal": "string"
  }
}
```

### Responses

**201** – Response

Content-Type: `application/json`

```json
{
  "orderId": "string",
  "paymentId": "string",
  "providerSessionId": null,
  "status": "pending_payment",
  "caseId": null,
  "workflowInstanceId": null
}
```

**400** – Invalid purchase input

Content-Type: `application/json`

**401** – Customer session required

Content-Type: `application/json`

**403** – Linked active customer required or demo disabled

Content-Type: `application/json`

**409** – Offer or request conflict

Content-Type: `application/json`

**413** – Request exceeds 20 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/purchases" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"requestId\": \"string\",
  \"offerVersion\": \"string\",
  \"termsVersion\": \"string\",
  \"acceptedTerms\": true,
  \"buyer\": {
    \"brandDisplayName\": \"string\",
    \"brandWebsiteUrl\": \"string\",
    \"market\": \"string\",
    \"language\": \"string\",
    \"contactName\": \"string\",
    \"contactEmail\": \"string\",
    \"billingBuyerType\": \"company\",
    \"billingLegalName\": \"string\",
    \"billingCountry\": \"string\",
    \"billingAddress\": \"string\",
    \"billingTaxId\": \"string\",
    \"officialSocialUrl\": \"string\",
    \"purchaseGoal\": \"string\"
  }
}"
```

## GET `/agency/portal/purchases/{id}`

Read authoritative status of this customer-owned demo purchase

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "orderId": "string",
  "paymentId": "string",
  "providerSessionId": null,
  "status": "pending_payment",
  "caseId": null,
  "workflowInstanceId": null
}
```

**400** – Invalid order identifier

Content-Type: `application/json`

**401** – Customer session required

Content-Type: `application/json`

**403** – Linked active customer required

Content-Type: `application/json`

**404** – Purchase not found in customer scope

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/purchases/string" \
  -H "Accept: application/json"
```

## POST `/agency/portal/purchases/{id}/confirm`

Confirm or retry this customer-owned zero-charge test payment

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "orderId": "string",
  "paymentId": "string",
  "providerSessionId": null,
  "status": "pending_payment",
  "caseId": null,
  "workflowInstanceId": null
}
```

**400** – Invalid order identifier or confirmation payload

Content-Type: `application/json`

**401** – Customer session required

Content-Type: `application/json`

**403** – Linked active customer required or demo disabled

Content-Type: `application/json`

**404** – Purchase not found in customer scope

Content-Type: `application/json`

**409** – Payment cannot be confirmed

Content-Type: `application/json`

**413** – Request exceeds 20 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/purchases/string/confirm" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/agency/portal/purchases/{id}/retry`

Retry one failed zero-charge payment without creating another order

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "providerSessionId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "orderId": "string",
  "paymentId": "string",
  "providerSessionId": null,
  "status": "pending_payment",
  "caseId": null,
  "workflowInstanceId": null
}
```

**400** – Invalid failed session reference

Content-Type: `application/json`

**401** – Customer session required

Content-Type: `application/json`

**403** – Linked active customer required or demo disabled

Content-Type: `application/json`

**404** – Purchase not found in customer scope

Content-Type: `application/json`

**409** – Payment is not eligible for retry

Content-Type: `application/json`

**413** – Request exceeds 20 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/purchases/string/retry" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"providerSessionId\": \"string\"
}"
```

## GET `/agency/portal/questions`

Read this customer account’s saved fixed-offer questions and answers

**Tags:** Agency

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "eventId": "string",
      "question": "string",
      "createdAt": "string",
      "previousQuestionId": null,
      "catalogVersionId": "string",
      "productId": "string",
      "state": "waiting_configuration",
      "answer": null
    }
  ],
  "offer": {
    "versionId": "string",
    "productId": "string",
    "content": "string"
  }
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Verified active customer required

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/portal/questions" \
  -H "Accept: application/json"
```

## POST `/agency/portal/questions`

Save an original pre-purchase question, or resume its idempotent configured answer

**Tags:** Agency

### Request Body

Content-Type: `application/json`

```json
{
  "eventId": "string",
  "question": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "item": {
    "id": "string",
    "eventId": "string",
    "question": "string",
    "createdAt": "string",
    "previousQuestionId": null,
    "catalogVersionId": "string",
    "productId": "string",
    "state": "waiting_configuration",
    "answer": null
  },
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "item": {
    "id": "string",
    "eventId": "string",
    "question": "string",
    "createdAt": "string",
    "previousQuestionId": null,
    "catalogVersionId": "string",
    "productId": "string",
    "state": "waiting_configuration",
    "answer": null
  },
  "replayed": true
}
```

**400** – Invalid question

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Verified active customer required

Content-Type: `application/json`

**404** – Follow-up question not found

Content-Type: `application/json`

**413** – Question request exceeds 20 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/portal/questions" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"eventId\": \"string\",
  \"question\": \"string\"
}"
```

## GET `/agency/post-reviews/{id}`

Read the exact invited post content

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "ok": true,
  "review": {
    "caseId": "string",
    "post": {
      "caseId": "string",
      "documentId": "string",
      "versionId": "string",
      "version": "string",
      "templateId": "WZR-BRIEF",
      "title": "string",
      "html": "string",
      "status": "ready_for_review",
      "isCurrent": true,
      "mode": "content"
    }
  },
  "canRespond": true
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Review task or post not visible to this customer

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/post-reviews/string" \
  -H "Accept: application/json"
```

## POST `/agency/post-reviews/{id}`

Receive an original content response through shared intake; not document acceptance

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "channel": "portal",
  "kind": "approval",
  "post": {
    "documentId": "string",
    "versionId": "string"
  },
  "externalEventId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**400** – Invalid post response

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Review task or post not visible to this customer

Content-Type: `application/json`

**409** – Stale post or invalid QA or response conflict

Content-Type: `application/json`

**413** – Request exceeds 100 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/post-reviews/string" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"channel\": \"portal\",
  \"kind\": \"approval\",
  \"post\": {
    \"documentId\": \"string\",
    \"versionId\": \"string\"
  },
  \"externalEventId\": \"string\"
}"
```

## GET `/agency/publication-consents/{id}`

Read the immutable approved post and exact requested publication destination

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "ok": true,
  "request": {
    "caseId": "string",
    "documentId": "string",
    "postVersionId": "string",
    "version": "string",
    "contentHash": "string",
    "clientViewMd": "string",
    "acceptedAt": "string",
    "target": {
      "configVersionId": "string",
      "platform": "string",
      "accountId": null,
      "channelId": null,
      "displayName": "string"
    }
  },
  "canRespond": true,
  "canSend": false,
  "consentedAt": null
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Consent task not visible to this customer

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/publication-consents/string" \
  -H "Accept: application/json"
```

## POST `/agency/publication-consents/{id}`

Record explicit separate publication consent without content reapproval or sending

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "postVersionId": "string",
  "configVersionId": "string",
  "consent": true,
  "externalEventId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "taskId": "string",
  "status": "consent_recorded",
  "consentedAt": "string",
  "replayed": true,
  "preparation": {
    "status": "prepared",
    "orderRef": "string",
    "postVersionId": "string",
    "acceptanceSubmissionId": "string",
    "taskRunId": "string",
    "instructionVersionId": "string",
    "configVersionId": "string",
    "contentHash": "string",
    "contentApproval": "valid",
    "publicationConsent": "missing",
    "canSend": false,
    "missingGates": [
      "string"
    ],
    "replayed": true
  },
  "canSend": false
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "taskId": "string",
  "status": "consent_recorded",
  "consentedAt": "string",
  "replayed": true,
  "preparation": {
    "status": "prepared",
    "orderRef": "string",
    "postVersionId": "string",
    "acceptanceSubmissionId": "string",
    "taskRunId": "string",
    "instructionVersionId": "string",
    "configVersionId": "string",
    "contentHash": "string",
    "contentApproval": "valid",
    "publicationConsent": "missing",
    "canSend": false,
    "missingGates": [
      "string"
    ],
    "replayed": true
  },
  "canSend": false
}
```

**400** – Invalid consent response

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Consent task not visible to this customer

Content-Type: `application/json`

**409** – Changed post, destination, approval or original response

Content-Type: `application/json`

**413** – Request exceeds 10 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/publication-consents/string" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"postVersionId\": \"string\",
  \"configVersionId\": \"string\",
  \"consent\": true,
  \"externalEventId\": \"string\"
}"
```

## GET `/agency/reviews/{id}`

Read the client-safe exact brief snapshot for an owned native review task

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "ok": true,
  "review": {
    "caseId": "string",
    "documentId": "string",
    "versionId": "string",
    "version": "string",
    "templateId": "WZR-BRIEF",
    "title": "string",
    "html": "string",
    "status": "ready_for_review",
    "isCurrent": true,
    "mode": "content"
  },
  "canRespond": true
}
```

**400** – Invalid task id

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Portal task view permission required

Content-Type: `application/json`

**404** – Review task not visible to this customer

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/reviews/string" \
  -H "Accept: application/json"
```

## GET `/agency/strategy-reviews/{id}`

Read the exact invited strategy and tone-of-voice pair

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "ok": true,
  "review": {
    "caseId": "string",
    "strategy": {
      "caseId": "string",
      "documentId": "string",
      "versionId": "string",
      "version": "string",
      "templateId": "WZR-BRIEF",
      "title": "string",
      "html": "string",
      "status": "ready_for_review",
      "isCurrent": true,
      "mode": "content"
    },
    "tov": {
      "caseId": "string",
      "documentId": "string",
      "versionId": "string",
      "version": "string",
      "templateId": "WZR-BRIEF",
      "title": "string",
      "html": "string",
      "status": "ready_for_review",
      "isCurrent": true,
      "mode": "content"
    }
  },
  "canRespond": true
}
```

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Review task or pair not visible to this customer

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agency/strategy-reviews/string" \
  -H "Accept: application/json"
```

## POST `/agency/strategy-reviews/{id}`

Receive an original paired response through shared intake; not document acceptance

**Tags:** Agency

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "channel": "portal",
  "kind": "approval",
  "strategy": {
    "documentId": "string",
    "versionId": "string"
  },
  "tov": {
    "documentId": "string",
    "versionId": "string"
  },
  "externalEventId": "string"
}
```

### Responses

**200** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**201** – Response

Content-Type: `application/json`

```json
{
  "requestId": "string",
  "status": "response_received",
  "replayed": true
}
```

**400** – Invalid paired response

Content-Type: `application/json`

**401** – Customer authentication required

Content-Type: `application/json`

**403** – Native portal task permission required

Content-Type: `application/json`

**404** – Review task or pair not visible to this customer

Content-Type: `application/json`

**409** – Stale pair, invalid QA or response conflict

Content-Type: `application/json`

**413** – Request exceeds 100 KB

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agency/strategy-reviews/string" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"channel\": \"portal\",
  \"kind\": \"approval\",
  \"strategy\": {
    \"documentId\": \"string\",
    \"versionId\": \"string\"
  },
  \"tov\": {
    \"documentId\": \"string\",
    \"versionId\": \"string\"
  },
  \"externalEventId\": \"string\"
}"
```

## GET `/agent_orchestrator/agents`

List registered agents

Returns the in-module agent registry (id, result kind, declared agent type, narrowed action vocabulary, tools, skills, label, description, OUTCOME JSON-Schema) for agents declared via defineAgent or the file-agent conventions, merged with the tenant presentation overrides (icon, tags).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Registered agents

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "resultKind": "research",
      "agentType": null,
      "allowedActions": null,
      "runtime": "in-process",
      "tools": [
        "string"
      ],
      "skills": [
        "string"
      ],
      "label": "string",
      "description": "string",
      "icon": null,
      "tags": [
        "string"
      ]
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/agents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/agents/{id}`

Get the full definition of a registered agent

Returns the full in-module agent definition (id, module, result kind, tools, skills, instructions, provider/model, loop) for an agent declared via defineAgent. Gated by agent_orchestrator.agents.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Agent definition

Content-Type: `application/json`

```json
{
  "id": "string",
  "moduleId": "string",
  "resultKind": "research",
  "agentType": null,
  "allowedActions": null,
  "runtime": "in-process",
  "tools": [
    "string"
  ],
  "skills": [
    "string"
  ],
  "skillDetails": [
    {
      "id": "string",
      "label": "string",
      "description": "string",
      "instructions": "string",
      "tools": [
        "string"
      ]
    }
  ],
  "subAgents": [
    "string"
  ],
  "label": "string",
  "description": "string",
  "icon": null,
  "tags": [
    "string"
  ],
  "iconUpdatedAt": null,
  "instructions": "string",
  "defaultProvider": null,
  "defaultModel": null,
  "loop": null,
  "tokenUsage": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown agent id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/agents/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/agents/{id}/files`

Read a file-defined agent's raw definition files

Returns the baked raw content and o200k_base token count of every construction file (AGENT.md, OUTCOME.md, skills, tools, sub-agents) of a file-defined (OpenCode) agent, for the read-only Files tab. 404 for native agents. Gated by agent_orchestrator.agents.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Agent source files

Content-Type: `application/json`

```json
{
  "agentId": "string",
  "files": [
    {
      "path": "string",
      "content": "string",
      "tokens": 1,
      "inContext": true
    }
  ],
  "tokenUsage": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown agent id or native agent (no files)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/agents/:id/files" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/agents/{id}/metrics`

Override rate, eval-pass rate, latency and cost for an agent over a window

Per-agent metrics over a window (24h|7d|30d|90d, default 30d). Prefers a precomputed rollup row when one matches the window and is fresh (source="rollup"); otherwise live-computes from this module's run + correction tables (source="live"). Gated by agent_orchestrator.trace.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Per-agent metrics over the window

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.trace.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/agents/:id/metrics" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/agents/{id}/run`

Run one agent directly (Playground, evals, diagnostics)

An ENGINEERING primitive, not a business-orchestration one. It runs a single agent synchronously and returns what it produced; it has no retry, no wait states, no signals, no cancellation and no durable business lifecycle, because an AgentRun records an agent execution rather than a business process. Use it for the Playground, development, evals, diagnostics and sub-agent invocation. To start durable business work — from an integration, a schedule, an event or by hand — call POST /processes/{id}/executions and observe agent_orchestrator.process.execution.* instead; a caller coupled to an agent id cannot be refactored around. Runs the agent in object mode under the caller scope, persists an AgentRun (and an AgentProposal for proposal results), and returns the typed AgentResult plus additive sibling fields: `runId` (the persisted AgentRun id) and `proposalId` (the newest AgentProposal created by the run, null for researcher runs).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Typed AgentResult + { runId, proposalId }

Content-Type: `application/json`

```json
{
  "kind": "research",
  "runId": null,
  "proposalId": null
}
```

**400** – Tenant context missing, or no single organization is selected (run under "All organizations" is rejected)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.run

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown agent id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid input, invalid model output, run wall-clock timeout — or a runtime guardrail block, in which case the body carries `code: "guardrail_blocked"` plus the typed `kind`/`phase`/`guardrailSetVersion` reason

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Agent run capacity exhausted (admission control); includes Retry-After

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – The run failed for a reason this route does not classify; the body carries `code` (`agent_run_failed`) and a truncated `reason`

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "agent_run_failed",
  "reason": "string"
}
```

**503** – The deployment has no usable LLM provider; the body carries `code` (`no_provider_configured`, `api_key_missing`, or `provider_rejected` when a configured provider refuses the call)

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "no_provider_configured"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/agents/:id/run" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## PUT `/agent_orchestrator/agents/{id}/settings`

Set an agent's presentation icon and tags

Upserts the per-(tenant, organization) presentation icon and operator tags for an agent definition. Both fields are optional and an omitted one is left unchanged. Optimistic-locked on the settings row updatedAt. Gated by agent_orchestrator.agents.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Updated settings

Content-Type: `application/json`

```json
{
  "agentId": "string",
  "icon": null,
  "tags": [
    "string"
  ],
  "updatedAt": "string"
}
```

**400** – Validation failed / missing scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown agent id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/agent_orchestrator/agents/:id/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/artifacts/file/{id}`

Stream a captured artifact’s decrypted bytes

Streams the decrypted bytes of one AgentRunArtifact. Org-scoped; gated by agent_orchestrator.trace.view. Pass ?download=1 to force an attachment disposition.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Artifact bytes

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.trace.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown artifact id or bytes unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/artifacts/file/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/audit/by-instigator/{humanUserId}`

List actions a human caused directly and via agents

Returns ActionLog entries where the human is either the direct actor or the on-behalf-of principal of an agent action, joined on action_logs.on_behalf_of_user_id. Org-scoped; gated by agent_orchestrator.identity.read.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| humanUserId | path | any | Required |

### Responses

**200** – Instigator audit chain

Content-Type: `application/json`

```json
{
  "humanUserId": "string",
  "items": [
    {
      "id": "string",
      "commandId": null,
      "actionType": null,
      "actionLabel": null,
      "sourceKey": null,
      "resourceKind": null,
      "resourceId": null,
      "actorUserId": null,
      "onBehalfOfUserId": null,
      "createdAt": null,
      "via": "direct"
    }
  ],
  "total": 1
}
```

**400** – Invalid query

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.identity.read

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Invalid user id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/audit/by-instigator/:humanUserId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/auto-approval/settings`

Read the tenant auto-approval policy

Returns the policy the disposition service applies, and whether it is the tenant’s own row or the inherited conservative default. Gated by agent_orchestrator.agents.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Resolved policy

Content-Type: `application/json`

```json
{
  "policy": {
    "enabled": true,
    "maxAutoApproveRisk": "low"
  },
  "source": "tenant",
  "riskTiers": [
    "low"
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/auto-approval/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/agent_orchestrator/auto-approval/settings`

Save the tenant auto-approval policy

Writes the tenant-scoped policy row: the master switch and the highest action risk that may run unattended. The complete object is required.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Saved policy

Content-Type: `application/json`

```json
{
  "policy": {
    "enabled": true,
    "maxAutoApproveRisk": "low"
  },
  "source": "tenant",
  "riskTiers": [
    "low"
  ]
}
```

**400** – Invalid policy or missing tenant

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Config store unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/agent_orchestrator/auto-approval/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/context-bundles`

List context bundles

Returns a paginated collection of context bundles scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| agentRunId | query | any | Optional |
| workflowInstanceId | query | any | Optional |
| capability | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated context bundles

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "agent_run_id": "00000000-0000-4000-8000-000000000000",
      "workflow_instance_id": null,
      "step_id": null,
      "capability": "string",
      "pruned_sources": null,
      "token_budget": 1,
      "tokens_used": 1,
      "redaction_applied": null,
      "payload_ref": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/context-bundles?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/corrections`

Record a human correction of an agent proposal and auto-draft an eval case

Writes an append-only AgentCorrection (mandatory non-empty reason) referencing a proposal, and auto-drafts a draft AgentEvalCase from it. Gated by agent_orchestrator.trace.correct.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "proposalId": "00000000-0000-4000-8000-000000000000",
  "action": "edit",
  "reason": "string"
}
```

### Responses

**201** – Correction recorded + eval case drafted

Content-Type: `application/json`

```json
{
  "correctionId": "00000000-0000-4000-8000-000000000000",
  "evalCaseId": "00000000-0000-4000-8000-000000000000"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.trace.correct

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Proposal not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid input (e.g. empty reason)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/corrections" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"proposalId\": \"00000000-0000-4000-8000-000000000000\",
  \"action\": \"edit\",
  \"reason\": \"string\"
}"
```

## DELETE `/agent_orchestrator/eval-assertions`

Delete evalassertion

Soft-deletes an evaluation assertion by id (provided via query).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – EvalAssertion deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/agent_orchestrator/eval-assertions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/agent_orchestrator/eval-assertions`

List eval assertions

Returns a paginated collection of eval assertions scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| appliesTo | query | any | Optional |
| scorerKey | query | any | Optional |
| type | query | any | Optional |
| severity | query | any | Optional |
| enabled | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated eval assertions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "key": "string",
      "scorer_key": "string",
      "title": "string",
      "description": null,
      "applies_to": "string",
      "type": "string",
      "severity": "string",
      "config": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-assertions?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/eval-assertions`

Create evalassertion

Creates an evaluation assertion. `llm_judge` assertions are always stored as `warn` severity (the judge tier never blocks production).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "key": "string",
  "title": "string",
  "appliesTo": "*",
  "type": "deterministic",
  "severity": "gate"
}
```

### Responses

**201** – EvalAssertion created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-assertions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"key\": \"string\",
  \"title\": \"string\",
  \"appliesTo\": \"*\",
  \"type\": \"deterministic\",
  \"severity\": \"gate\"
}"
```

## PUT `/agent_orchestrator/eval-assertions`

Update evalassertion

Updates an evaluation assertion (enable/disable, retarget, or retune its rubric/config).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "appliesTo": "*"
}
```

### Responses

**200** – EvalAssertion updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/agent_orchestrator/eval-assertions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"appliesTo\": \"*\"
}"
```

## POST `/agent_orchestrator/eval-assertions/preview`

Dry-run a scorer or judge rubric against a real historical run

Scores an existing AgentRun with the supplied scorerKey + config and returns the verdict WITHOUT persisting anything. `passed: null` means the assertion would be skipped. Config is validated with the same rules as saving, so a preview cannot green-light a config the form would reject. Judge previews resolve a model and therefore cost a round-trip; they return 422 (not 500) when no provider is configured. Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – The verdict this assertion would produce

Content-Type: `application/json`

**400** – Invalid body

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Run not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Unknown scorer, invalid config, or judge unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-assertions/preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-cases`

List eval cases

Returns a paginated collection of eval cases scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| status | query | any | Optional |
| agentDefinitionId | query | any | Optional |
| sourceType | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated eval cases

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": null,
      "status": "string",
      "source_type": "string",
      "source_id": "00000000-0000-4000-8000-000000000000",
      "agent_definition_id": "string",
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/eval-cases`

Eval case management

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/agent_orchestrator/eval-cases`

Eval case management

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-cases/{id}`

Full eval case including the decrypted input and expected value

The only endpoint that returns a case payload. `input` and `expected` are encrypted at rest and decrypted per record here; the list route projects metadata only and never exposes them. Returns `updatedAt` for optimistic locking. Cross-tenant ids return 404. Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The eval case

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Eval case not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/eval-cases/{id}/approve`

Approve a drafted eval case so it joins the exported regression set

Flips a draft AgentEvalCase to approved. Enforces an optimistic lock on updatedAt (stale write → 409 surfaced via surfaceRecordConflict). Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The approved eval case

Content-Type: `application/json`

```json
{
  "evalCaseId": "00000000-0000-4000-8000-000000000000",
  "status": "string",
  "updatedAt": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Eval case not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic-lock conflict (stale updatedAt) or not in draft

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases/:id/approve" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/eval-cases/{id}/archive`

Archive a drafted eval case so it joins the exported regression set

Flips an eval case to archived, removing it from the replayable set without deleting it. Enforces an optimistic lock on updatedAt (stale write → 409 surfaced via surfaceRecordConflict). Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The archived eval case

Content-Type: `application/json`

```json
{
  "evalCaseId": "00000000-0000-4000-8000-000000000000",
  "status": "string",
  "updatedAt": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Eval case not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic-lock conflict (stale updatedAt) or not in draft

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases/:id/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-cases/export`

Export approved eval cases in the versioned agent_orchestrator eval-case format

Returns a versioned envelope of APPROVED eval cases (drafts/archived excluded), org-scoped, optionally filtered by agentDefinitionId. Consumed by the lifecycle regression gate. Gated by agent_orchestrator.eval.export.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – The versioned eval-case export envelope

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.export

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-cases/export" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-runs`

Paginated history of evaluation runs for the organization

Suite-run history, newest first. Filterable by agentDefinitionId and status. pageSize is capped at 100. Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Paged suite runs

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-runs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/eval-runs`

Run an evaluation of an agent against selected approved eval cases

Replays each selected case through the real agent runtime (FRESH inference under the agent's own principal, propose-only: no proposal is ever disposed) and scores the resulting run against the effective assertion set. Only approved cases are accepted. Selections of 5 case runs or fewer execute inline and return 200 with the finished summary; larger ones are queued and return 202 with status "queued" — follow them via the eval_case_run.* SSE events. Gated by agent_orchestrator.eval.run.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – The completed suite run summary (executed inline)

Content-Type: `application/json`

**202** – The suite run was queued for the eval worker

Content-Type: `application/json`

**400** – Invalid body

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.run

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – No approved cases matched, or selection too large

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-runs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-runs/{id}`

Suite run detail plus a keyset page of its case runs

Returns the suite run and up to `pageSize` (max 100) case runs ordered by created_at, with `nextCursor` for the next page. Assertion results are NOT inlined — fetch them per case run from /eval-runs/:id/case-runs/:caseRunId/results. Cross-tenant ids return 404. Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Suite run + paged case runs

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Suite run not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-runs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/eval-runs/{id}/cancel`

Move a queued or running evaluation to a terminal cancelled state

Idempotent: cancelling an already-terminal run returns its current state. The suite run and its case runs are retained (append-only, >=6yr) — cancelling never deletes. Gated by agent_orchestrator.eval.run.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The cancelled suite run

Content-Type: `application/json`

```json
{
  "suiteRunId": "00000000-0000-4000-8000-000000000000",
  "status": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.run

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Suite run not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/eval-runs/:id/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-runs/{id}/case-runs/{caseRunId}/results`

Per-assertion verdicts for a single case run

`passed: null` means the assertion was SKIPPED (no expected value, invalid config, or unknown scorer) — it is neither a pass nor a failure and is excluded from aggregation. The case run must belong to the suite run in the path. Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| caseRunId | path | any | Required |

### Responses

**200** – Assertion results

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Case run not found in this suite (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-runs/:id/case-runs/:caseRunId/results" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/eval-scorers`

Scorer registry descriptors used to render the evaluation-assertion form

Returns every registered scorer as { scorerKey, labelKey, group, kind, fields[] }. `fields[]` is UI metadata (kind, label key, bounds, options) from which the assertion form is generated, so a new scorer becomes configurable without a UI change. `kind` maps to the assertion `type` column: only `deterministic` scorers may back a `gate`-severity assertion. Deprecated aliases are included and flagged with `deprecated: true` plus `deprecatedInFavourOf`. Gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Scorer descriptors

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/eval-scorers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/executions`

List process executions

Returns a paginated collection of process executions scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| workflowInstanceId | query | any | Optional |
| processDefinitionId | query | any | Optional |
| scope | query | any | Optional |
| status | query | any | Optional |
| subjectType | query | any | Optional |
| sourceEntityType | query | any | Optional |
| sourceEntityId | query | any | Optional |
| q | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated process executions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "workflow_instance_id": null,
      "process_definition_id": null,
      "workflow_id": null,
      "workflow_version": null,
      "triggered_by": null,
      "idempotency_key": null,
      "source_entity_type": null,
      "source_entity_id": null,
      "subject_type": null,
      "subject_id": null,
      "subject_label": null,
      "subject_title": null,
      "subject_value_minor": null,
      "subject_fraud": null,
      "subject_facets": null,
      "status": "string",
      "current_stage": null,
      "milestones_reached": null,
      "agent_ids": null,
      "cost_minor": null,
      "currency": null,
      "run_count": null,
      "pending_proposal_count": null,
      "outcome_type": null,
      "outcome_id": null,
      "outcome_label": null,
      "outcome_href": null,
      "failure_reason": null,
      "assignee_user_id": null,
      "team_id": null,
      "waiting_since": null,
      "opened_at": null,
      "completed_at": null,
      "last_activity_at": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/executions?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/executions/{id}`

Get a process execution with its milestones and outcome

Returns the business-facing view of one execution: derived status, the declared milestones with the ones reached marked done, and the optional outcome with a resolved href. Accepts the execution id or the workflow instance id. Org-scoped; gated by agent_orchestrator.processes.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Process execution

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.processes.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown execution id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/executions/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/features`

List declared ACL feature ids and titles

Flattens the enabled modules’ static feature declarations to id/title/module triples for the agentic-task grantedFeatures picker. Gated by agent_orchestrator.processes.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Declared feature catalog

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "module": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.processes.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/features" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/guardrail-checks`

List guardrail checks

Returns a paginated collection of guardrail checks scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| agentRunId | query | any | Optional |
| proposalId | query | any | Optional |
| phase | query | any | Optional |
| kind | query | any | Optional |
| result | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated guardrail checks

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "agent_run_id": "00000000-0000-4000-8000-000000000000",
      "proposal_id": null,
      "guardrail_set_version": "string",
      "capability": "string",
      "phase": "string",
      "kind": "string",
      "result": "string",
      "evidence": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/guardrail-checks?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/identity/agent/auth`

Onboard an external agent from an issuer-signed assertion and mint a scoped token

RFC 7523 JWT-bearer grant for external-agent self-registration at scale. Validates the issuer-signed ID-JAG assertion (issuer + audience + signature, server-side against the trusted-issuer registry), idempotently onboards the agent to a scoped AgentPrincipal (credentialMode=authmd) + an AgentDelegationGrant (issuer/subject/audience populated), then mints a short-lived, revocable agent token via the same mint path the client-credentials /token server uses. tenant/org/scope are derived from the signed assertion + grant, never widenable by the caller. An invalid/forged/wrong-audience assertion returns a single minimal 401 with no info leak.

**Tags:** Agent Orchestrator

### Request Body

Content-Type: `application/json`

```json
{
  "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
  "assertion": "string"
}
```

### Responses

**200** – The minted access token

Content-Type: `application/json`

```json
{
  "access_token": "string",
  "token_type": "Bearer",
  "expires_in": 1,
  "scope": "string"
}
```

**400** – Malformed request or unsupported grant_type

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Invalid, forged, or wrong-audience assertion

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Too many self-registration requests from this client IP

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Rate limiter unavailable — the request is refused rather than left uncounted

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/identity/agent/auth" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"grant_type\": \"urn:ietf:params:oauth:grant-type:jwt-bearer\",
  \"assertion\": \"string\"
}"
```

## POST `/agent_orchestrator/identity/grants/{id}/revoke`

Revoke a delegation grant

Sets revokedAt on an AgentDelegationGrant through the audited revoke Command (mutation guard + optimistic lock). After revoke, the /token server refuses to mint and every minted token is denied on its next request — revocation stops further agent action immediately. A stale updatedAt returns a structured 409.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – The revoked grant

Content-Type: `application/json`

```json
{
  "grantId": "00000000-0000-4000-8000-000000000000",
  "revokedAt": "string",
  "updatedAt": "string"
}
```

**400** – Tenant context missing or invalid input

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.identity.tokens

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Grant not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic-lock conflict (stale updatedAt)

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/identity/grants/:id/revoke" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/agent_orchestrator/identity/token`

Mint a scoped, revocable agent access token

OAuth 2.0 client-credentials grant for external agents. Validates the client_id/client_secret against an external (oauth_client) AgentPrincipal with an active (non-revoked, non-expired) AgentDelegationGrant, then mints a short-lived audience-bound JWT scoped to the grant capability + the principal tenant/org (both server-derived, never widenable by the client). Invalid credentials or an inactive grant return a single minimal 401 with no info leak.

**Tags:** Agent Orchestrator

### Request Body

Content-Type: `application/json`

```json
{
  "grant_type": "client_credentials",
  "client_id": "string",
  "client_secret": "string"
}
```

### Responses

**200** – The minted access token

Content-Type: `application/json`

```json
{
  "access_token": "string",
  "token_type": "Bearer",
  "expires_in": 1,
  "scope": "string"
}
```

**400** – Malformed request or unsupported grant_type

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Invalid client credentials or inactive grant

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Too many token requests from this client IP

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Rate limiter unavailable — the request is refused rather than left uncounted

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/identity/token" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"grant_type\": \"client_credentials\",
  \"client_id\": \"string\",
  \"client_secret\": \"string\"
}"
```

## GET `/agent_orchestrator/identity/well-known`

Discover the agent-auth endpoints and supported grant types

Public, read-only agent-auth discovery metadata for external-agent onboarding at scale: the token + agent-auth endpoints, the supported grant types (client_credentials + the ID-JAG / JWT-bearer flow), and the assertion audience an external ID-JAG assertion must target. Contains no secrets, issuer keys, or JWKS.

**Tags:** Agent Orchestrator

### Responses

**200** – The agent-auth discovery metadata

Content-Type: `application/json`

```json
{
  "issuer": "string",
  "token_endpoint": "string",
  "agent_auth_endpoint": "string",
  "grant_types_supported": [
    "string"
  ],
  "agent_assertion_audience": "string",
  "token_audience": "string",
  "token_endpoint_auth_methods_supported": [
    "string"
  ]
}
```

**429** – Too many discovery requests from this client IP

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Rate limiter unavailable — the request is refused rather than left uncounted

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/identity/well-known" \
  -H "Accept: application/json"
```

## GET `/agent_orchestrator/metrics/agents`

Runs, error/override/eval-pass rates and estimated cost per agent over a window

Batch per-agent metrics over a window (24h|7d|30d, default 7d) for up to 50 comma-separated agent ids. Each item prefers a fresh precomputed rollup row (source="rollup") and live-computes otherwise (source="live"); ids with no data return zero-run items and unknown ids are indistinguishable from agents that never ran (no existence oracle). Cost figures are estimates priced from the deployment model-pricing table. Gated by agent_orchestrator.agents.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Per-agent metric items for the requested ids

Content-Type: `application/json`

**400** – Invalid query (missing ids or more than 50)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/metrics/agents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/metrics/overview`

Auto-approve rate, pending backlog and run totals for the organization over a window

Org-level cockpit metrics over a window (24h|7d|30d, default 7d). Windowed run totals aggregate fresh precomputed per-agent rollup rows when available (source="rollup") and fall back to live indexed aggregates (source="live"). pendingCount, oldestPendingAt and dispositionCounts are current-state indexed counts of agent proposals, not windowed history. Additive fields: `correctionsCount` (windowed corrections) and a `traces` block ({ p95LatencyMs, errorRate, evalPassRate, source }) for the traces-list KPI strip — its error/eval rates prefer fresh rollup count sums; p95 is always live-computed (percentiles are not aggregatable from per-agent rollups). Gated by agent_orchestrator.proposals.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Overview metrics for the authenticated organization

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.proposals.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/metrics/overview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/agent_orchestrator/processes`

Delete processdefinition

Soft-deletes a process definition, unregisters every schedule it registered, and removes the workflow it generated (a hand-authored workflow is left alone).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – ProcessDefinition deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/agent_orchestrator/processes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/agent_orchestrator/processes`

List processes

Returns a paginated collection of processes scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| workflowId | query | any | Optional |
| enabled | query | any | Optional |
| search | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated processes

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "description": null,
      "workflow_id": "string",
      "input_defaults": null,
      "input_schema": null,
      "outcome_schema": null,
      "triggers": null,
      "milestones": null,
      "ui_metadata": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null,
      "last_execution": null,
      "single_agent": null,
      "granted_features": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/processes?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/processes`

Create processdefinition

Creates a process definition. Every process points at a workflow: `workflowMode: "workflow"` binds an existing one, `"single_agent"` generates a real START → INVOKE_AGENT → END workflow owned by this definition and editable in the Studio. `grantedFeatures` is applied to that workflow, which owns the least-privilege execution identity every run acts as. Registers a scheduler job for each declared `{ kind: "schedule" }` trigger.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "description": null,
  "workflowMode": "workflow",
  "workflowId": null,
  "singleAgent": null,
  "inputDefaults": null,
  "inputSchema": null,
  "outcomeSchema": null,
  "uiMetadata": null
}
```

### Responses

**201** – ProcessDefinition created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/processes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"workflowMode\": \"workflow\",
  \"workflowId\": null,
  \"singleAgent\": null,
  \"inputDefaults\": null,
  \"inputSchema\": null,
  \"outcomeSchema\": null,
  \"uiMetadata\": null
}"
```

## PUT `/agent_orchestrator/processes`

Update processdefinition

Updates a process definition (optimistic-locked on updatedAt). Regenerates the bound workflow in single-agent mode and re-syncs every declared schedule trigger.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "description": null,
  "workflowMode": "workflow",
  "workflowId": null,
  "singleAgent": null,
  "inputDefaults": null,
  "inputSchema": null,
  "outcomeSchema": null,
  "uiMetadata": null
}
```

### Responses

**200** – ProcessDefinition updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/agent_orchestrator/processes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"description\": null,
  \"workflowMode\": \"workflow\",
  \"workflowId\": null,
  \"singleAgent\": null,
  \"inputDefaults\": null,
  \"inputSchema\": null,
  \"outcomeSchema\": null,
  \"uiMetadata\": null
}"
```

## GET `/agent_orchestrator/processes/{id}`

Get a process definition with its declared triggers

Returns the process definition including updatedAt for optimistic locking, the bound workflowId, the declared triggers list (schedule / event / manual) and the milestone vocabulary. Org-scoped; gated by agent_orchestrator.processes.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Process definition detail

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.processes.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown process definition id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/processes/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/processes/{id}/executions`

Start one execution of this process (always async)

Requires the definition to declare a { kind: "manual" } trigger (403 otherwise) plus any features that trigger names. Validates input against the definition inputSchema when set, dedupes on idempotencyKey so one key can never produce two executions, and starts the bound workflow. Returns 202 with the executionId immediately; observe completion via the agent_orchestrator.process.execution.* events or GET /executions/:id. Gated by agent_orchestrator.processes.run (session or API key).

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**202** – Execution accepted

Content-Type: `application/json`

```json
{
  "executionId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed (body or inputSchema)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.processes.run, no declared manual trigger, or missing the trigger's requireFeatures

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown process definition id (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Process definition disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/processes/:id/executions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/proposals`

List proposals

Returns a paginated collection of proposals scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| agentId | query | any | Optional |
| workflowInstanceId | query | any | Optional |
| disposition | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated proposals

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "agent_id": "string",
      "run_id": "00000000-0000-4000-8000-000000000000",
      "workflow_instance_id": null,
      "step_id": null,
      "confidence": null,
      "disposition": "string",
      "disposition_by": null,
      "disposition_reason": null,
      "selected_option_id": null,
      "auto_disposition_block": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/proposals?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/proposals/{id}/dispose`

Dispose a proposal

Records an operator verdict (approve/edit/reject) on a pending AgentProposal. Routes through the audited dispose Command (mutation guard + optimistic lock); on a workflow-originated proposal it emits the resume signal. Edit overrides the proposal payload (requires payload + reason); reject requires a reason. `selectedOptionId` names which of the envelope options the verdict runs — required for approve/edit, forbidden for reject, and rejected with a 400 when it names an option the agent never offered.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "disposition": "approved"
}
```

### Responses

**200** – The updated proposal

Content-Type: `application/json`

```json
{
  "proposalId": "00000000-0000-4000-8000-000000000000",
  "disposition": "auto_approved",
  "dispositionBy": null,
  "selectedOptionId": null,
  "updatedAt": "string"
}
```

**400** – Tenant context missing or invalid input

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.proposals.dispose

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Proposal not found (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic-lock conflict (stale updatedAt) or already disposed

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/proposals/:id/dispose" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"disposition\": \"approved\"
}"
```

## GET `/agent_orchestrator/runs`

List runs

Returns a paginated collection of runs scoped to the authenticated organization.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| idPrefix | query | any | Optional |
| agentId | query | any | Optional |
| status | query | any | Optional |
| resultKind | query | any | Optional |
| agentType | query | any | Optional |
| flagged | query | any | Optional |
| filter | query | any | Optional |
| window | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated runs

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "agent_id": "string",
      "status": null,
      "result_kind": null,
      "error_message": null,
      "runtime": null,
      "external_run_id": null,
      "model": null,
      "confidence": null,
      "eval_score": null,
      "eval_passed": null,
      "latency_ms": null,
      "cost_minor": null,
      "currency": null,
      "input_tokens": null,
      "output_tokens": null,
      "workflow_instance_id": null,
      "proposal_id": null,
      "human_confirmed_at": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/runs?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/runs/{id}`

Get a full agent run with its spans and tool calls

Returns the run plus its ordered spans, tool-calls, eval results, the assembled context bundle (TDCR), guardrail check verdicts, and its proposals (decrypted payloads carrying the persisted rationale) for the trace inspector. Org-scoped; gated by agent_orchestrator.trace.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Run trace detail

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.trace.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown run id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/runs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/runs/{id}/artifact`

Retrieve the full (decrypted) offloaded output or tool payload for a run by storage key

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Decrypted artifact payload

Content-Type: `application/json`

**404** – Run or artifact key not found for this scope

Content-Type: `application/json`

**422** – Invalid artifact request

Content-Type: `application/json`

**502** – Artifact storage unavailable

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/runs/:id/artifact" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/runs/{id}/artifacts`

List the files a file-agent produced during a run

Returns metadata (no bytes) for every captured AgentRunArtifact of the run. Org-scoped; gated by agent_orchestrator.trace.view. Download bytes via /api/agent_orchestrator/artifacts/file/:id.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Run artifact list

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.trace.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown run id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/runs/:id/artifacts" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/runs/{id}/eval-case`

Create a draft golden-run eval case from this run

Drafts an AgentEvalCase (sourceType golden_run) from the run input/output. Idempotent per run — a repeat call returns the existing case with created: false. Org-scoped; gated by agent_orchestrator.eval.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The draft eval case

Content-Type: `application/json`

```json
{
  "evalCase": {
    "id": "00000000-0000-4000-8000-000000000000",
    "status": "string"
  },
  "created": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.eval.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown run id (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/runs/:id/eval-case" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/runs/{id}/flag`

Flag or unflag an agent run

Toggles the operator triage flag: an unflagged run gains flaggedAt/flaggedBy, a flagged run has both cleared. Org-scoped; gated by agent_orchestrator.trace.correct.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The new flag state

Content-Type: `application/json`

```json
{
  "flagged": true,
  "flaggedAt": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.trace.correct

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown run id (or cross-tenant)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/runs/:id/flag" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/runs/{id}/rerun`

Execute the run again with its original input

Runs the same agent with the decrypted original input through the standard execution path (admission control, guardrails, disposition) and links the new run via rerun_of_run_id. Returns the new run id. Org-scoped; gated by agent_orchestrator.agents.run.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – The new run id

Content-Type: `application/json`

```json
{
  "runId": null
}
```

**400** – Tenant context missing, or no single organization is selected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.run

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Unknown run id, cross-tenant run, or the agent is no longer registered

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid model output, run wall-clock timeout — or a runtime guardrail block, in which case the body carries `code: "guardrail_blocked"` plus the typed `kind`/`phase`/`guardrailSetVersion` reason

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Agent run capacity exhausted (admission control); includes Retry-After

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/runs/:id/rerun" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/tokens/estimate`

Count the o200k_base tokens of arbitrary text

Returns the o200k_base token count of the supplied text using the same shared tokenizer that powers the per-file estimates on the Files tab. Gated by agent_orchestrator.agents.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "text": "string"
}
```

### Responses

**200** – Token estimate

Content-Type: `application/json`

```json
{
  "tokens": 1,
  "encoding": "string"
}
```

**400** – Invalid body

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Text too long

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/tokens/estimate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"text\": \"string\"
}"
```

## POST `/agent_orchestrator/trace/ingest`

Ingest a normalized, HMAC-signed agent run trace (idempotent by runtime + externalRunId)

**Tags:** Agent Orchestrator

### Responses

**202** – Trace accepted (run upserted, spans/tool-calls appended)

Content-Type: `application/json`

**401** – HMAC signature verification failed

Content-Type: `application/json`

**422** – Invalid trace payload

Content-Type: `application/json`

**429** – Too many ingest requests from this client IP

Content-Type: `application/json`

**503** – Rate limiter unavailable — the request is refused rather than left uncounted

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/trace/ingest" \
  -H "Accept: application/json"
```

## GET `/agent_orchestrator/web-search/health`

Report every installed web-search adapter and its health

Builds the tenant-resolved adapter set and reports one row per installed adapter. `probe` selects how much verification is done: omitted reports configuration readiness only; `auto` additionally calls every adapter whose health check is free and reuses a cached result for the ones that cost; `1` calls everything live and requires agent_orchestrator.agents.manage, because a metered source bills for it. `force=1` overrides the cached result of a costly adapter once it is older than 30 seconds, and `adapter=<id>` limits the live call to one adapter. Top-level `probed` is true only when every enabled adapter was verified. Reading is gated by agent_orchestrator.proposals.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Web-search adapter health

Content-Type: `application/json`

```json
{
  "status": "ok",
  "source": "tenant",
  "adapters": [
    {
      "id": "string",
      "enabled": true,
      "ready": true,
      "ok": true,
      "detail": null,
      "latencyMs": null,
      "probed": true,
      "probeCost": "free",
      "checkedAt": null
    }
  ],
  "problems": [
    {
      "id": null,
      "packageName": "string",
      "reason": "string"
    }
  ],
  "probed": true,
  "checkedAt": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.proposals.view, or agent_orchestrator.agents.manage for probe=1

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/web-search/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/agent_orchestrator/web-search/preview`

Run one search and return every adapter’s own results

Runs the tenant’s configured adapters exhaustively and returns each one’s untouched result list and prose alongside the fused ranking, so an operator can weigh sources against each other. Never cached. Spends real egress and, with a metered adapter, real money — gated by agent_orchestrator.agents.manage.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Per-adapter comparison

Content-Type: `application/json`

```json
{
  "query": "string",
  "settleMode": "string",
  "fused": [
    {}
  ],
  "answer": null,
  "diagnostics": {},
  "byAdapter": [
    {
      "adapterId": "string",
      "weight": 1,
      "answer": null,
      "results": [
        {
          "url": "string",
          "title": null,
          "snippet": null,
          "blockedByGuardrails": true
        }
      ]
    }
  ],
  "problems": [
    {
      "id": null,
      "packageName": "string",
      "reason": "string"
    }
  ]
}
```

**400** – Invalid query

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Tenant rate limit exceeded

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/agent_orchestrator/web-search/preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/agent_orchestrator/web-search/settings`

Read the resolved web-search policy and installed adapter catalogue

Returns the tenant-resolved policy (env default overlaid with the tenant row), the guardrails, and every installed adapter package. Gated by agent_orchestrator.agents.view.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Resolved settings

Content-Type: `application/json`

```json
{
  "policy": {},
  "guardrails": {},
  "source": "tenant"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.view

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/agent_orchestrator/web-search/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/agent_orchestrator/web-search/settings`

Save the tenant web-search policy

Writes the tenant-scoped policy row. Validated against the engine policy schema; unknown adapters are accepted so a policy can be written before its package is installed.

**Tags:** Agent Orchestrator

**Requires authentication.**

### Responses

**200** – Saved settings

Content-Type: `application/json`

```json
{
  "policy": {},
  "guardrails": {},
  "source": "tenant"
}
```

**400** – Invalid settings or missing tenant

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing agent_orchestrator.agents.manage

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Config store unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/agent_orchestrator/web-search/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/ai/actions/{id}`

Fetch the current state of an AI pending action by id.

Returns the tenant-scoped {@link AiPendingAction} addressed by `:id`. Powers the chat UI reconnect/polling path: after a page reload or SSE reconnect the client carries the `pendingActionId` from an earlier `mutation-preview-card` UI part and calls this route to re-hydrate the card. Server-internal fields (`normalizedInput`, `createdByUserId`, `idempotencyKey`) are stripped by a whitelist serializer. Enforces tenant/org scoping via the repository.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Serialized pending action. Never includes normalizedInput, createdByUserId, or idempotencyKey.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

**404** – No pending action with the given id is accessible to the caller.

Content-Type: `application/json`

**500** – Internal runtime failure.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/actions/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/actions/{id}/cancel`

Cancel an AI pending action without executing the wrapped tool.

Flips a pending AI action from `pending` to `cancelled` and emits the `ai.action.cancelled` event. The tool handler is never invoked. Idempotent: a second call on a row already in `cancelled` status returns 200 with the current row without re-emitting the event. Rows whose `expiresAt` is in the past are flipped to `expired` and returned as 409 `expired` so the client can surface the TTL loss instead of silently masking it as a cancellation.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Cancellation complete (or idempotent replay); body includes the serialized pending action with status `cancelled`.

Content-Type: `application/json`

**400** – Invalid cancel request body (unknown field, reason exceeds 500 chars, wrong type).

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.view`.

Content-Type: `application/json`

**404** – Pending action not found in the caller scope.

Content-Type: `application/json`

**409** – Pending action is not in `pending` status (already confirmed/failed/executing) or has expired.

Content-Type: `application/json`

**500** – Unexpected server failure during cancel.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/actions/:id/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/actions/{id}/confirm`

Confirm an AI pending action, re-running every server-side check before execution.

Re-verifies the full contract from spec §9.4 (status, expiry, agent registration, required features, mutation policy, tool whitelist, attachment tenant scope, record version, and schema drift), flips the pending-action state machine to `executing`, invokes the wrapped tool handler, and persists `executionResult`. Idempotent: a second call on a row already in `confirmed` state returns the prior result without re-executing the handler.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Confirmation complete; body includes the serialized pending action and the mutation result.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.view`, a required agent feature, tool whitelist, or accesses attachments outside their tenant.

Content-Type: `application/json`

**404** – Pending action or agent not found in the caller scope.

Content-Type: `application/json`

**409** – Pending action is not in `pending` status or has expired.

Content-Type: `application/json`

**412** – Record version changed between propose and confirm, or the input schema no longer accepts the stored payload.

Content-Type: `application/json`

**500** – Unexpected server failure during confirm.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/actions/:id/confirm" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/ai/agents`

List registered AI agents, filtered by the caller's features.

Returns `{ agents: [...] }` — the subset of agents from `ai-agents.generated.ts` that the authenticated caller can invoke based on each agent's `requiredFeatures`. Mirrors the `meta.list_agents` tool handler so backoffice pages (e.g. the playground) can render an agent picker without going through the MCP tool transport.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Accessible agent summaries.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**500** – Internal failure while loading the agent registry.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/agents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/ai_assistant/ai/agents/{agentId}/loop-override`

Remove the loop-policy columns from the agent-scoped runtime override row.

Nulls out all seven loop columns on the agent-scoped `ai_agent_runtime_overrides` row. Idempotent — returns 200 even when no override exists. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Responses

**200** – Loop override cleared (or already absent).

Content-Type: `application/json`

**400** – Invalid agent id.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/loop-override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/ai/agents/{agentId}/loop-override`

Read the current loop-policy override for this agent, if any.

Returns `{ agentId, override }` where `override` is the agent-scoped loop-policy row from `ai_agent_runtime_overrides` (or `null`). Requires `ai_assistant.view`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Responses

**200** – Loop override payload.

Content-Type: `application/json`

**400** – Invalid agent id.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.view`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/loop-override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/ai_assistant/ai/agents/{agentId}/loop-override`

Set (or replace) the tenant-scoped loop-policy override for this agent.

Body: loop columns. All fields are nullable/optional; `null` explicitly clears that axis. Validates `loopStopWhenJson` items and `loopActiveToolsJson` membership. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "loopDisabled": null,
  "loopMaxSteps": null,
  "loopMaxToolCalls": null,
  "loopMaxWallClockMs": null,
  "loopMaxTokens": null,
  "loopStopWhenJson": null,
  "loopActiveToolsJson": null
}
```

### Responses

**200** – Override persisted.

Content-Type: `application/json`

**400** – Invalid agent id or validation error.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/loop-override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"loopDisabled\": null,
  \"loopMaxSteps\": null,
  \"loopMaxToolCalls\": null,
  \"loopMaxWallClockMs\": null,
  \"loopMaxTokens\": null,
  \"loopStopWhenJson\": null,
  \"loopActiveToolsJson\": null
}"
```

## GET `/ai_assistant/ai/agents/{agentId}/models`

Get the providers and curated models available for the chat-UI picker for this agent

Returns all configured providers with their curated model catalogs, filtered to providers that have an API key configured in the current environment. When the agent declares `allowRuntimeOverride: false`, the response reflects that constraint so the UI picker can hide itself. Includes the agent's resolved default provider/model so the picker can render a "(default)" badge next to the right entry. When a tenant-scoped lookup (the allowlist snapshot or the per-agent runtime override) cannot be loaded, the route still answers 200 with a partially resolved provider list and sets `degraded: true` plus a `degradedReason` code, so callers can tell a full entitlement list from a partial one. RBAC: requires the same features as the agent itself (typically `ai_assistant.view`).

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Responses

**200** – Providers and curated models available for the agent picker. Empty `providers` array when `allowRuntimeOverride` is false. `degraded` is `false` and `degradedReason` is `null` on a fully resolved response; `degraded: true` with `degradedReason: "tenant_allowlist_unavailable"` means a tenant-scoped lookup failed, so `providers` may be missing the tenant allowlist and/or the per-agent override narrowing — one code covers the whole tenant-scoped block because no client can act differently per source. Clients SHOULD render the list but MUST NOT treat it as the tenant's authoritative entitlement (for example, do not prune a stored model selection against it).

Content-Type: `application/json`

**401** – Unauthenticated.

Content-Type: `application/json`

**403** – Caller lacks the agent's required features.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/models" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/ai_assistant/ai/agents/{agentId}/mutation-policy`

Remove the tenant-scoped mutationPolicy override for this agent.

Deletes the override row if it exists; subsequent calls fall back to the agent's code-declared policy. Idempotent — returns 200 even when no override exists. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Responses

**200** – Override cleared (or already absent).

Content-Type: `application/json`

**400** – Invalid agent id.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/mutation-policy" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/ai/agents/{agentId}/mutation-policy`

Read the effective mutationPolicy for an agent — code-declared value plus any tenant override.

Returns `{ agentId, codeDeclared, override }` where `codeDeclared` is the agent's compiled-in `mutationPolicy` and `override` is the persisted tenant-scoped override (or `null`). Requires `ai_assistant.view`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Responses

**200** – Effective mutationPolicy payload.

Content-Type: `application/json`

**400** – Invalid agent id.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.view`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/mutation-policy" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/agents/{agentId}/mutation-policy`

Set (or replace) the tenant-scoped mutationPolicy override for this agent.

Body: `{ mutationPolicy: "read-only" | "confirm-required" | "destructive-confirm-required", notes? }`. The override MUST NOT escalate beyond the agent's code-declared policy. Escalation attempts are rejected with 400 + `code: "escalation_not_allowed"`. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "mutationPolicy": "read-only"
}
```

### Responses

**200** – Override persisted.

Content-Type: `application/json`

**400** – Invalid agent id, malformed body, or escalation attempt.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/mutation-policy" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"mutationPolicy\": \"read-only\"
}"
```

## GET `/ai_assistant/ai/agents/{agentId}/prompt-override`

Read the latest prompt-section override for an agent plus recent version history.

Returns `{ agentId, override, versions }` where `override` is the latest persisted row (or `null`) and `versions` is the newest-first history capped at 10 rows. Tenant-scoped; requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Responses

**200** – Latest override + recent version history.

Content-Type: `application/json`

**400** – Invalid agent id.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/prompt-override" \
  -H "Accept: application/json"
```

## POST `/ai_assistant/ai/agents/{agentId}/prompt-override`

Save a new prompt-section override version for the agent.

Persists an additive `{ sections: Record<sectionId, text>, notes? }` override, allocating the next monotonic version for `(tenant, org, agent)`. Reserved policy keys (`mutationPolicy`, `readOnly`, `allowedTools`, `acceptedMediaTypes`) are rejected with 400 / `reserved_key`. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agentId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Override persisted. Returns `{ ok: true, version, updatedAt }`.

Content-Type: `application/json`

**400** – Invalid agent id, malformed body, or reserved policy key.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/agents/:agentId/prompt-override" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/ai_assistant/ai/chat`

Stream a chat turn for a registered AI agent

Dispatches a chat turn to the focused AI agent identified by `?agent=<module>.<agent>`. Enforces agent-level `requiredFeatures`, tool whitelisting, read-only / mutationPolicy, execution-mode compatibility, and attachment media-type policy. The streaming response body uses an AI SDK-compatible `text/event-stream` transport. Optional `?provider=`, `?model=`, and `?baseUrl=` query params let callers override the resolved provider/model/base-URL for this turn (Phase 4a). Provider must be registered and configured; baseUrl must match `AI_RUNTIME_BASEURL_ALLOWLIST` when set. Both are suppressed when the agent declares `allowRuntimeOverride: false`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| agent | query | any | Required |
| provider | query | any | Optional |
| model | query | any | Optional |
| baseUrl | query | any | Optional |
| loopBudget | query | any | Optional |

### Request Body

Content-Type: `application/json`

```json
{
  "messages": [
    {
      "role": "user",
      "content": "string"
    }
  ]
}
```

### Responses

**200** – Streaming text/event-stream response compatible with AI SDK chat transports.

Content-Type: `text/event-stream`

**400** – Invalid query param, malformed payload, or message count above the cap. Typed codes: `runtime_override_disabled` (agent has allowRuntimeOverride:false), `provider_unknown` (provider id not registered), `provider_not_configured` (provider registered but no API key in env), `baseurl_not_allowlisted` (baseUrl not in AI_RUNTIME_BASEURL_ALLOWLIST).

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks agent-level or tool-level required features.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

**409** – Agent/tool/execution-mode policy violation.

Content-Type: `application/json`

**500** – Internal runtime failure.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/chat?agent=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"messages\": [
    {
      \"role\": \"user\",
      \"content\": \"string\"
    }
  ]
}"
```

## GET `/ai_assistant/ai/conversations`

List AI chat conversations visible to the caller.

Returns `{ items, nextCursor }` for the authenticated caller, ordered by `lastMessageAt` descending. View-only callers receive only their own conversations. Callers with `ai_assistant.conversations.manage` may list conversations across users in the same tenant/organization. The `agent` and `status` filters are optional; `cursor` is the ISO timestamp returned by a previous response.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Caller-owned conversation summaries.

Content-Type: `application/json`

**400** – Invalid query parameters.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/conversations`

Idempotently create a new AI chat conversation.

If a non-deleted conversation already exists with the supplied `conversationId` for the authenticated caller in this tenant/org, returns the existing summary. Otherwise creates a fresh row and writes the owner-participant row in the same transaction.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Existing conversation (idempotent path).

Content-Type: `application/json`

**201** – Newly created conversation.

Content-Type: `application/json`

**400** – Invalid request body.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/ai_assistant/ai/conversations/{conversationId}`

Soft-delete a conversation and its messages.

View-only callers can delete only their own conversations. Callers with `ai_assistant.conversations.manage` can delete conversations in the same tenant/organization. Marks the conversation row and every undeleted message row with a `deleted_at` timestamp in one transaction. The transcript remains in the database for audit/restore until a future retention worker hard-deletes it.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| conversationId | path | any | Required |

### Responses

**200** – Soft-delete acknowledgment.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

**404** – No conversation accessible to the caller.

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/:conversationId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/ai/conversations/{conversationId}`

Fetch a conversation summary and recent transcript.

Returns `{ conversation, messages, nextCursor }` for the supplied `conversationId`. View-only callers can load only their own conversations. Callers with `ai_assistant.conversations.manage` can load conversations across users in the same tenant/organization. Messages are ordered ascending by `createdAt`. The `before` cursor returns the next older page when paging back through long transcripts.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| conversationId | path | any | Required |

### Responses

**200** – Conversation transcript page for the authenticated owner.

Content-Type: `application/json`

**400** – Invalid path or query parameters.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

**404** – No conversation accessible to the caller.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/:conversationId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/ai_assistant/ai/conversations/{conversationId}`

Update an existing conversation.

Accepts a partial body containing any of `title`, `status`, `pageContext`. Setting `status` to `closed` archives the conversation while keeping its transcript intact. View-only callers can update only their own conversations; conversation managers can update conversations in the same tenant/organization.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| conversationId | path | any | Required |

### Responses

**200** – Updated conversation summary.

Content-Type: `application/json`

**400** – Invalid request body.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

**404** – No conversation accessible to the caller.

Content-Type: `application/json`

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/:conversationId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/ai/conversations/{conversationId}/participants`

List active participants of a conversation.

Returns the list of active (non-revoked) participants for the conversation. Only the conversation owner or a caller with `ai_assistant.conversations.manage` can call this endpoint.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| conversationId | path | any | Required |

### Responses

**200** – List of active participants.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks required features.

Content-Type: `application/json`

**404** – Conversation not found or not accessible.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/:conversationId/participants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/conversations/{conversationId}/participants`

Add a participant to a conversation.

Grants a named user read access to the conversation. Requires `ai_assistant.conversations.share`. Only the conversation owner may add participants. If the user was previously revoked, the soft-deleted row is restored.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| conversationId | path | any | Required |

### Responses

**201** – Participant added; conversation visibility updated to "shared".

Content-Type: `application/json`

**400** – Invalid request body.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks required feature or is not the owner.

Content-Type: `application/json`

**404** – Conversation not found.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/:conversationId/participants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/ai_assistant/ai/conversations/{conversationId}/participants/{userId}`

Revoke a participant from a conversation (soft-delete).

Soft-deletes the participant row. If no active non-owner participants remain, the conversation visibility is reset to "private". Only the conversation owner or a manager may revoke participants.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| conversationId | path | any | Required |
| userId | path | any | Required |

### Responses

**204** – Participant revoked.

**400** – Invalid path parameters.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks required features or is not the owner.

Content-Type: `application/json`

**404** – Conversation not found.

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/:conversationId/participants/:userId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/conversations/import`

Import a conversation that previously lived only in browser localStorage.

Idempotent: messages with `clientMessageId` already present in the server transcript are skipped and counted in `skippedMessageCount`. New messages are appended with the original `clientMessageId` so subsequent retries continue to dedupe. Up to 100 messages per request. Attachment previews stored as `data:` URLs in the source localStorage record MUST NOT be forwarded to this endpoint; the UI strips them before upload.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Import result including imported/skipped counters.

Content-Type: `application/json`

**400** – Invalid request body.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks the `ai_assistant.view` feature.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/conversations/import" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/ai/run-object`

Run an object-mode AI agent and return the generated object

Invokes `runAiAgentObject` server-side for the registered AI agent identified by `agent` (matching "<module>.<agent>"). Enforces the same `requiredFeatures`, tool whitelisting, mutationPolicy, and attachment media-type policy as the chat dispatcher, but additionally requires the agent to declare `executionMode: "object"`. Returns the generated object in a single JSON response (no streaming).

**Tags:** AI Assistant

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "agent": "string",
  "messages": [
    {
      "role": "user",
      "content": "string"
    }
  ]
}
```

### Responses

**200** – Object-mode run completed; response body contains `{ object, usage?, finishReason? }`.

Content-Type: `application/json`

**400** – Malformed payload or message cap exceeded.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks agent-level or tool-level required features.

Content-Type: `application/json`

**404** – Unknown agent id.

Content-Type: `application/json`

**409** – Agent/tool/execution-mode policy violation.

Content-Type: `application/json`

**422** – Agent does not support object-mode execution.

Content-Type: `application/json`

**500** – Internal runtime failure.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/ai/run-object" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"agent\": \"string\",
  \"messages\": [
    {
      \"role\": \"user\",
      \"content\": \"string\"
    }
  ]
}"
```

## POST `/ai_assistant/chat`

Send message to AI agent via SSE stream

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/chat" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/health`

Check OpenCode and MCP connection status

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/mcp-key`

Generate MCP API key

Generates a persistent `omk_` API key scoped to the calling user's tenant/organization and carrying the caller's own roles, so the key has the same ACL as the user.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – API key created

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "keyPrefix": "string",
  "secret": "string",
  "tenantId": null,
  "organizationId": null,
  "roles": [
    "string"
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to create MCP API key

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/mcp-key" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/moderation-flags`

List input-moderation audit flags for the current tenant.

Returns the append-only `ai_moderation_flags` audit rows (category flags + scores only — never prompt content) for the caller's tenant. Always tenant-scoped; cross-tenant access is impossible. Optionally filtered by `agentId`, `userId`, and a `from`/`to` date window. Paginated (`pageSize` ≤ 100). Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| agentId | query | any | Optional |
| userId | query | any | Optional |
| from | query | any | Optional |
| to | query | any | Optional |

### Responses

**200** – Paginated moderation-flag rows: `{ items, total, page, pageSize }`.

Content-Type: `application/json`

**400** – Invalid query parameters.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**500** – Internal failure.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/moderation-flags?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/route`

Route user query to appropriate AI handler

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/route" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/session-key`

Generate session key

Generates a new session token that can be included in MCP tool calls via the _sessionToken parameter. The token inherits the calling user's roles and organization context.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Session key created successfully

Content-Type: `application/json`

```json
{
  "sessionToken": "string",
  "expiresAt": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to create session key

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/session-key" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/ai_assistant/settings`

Clear per-tenant AI runtime override

Soft-deletes the active per-tenant runtime override. Pass `agentId` to clear only the agent-specific row; omit to clear the tenant-wide default. Gated by `ai_assistant.settings.manage`. Idempotent — returns 200 with `cleared: false` when no active row existed.

**Tags:** AI Assistant

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "agentId": null
}
```

### Responses

**200** – Returns `{ cleared: boolean }` indicating whether a row was found and removed.

Content-Type: `application/json`

**401** – Unauthenticated.

Content-Type: `application/json`

**403** – Caller lacks ai_assistant.settings.manage.

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/ai_assistant/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"agentId\": null
}"
```

## GET `/ai_assistant/settings`

Get AI provider configuration

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/ai_assistant/settings`

Upsert per-tenant AI runtime override

Creates or updates the per-tenant AI runtime override (provider, model, baseURL). Optionally scoped to a specific agent via `agentId`. Gated by `ai_assistant.settings.manage`. baseURL must match AI_RUNTIME_BASEURL_ALLOWLIST when set.

**Tags:** AI Assistant

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "providerId": null,
  "modelId": null,
  "baseURL": null,
  "agentId": null,
  "allowedOverrideProviders": null,
  "inputModeration": null
}
```

### Responses

**200** – Override saved. Returns the saved row.

Content-Type: `application/json`

**400** – Validation error: unknown provider, invalid URL, or baseURL not allowlisted.

Content-Type: `application/json`

**401** – Unauthenticated.

Content-Type: `application/json`

**403** – Caller lacks ai_assistant.settings.manage.

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/ai_assistant/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"providerId\": null,
  \"modelId\": null,
  \"baseURL\": null,
  \"agentId\": null,
  \"allowedOverrideProviders\": null,
  \"inputModeration\": null
}"
```

## DELETE `/ai_assistant/settings/allowlist`

Clear per-tenant AI provider/model allowlist

Soft-deletes the tenant allowlist row. Tenant overrides revert to env-only enforcement. Idempotent — returns `{ cleared: false }` when no active row existed.

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Returns `{ cleared: boolean }`.

Content-Type: `application/json`

**401** – Unauthenticated.

Content-Type: `application/json`

**403** – Caller lacks ai_assistant.settings.manage.

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/ai_assistant/settings/allowlist" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/ai_assistant/settings/allowlist`

Upsert per-tenant AI provider/model allowlist

Persists the per-tenant allowlist of providers and models. The runtime intersects this with the env allowlist (`OM_AI_AVAILABLE_*`) at resolution time. Tenant values that fall outside the env allowlist are rejected with `provider_not_in_env_allowlist` / `model_not_in_env_allowlist` 400 codes. Gated by `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "allowedProviders": null
}
```

### Responses

**200** – Allowlist saved. Returns the saved snapshot.

Content-Type: `application/json`

**400** – Validation error or values outside env allowlist.

Content-Type: `application/json`

**401** – Unauthenticated.

Content-Type: `application/json`

**403** – Caller lacks ai_assistant.settings.manage.

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/ai_assistant/settings/allowlist" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"allowedProviders\": null
}"
```

## GET `/ai_assistant/tools`

List available MCP tools filtered by user permissions

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/tools" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ai_assistant/tools/execute`

Execute a specific MCP tool by name

**Tags:** AI Assistant

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ai_assistant/tools/execute" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/usage/daily`

Fetch daily token-usage rollup rows for a date window.

Returns aggregated token-usage data from `ai_token_usage_daily` for the given date window. Tenant-scoped. Optionally filtered by `agentId` and/or `modelId`. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| from | query | any | Required |
| to | query | any | Required |
| agentId | query | any | Optional |
| modelId | query | any | Optional |

### Responses

**200** – Array of daily rollup rows.

Content-Type: `application/json`

**400** – Invalid query parameters.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**500** – Internal failure.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/usage/daily?from=string&to=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/usage/sessions`

List per-session token usage totals for a date window.

Returns aggregated token-usage data grouped by `session_id` from `ai_token_usage_events` for the given date window. Tenant-scoped. Optionally filtered by `agentId`. Paginated via `limit` / `offset`. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| from | query | any | Required |
| to | query | any | Required |
| agentId | query | any | Optional |
| limit | query | any | Required |
| offset | query | any | Required |

### Responses

**200** – Array of session-level usage summaries plus pagination metadata.

Content-Type: `application/json`

**400** – Invalid query parameters.

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**500** – Internal failure.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/usage/sessions?from=string&to=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/ai_assistant/usage/sessions/{sessionId}`

Fetch per-step token usage event rows for a single session.

Returns up to 200 raw `ai_token_usage_events` rows for the given `sessionId`, ordered by `created_at ASC, step_index ASC`. Tenant-scoped. Requires `ai_assistant.settings.manage`.

**Tags:** AI Assistant

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| sessionId | path | any | Required |

### Responses

**200** – Array of per-step event rows for the session.

Content-Type: `application/json`

**400** – Invalid session id (must be a UUID).

Content-Type: `application/json`

**401** – Unauthenticated caller.

Content-Type: `application/json`

**403** – Caller lacks `ai_assistant.settings.manage`.

Content-Type: `application/json`

**404** – No events found for the given session id in the caller's tenant.

Content-Type: `application/json`

**500** – Internal failure.

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/ai_assistant/usage/sessions/:sessionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/api_keys/keys`

Delete API key

Removes an API key by identifier. The key must belong to the current tenant and fall within the requester organization scope.

**Tags:** API Keys

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. API key identifier to delete |

### Responses

**200** – Key deleted successfully

Content-Type: `application/json`

```json
{
  "success": true
}
```

**400** – Missing or invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Organization outside allowed scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Key not found within scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/api_keys/keys?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/api_keys/keys`

List API keys

Returns paginated API keys visible to the current user, including per-key role assignments and organization context.

**Tags:** API Keys

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |

### Responses

**200** – Collection of API keys

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "description": null,
      "keyPrefix": "string",
      "organizationId": null,
      "organizationName": null,
      "createdAt": "string",
      "lastUsedAt": null,
      "expiresAt": null,
      "roles": [
        {
          "id": "string",
          "name": null
        }
      ]
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Tenant context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden by organization scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/api_keys/keys" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/api_keys/keys`

Create API key

Creates a new API key, returning the one-time secret value together with the generated key prefix and scope details.

**Tags:** API Keys

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "description": null,
  "tenantId": null,
  "organizationId": null,
  "roles": [],
  "expiresAt": null
}
```

### Responses

**201** – API key created successfully

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "keyPrefix": "string",
  "tenantId": null,
  "organizationId": null,
  "roles": [
    {
      "id": "string",
      "name": null
    }
  ]
}
```

**400** – Invalid payload or missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Organization outside allowed scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/api_keys/keys" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"tenantId\": null,
  \"organizationId\": null,
  \"roles\": [],
  \"expiresAt\": null
}"
```

## DELETE `/attachments`

Delete attachment

Removes an uploaded attachment and deletes the stored asset.

**Tags:** Attachments

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required |

### Responses

**200** – Attachment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing attachment identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/attachments?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/attachments`

List attachments for a record

Returns uploaded attachments for the given entity record, ordered by newest first.

**Tags:** Attachments

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Required. Entity identifier that owns the attachments |
| recordId | query | any | Required. Record identifier within the entity |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Attachments found for the record

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "url": "string",
      "fileName": "string",
      "fileSize": 1,
      "createdAt": "string",
      "mimeType": null,
      "content": null
    }
  ]
}
```

**400** – Missing entity or record identifiers

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/attachments?entityId=string&recordId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/attachments`

Upload attachment

Uploads a new attachment using multipart form-data and stores metadata for later retrieval.

**Tags:** Attachments

**Requires authentication.**

### Request Body

Content-Type: `multipart/form-data`

```text
entityId=string
recordId=string
file=string
```

### Responses

**200** – Attachment stored successfully

Content-Type: `application/json`

```json
{
  "ok": true,
  "item": {
    "id": "string",
    "url": "string",
    "fileName": "string",
    "fileSize": 1,
    "content": null
  }
}
```

**400** – Payload validation error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Attachment violates field constraints

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: multipart/form-data" \
  -d "{
  \"entityId\": \"string\",
  \"recordId\": \"string\",
  \"file\": \"string\"
}"
```

## GET `/attachments/file/{id}`

Download or serve attachment file

Returns the raw file content for an attachment. Path parameter: {id} - Attachment UUID. Query parameter: ?download=1 - Force file download with Content-Disposition header. Access control is enforced based on partition settings.

**Tags:** Attachments

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – File content with appropriate MIME type

Content-Type: `application/json`

**400** – Missing attachment ID

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized - authentication required for private partitions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment or file not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Partition misconfigured

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/attachments/file/:id" \
  -H "Accept: application/json"
```

## GET `/attachments/image/{id}/{slug}`

Serve image with optional resizing

Returns an image attachment with optional on-the-fly resizing and cropping. Resized images are cached for performance. Only works with image MIME types. Path parameter: {id} - Attachment UUID. Query parameters: ?width=N (1-4000 pixels), ?height=N (1-4000 pixels), ?cropType=cover|contain (resize behavior).

**Tags:** Attachments

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| slug | path | any | Optional |

### Responses

**200** – Binary image content (Content-Type: image/jpeg, image/png, etc.)

Content-Type: `application/json`

**400** – Invalid parameters, missing ID, or non-image attachment

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized - authentication required for private partitions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Image not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Partition misconfigured or image rendering failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/attachments/image/:id/:slug" \
  -H "Accept: application/json"
```

## GET `/attachments/library`

List attachments

Returns paginated list of attachments with optional filtering by search term, partition, and tags. Includes available tags and partitions.

**Tags:** Attachments

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional. Page number for pagination |
| pageSize | query | any | Optional. Number of items per page (max 100) |
| search | query | any | Optional. Search by file name (case-insensitive) |
| partition | query | any | Optional. Filter by partition code |
| tags | query | any | Optional. Filter by tags (comma-separated) |
| sortField | query | any | Optional. Field to sort by |
| sortDir | query | any | Optional. Sort direction |

### Responses

**200** – Attachments list with pagination and metadata

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fileName": "string",
      "fileSize": 1,
      "mimeType": "string",
      "partitionCode": "string",
      "partitionTitle": null,
      "url": null,
      "createdAt": "string",
      "tags": [
        "string"
      ],
      "assignments": [],
      "content": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1,
  "availableTags": [
    "string"
  ],
  "partitions": [
    {
      "code": "string",
      "title": "string",
      "description": null,
      "isPublic": true
    }
  ]
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/attachments/library?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/attachments/library/{id}`

Delete attachment

Permanently deletes an attachment file from storage and database. Emits CRUD side effects.

**Tags:** Attachments

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Attachment deleted successfully

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid attachment ID

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/attachments/library/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/attachments/library/{id}`

Get attachment details

Returns complete details of an attachment including metadata, tags, assignments, and custom fields.

**Tags:** Attachments

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Attachment details

Content-Type: `application/json`

```json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "fileName": "string",
    "fileSize": 1,
    "mimeType": "string",
    "partitionCode": "string",
    "partitionTitle": null,
    "tags": [
      "string"
    ],
    "assignments": [],
    "content": null,
    "customFields": null
  }
}
```

**400** – Invalid attachment ID

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/attachments/library/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/attachments/library/{id}`

Update attachment metadata

Updates attachment tags, assignments, and custom fields. Emits CRUD side effects for indexing and events.

**Tags:** Attachments

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Attachment updated successfully

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload or attachment ID

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to save attributes

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/attachments/library/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## DELETE `/attachments/partitions`

Delete partition

Deletes a partition. Default partitions cannot be deleted. Partitions with existing attachments cannot be deleted.

**Tags:** Attachments

**Requires authentication.**

### Responses

**200** – Partition deleted successfully

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid ID or default partition deletion attempt

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Partitions locked in demo mode

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Partition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Partition in use

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/attachments/partitions`

List all attachment partitions

Returns all configured attachment partitions with storage settings, OCR configuration, and access control settings.

**Tags:** Attachments

**Requires authentication.**

### Responses

**200** – List of partitions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "code": "string",
      "title": "string",
      "description": null,
      "isPublic": true,
      "requiresOcr": true,
      "ocrModel": null,
      "configJson": null,
      "createdAt": null,
      "updatedAt": null,
      "envKey": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/attachments/partitions`

Create new partition

Creates a new attachment partition with specified storage and OCR settings. Requires unique partition code.

**Tags:** Attachments

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "code": "string",
  "title": "string",
  "description": null,
  "ocrModel": null,
  "storageDriver": "local",
  "configJson": null
}
```

### Responses

**201** – Partition created successfully

Content-Type: `application/json`

```json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "code": "string",
    "title": "string",
    "description": null,
    "isPublic": true,
    "requiresOcr": true,
    "ocrModel": null,
    "configJson": null,
    "createdAt": null,
    "updatedAt": null,
    "envKey": "string"
  }
}
```

**400** – Invalid payload or partition code

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Partitions locked in demo mode

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Partition code already exists

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"code\": \"string\",
  \"title\": \"string\",
  \"description\": null,
  \"ocrModel\": null,
  \"storageDriver\": \"local\",
  \"configJson\": null
}"
```

## PUT `/attachments/partitions`

Update partition

Updates an existing partition. Partition code cannot be changed. Title, description, OCR settings, and access control can be modified.

**Tags:** Attachments

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "code": "string",
  "title": "string",
  "description": null,
  "ocrModel": null,
  "storageDriver": "local",
  "configJson": null,
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Partition updated successfully

Content-Type: `application/json`

```json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "code": "string",
    "title": "string",
    "description": null,
    "isPublic": true,
    "requiresOcr": true,
    "ocrModel": null,
    "configJson": null,
    "createdAt": null,
    "updatedAt": null,
    "envKey": "string"
  }
}
```

**400** – Invalid payload or code change attempt

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Partitions locked in demo mode

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Partition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/attachments/partitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"code\": \"string\",
  \"title\": \"string\",
  \"description\": null,
  \"ocrModel\": null,
  \"storageDriver\": \"local\",
  \"configJson\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/attachments/transfer`

Transfer attachments to different record

Transfers one or more attachments from one record to another within the same entity type. Updates attachment assignments and metadata to reflect the new record.

**Tags:** Attachments

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "attachmentIds": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "toRecordId": "string"
}
```

### Responses

**200** – Attachments transferred successfully

Content-Type: `application/json`

```json
{
  "ok": true,
  "updated": 1
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachments not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Attachment model missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/attachments/transfer" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"attachmentIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ],
  \"toRecordId\": \"string\"
}"
```

## GET `/audit_logs/audit-logs/access`

Retrieve access logs

Fetches paginated access audit logs scoped to the authenticated user. Tenant administrators can optionally expand the search to other actors or organizations.

**Tags:** Audit & Action Logs

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| organizationId | query | any | Optional. Limit results to a specific organization |
| actorUserId | query | any | Optional. Filter by actor user id (tenant administrators only) |
| resourceKind | query | any | Optional. Restrict to a resource kind such as `order` or `product` |
| accessType | query | any | Optional. Access type filter, e.g. `read` or `export` |
| page | query | any | Optional. Page number (default 1) |
| pageSize | query | any | Optional. Page size (default 50) |
| limit | query | any | Optional. Explicit maximum number of records when paginating manually |
| before | query | any | Optional. Return logs created before this ISO-8601 timestamp |
| after | query | any | Optional. Return logs created after this ISO-8601 timestamp |

### Responses

**200** – Access logs returned successfully

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "resourceKind": "string",
      "resourceId": "string",
      "accessType": "string",
      "actorUserId": null,
      "actorUserName": null,
      "tenantId": null,
      "tenantName": null,
      "organizationId": null,
      "organizationName": null,
      "fields": [
        "string"
      ],
      "context": null,
      "createdAt": "string"
    }
  ],
  "canViewTenant": true,
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid filters supplied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Caller has no resolved tenant scope and is not a superadmin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/audit_logs/audit-logs/access" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/audit_logs/audit-logs/actions`

Fetch action logs

Returns recent action audit log entries. Tenant administrators can widen the scope to other actors or organizations, and callers can optionally restrict results to undoable actions.

**Tags:** Audit & Action Logs

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| organizationId | query | any | Optional. Limit results to a specific organization |
| actorUserId | query | any | Optional. Filter logs created by specific actor IDs (tenant administrators only). Accepts a single UUID or a comma-separated UUID list. |
| resourceKind | query | any | Optional. Filter by resource kind (e.g., "order", "product") |
| resourceId | query | any | Optional. Filter by resource ID (UUID of the specific record) |
| actionType | query | any | Optional. Filter by action type (`create`, `edit`, `delete`, `assign`). Accepts a single value or a comma-separated list. |
| fieldName | query | any | Optional. Filter to entries where the given field changed. Accepts a single field name or a comma-separated list. |
| includeRelated | query | any | Optional. When `true`, also returns changes to child entities linked via parentResourceKind/parentResourceId |
| includeTotal | query | any | Optional. When `true`, the response includes the filtered total count. |
| undoableOnly | query | any | Optional. When `true`, only undoable actions are returned |
| limit | query | any | Optional. Maximum number of records to return (default 50, max 1000) |
| offset | query | any | Optional. Zero-based record offset for pagination (legacy — prefer page/pageSize) |
| page | query | any | Optional. Page number (default 1) |
| pageSize | query | any | Optional. Page size (default 50, max 200) |
| sortField | query | any | Optional. Sort field: `createdAt`, `user`, `action`, `field`, or `source`. |
| sortDir | query | any | Optional. Sort direction: `asc` or `desc`. |
| before | query | any | Optional. Return actions created before this ISO-8601 timestamp |
| after | query | any | Optional. Return actions created after this ISO-8601 timestamp |

### Responses

**200** – Action logs retrieved successfully

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "commandId": "string",
      "actionLabel": null,
      "executionState": "done",
      "actorUserId": null,
      "actorUserName": null,
      "tenantId": null,
      "tenantName": null,
      "organizationId": null,
      "organizationName": null,
      "resourceKind": null,
      "resourceId": null,
      "parentResourceKind": null,
      "parentResourceId": null,
      "undoToken": null,
      "createdAt": "string",
      "updatedAt": "string",
      "snapshotBefore": null,
      "snapshotAfter": null,
      "changes": null,
      "context": null
    }
  ],
  "canViewTenant": true,
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid filter values

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Caller has no resolved tenant scope and is not a superadmin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/audit_logs/audit-logs/actions?includeRelated=false&includeTotal=false&undoableOnly=false" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/audit_logs/audit-logs/actions/export`

Export action logs as CSV

Returns a CSV attachment containing filtered action audit log entries. Tenant administrators can widen the scope to other actors or organizations.

**Tags:** Audit & Action Logs

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| organizationId | query | any | Optional. Limit results to a specific organization |
| actorUserId | query | any | Optional. Filter logs created by specific actor IDs (tenant administrators only). Accepts a single UUID or a comma-separated UUID list. |
| resourceKind | query | any | Optional. Filter by resource kind (e.g., "order", "product") |
| resourceId | query | any | Optional. Filter by resource ID (UUID of the specific record) |
| actionType | query | any | Optional. Filter by action type (`create`, `edit`, `delete`, `assign`). Accepts a single value or a comma-separated list. |
| fieldName | query | any | Optional. Filter to entries where the given field changed. Accepts a single field name or a comma-separated list. |
| includeRelated | query | any | Optional. When `true`, also returns changes to child entities linked via parentResourceKind/parentResourceId |
| undoableOnly | query | any | Optional. When `true`, only undoable actions are returned |
| limit | query | any | Optional. Maximum number of records to export (default 1000, capped at 1000) |
| sortField | query | any | Optional. Sort field: `createdAt`, `user`, `action`, `field`, or `source`. |
| sortDir | query | any | Optional. Sort direction: `asc` or `desc`. |
| before | query | any | Optional. Return actions created before this ISO-8601 timestamp |
| after | query | any | Optional. Return actions created after this ISO-8601 timestamp |

### Responses

**200** – CSV export generated successfully

Content-Type: `application/json`

```json
{
  "file": "csv"
}
```

**400** – Invalid filter values

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Caller has no resolved tenant scope and is not a superadmin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/audit_logs/audit-logs/actions/export?includeRelated=false&undoableOnly=false" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/audit_logs/audit-logs/actions/redo`

Redo by action log id

Redoes the latest undone command owned by the caller. Requires the action to still be eligible for redo within tenant and organization scope.

**Tags:** Audit & Action Logs

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "logId": "string"
}
```

### Responses

**200** – Redo executed successfully

Content-Type: `application/json`

```json
{
  "ok": true,
  "logId": null,
  "undoToken": null
}
```

**400** – Log not eligible for redo

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Redo blocked by scope checks

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/audit_logs/audit-logs/actions/redo" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"logId\": \"string\"
}"
```

## POST `/audit_logs/audit-logs/actions/undo`

Undo action by token

Replays the undo handler registered for a command. The provided undo token must match the latest undoable log entry accessible to the caller.

**Tags:** Audit & Action Logs

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "undoToken": "string"
}
```

### Responses

**200** – Undo applied successfully

Content-Type: `application/json`

```json
{
  "ok": true,
  "logId": "string"
}
```

**400** – Invalid or unavailable undo token

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Undo blocked by organization or tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Undo deliberately blocked by a beforeUndo command interceptor. The interceptor chooses the status (any 4xx/5xx) and may replace the body.

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/audit_logs/audit-logs/actions/undo" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"undoToken\": \"string\"
}"
```

## GET `/auth/admin/nav`

Resolve backend chrome bootstrap payload

Returns the backend chrome payload available to the authenticated administrator after applying scope, RBAC, role defaults, and personal sidebar preferences.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**200** – Backend chrome payload

Content-Type: `application/json`

```json
{
  "brand": null,
  "groups": [
    {
      "name": "string",
      "items": [
        {
          "href": "string",
          "title": "string"
        }
      ]
    }
  ],
  "settingsSections": [
    {
      "id": "string",
      "label": "string",
      "items": [
        {
          "id": "string",
          "label": "string",
          "href": "string"
        }
      ]
    }
  ],
  "settingsPathPrefixes": [
    "string"
  ],
  "profileSections": [
    {
      "id": "string",
      "label": "string",
      "items": [
        {
          "id": "string",
          "label": "string",
          "href": "string"
        }
      ]
    }
  ],
  "profilePathPrefixes": [
    "string"
  ],
  "grantedFeatures": [
    "string"
  ],
  "roles": [
    "string"
  ],
  "currentOrganization": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/admin/nav" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/autologin`

Auto sign-in using env-configured demo credentials

When OM_AUTOLOGIN_EMAIL / OM_AUTOLOGIN_PASSWORD are configured, signs the visitor in with those credentials and redirects into the app. Intended for single-tenant demo instances only. Falls back to the login page when disabled or misconfigured.

**Tags:** Authentication & Accounts

### Responses

**200** – Success response

Content-Type: `application/json`

**307** – Redirect into the app (or to /login on failure)

Content-Type: `text/html`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/autologin" \
  -H "Accept: application/json"
```

## POST `/auth/feature-check`

Check feature grants for the current user

Evaluates which of the requested features are available to the signed-in user within the active tenant / organization context.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "features": [
    "string"
  ]
}
```

### Responses

**200** – Evaluation result

Content-Type: `application/json`

```json
{
  "ok": true,
  "granted": [
    "string"
  ],
  "userId": "string"
}
```

**400** – Invalid request — features array missing, too large, or contains invalid entries

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/feature-check" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"features\": [
    \"string\"
  ]
}"
```

## GET `/auth/features`

List declared feature flags

Returns all static features contributed by the enabled modules along with their module source.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**200** – Aggregated feature catalog

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "module": "string"
    }
  ],
  "modules": [
    {
      "id": "string",
      "title": "string"
    }
  ]
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/features" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/locale`

Set locale and redirect

Stores the selected locale in a cookie and redirects to a safe local path.

**Tags:** Authentication & Accounts

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| locale | query | any | Required. A locale code this tenant serves — one of the `servable` entries returned by `GET /api/translations/locales`. Codes are canonicalized (`de-AT` → `de`). |
| redirect | query | any | Optional |

### Responses

**200** – Success response

Content-Type: `application/json`

**302** – Locale cookie set and request redirected

Content-Type: `application/json`

**400** – Invalid locale

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/locale?locale=string" \
  -H "Accept: application/json"
```

## POST `/auth/locale`

Set locale

Stores the selected locale in a cookie and returns a JSON success response.

**Tags:** Authentication & Accounts

### Request Body

Content-Type: `application/json`

```json
{
  "locale": "string"
}
```

### Responses

**200** – Locale cookie set

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid locale or malformed request body

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/locale" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"locale\": \"string\"
}"
```

## POST `/auth/login`

Authenticate user credentials

Validates the submitted credentials and issues a bearer token cookie for subsequent API calls.

**Tags:** Authentication & Accounts

### Request Body

Content-Type: `application/x-www-form-urlencoded`

```text
email=user%40example.com&password=string
```

### Responses

**200** – Authentication succeeded

Content-Type: `application/json`

```json
{
  "ok": true,
  "token": "string",
  "redirect": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Invalid credentials

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – User lacks required role

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many login attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=user%40example.com&password=string"
```

## POST `/auth/logout`

Invalidate session and redirect

Clears authentication cookies and redirects the browser to the login page.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

**302** – Redirect to login after successful logout

Content-Type: `text/html`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/logout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/profile`

Get current profile

Returns the email address, display name, and roles for the signed-in user. The display name is null when unset.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**200** – Profile payload

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "name": null,
  "roles": [
    "string"
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/profile" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/auth/profile`

Update current profile

Updates the email address or password for the signed-in user.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Profile updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "email": "user@example.com"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/profile" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/auth/reset`

Send reset email

Requests a password reset email for the given account. The endpoint always returns `ok: true` to avoid leaking account existence.

**Tags:** Authentication & Accounts

### Request Body

Content-Type: `application/x-www-form-urlencoded`

```text
email=user%40example.com
```

### Responses

**200** – Reset email dispatched (or ignored for unknown accounts)

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request origin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Too many password reset requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Password reset email origin is not configured

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/reset" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "email=user%40example.com"
```

## POST `/auth/reset/confirm`

Complete password reset

Validates the reset token and updates the user password.

**Tags:** Authentication & Accounts

### Request Body

Content-Type: `application/x-www-form-urlencoded`

```text
token=string&password=string
```

### Responses

**200** – Password reset succeeded

Content-Type: `application/json`

```json
{
  "ok": true,
  "redirect": "string"
}
```

**400** – Invalid token or payload

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many reset confirmation attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/reset/confirm" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=string&password=string"
```

## POST `/auth/reset/validate`

Check whether a password reset token is still usable

Reports whether a reset token exists, is unused, and has not expired, so the reset page can render a terminal state instead of a form the token can never submit. The token is never consumed and the response never distinguishes unknown, used, and expired tokens.

**Tags:** Authentication & Accounts

### Request Body

Content-Type: `application/x-www-form-urlencoded`

```text
token=string
```

### Responses

**200** – Token state resolved

Content-Type: `application/json`

```json
{
  "ok": true,
  "valid": true
}
```

**429** – Too many token validation attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/reset/validate" \
  -H "Accept: application/json" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=string"
```

## DELETE `/auth/roles`

Delete role

Deletes a role by identifier. Fails when users remain assigned.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. Role identifier |

### Responses

**200** – Role deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Role cannot be deleted

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/auth/roles?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/roles`

List roles

Returns available roles within the current tenant. Super administrators receive visibility across tenants.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| tenantId | query | any | Optional |

### Responses

**200** – Role collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "usersCount": 1,
      "tenantId": null,
      "tenantName": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/roles?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/auth/roles`

Create role

Creates a new role anchored to the caller's tenant. Non-superadmins cannot target another tenant; supplying a foreign `tenantId` is rejected.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string"
}
```

### Responses

**201** – Role created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\"
}"
```

## PUT `/auth/roles`

Update role

Updates mutable fields on an existing role.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Role updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/auth/roles/acl`

Fetch role ACL

Returns the feature and organization assignments associated with a role within the current tenant.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| roleId | query | any | Required |
| tenantId | query | any | Optional |

### Responses

**200** – Role ACL entry

Content-Type: `application/json`

```json
{
  "isSuperAdmin": true,
  "features": [
    "string"
  ],
  "organizations": null,
  "updatedAt": null
}
```

**400** – Invalid role id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/roles/acl?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/auth/roles/acl`

Update role ACL

Replaces the feature list, super admin flag, and optional organization assignments for a role.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "roleId": "00000000-0000-4000-8000-000000000000",
  "organizations": null
}
```

### Responses

**200** – Role ACL updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "sanitized": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient privileges to modify ACL

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/roles/acl" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizations\": null
}"
```

## GET `/auth/session/refresh`

Refresh auth cookie from session token (browser)

Exchanges an existing `session_token` cookie for a fresh JWT auth cookie and redirects the browser.

**Tags:** Authentication & Accounts

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| redirect | query | any | Optional. Absolute or relative URL to redirect after refresh |

### Responses

**200** – Success response

Content-Type: `application/json`

**302** – Redirect to target location when session is valid

Content-Type: `text/html`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/session/refresh" \
  -H "Accept: application/json"
```

## POST `/auth/session/refresh`

Refresh access token (API/mobile)

Exchanges a refresh token for a new JWT access token. Pass the refresh token obtained from login in the request body.

**Tags:** Authentication & Accounts

### Request Body

Content-Type: `application/json`

```json
{
  "refreshToken": "string"
}
```

### Responses

**200** – New access token issued

Content-Type: `application/json`

```json
{
  "ok": true,
  "accessToken": "string",
  "expiresIn": 1
}
```

**400** – Missing refresh token

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Invalid or expired token

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many refresh attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/session/refresh" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"refreshToken\": \"string\"
}"
```

## DELETE `/auth/sidebar/preferences`

Delete a role sidebar variant

Removes the role variant for the current tenant + locale. Idempotent. Requires `auth.sidebar.manage`.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**200** – Variant deleted (or never existed)

Content-Type: `application/json`

```json
{
  "ok": true,
  "scope": {
    "type": "user"
  }
}
```

**400** – Missing roleId query parameter

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing features

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found in current tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/auth/sidebar/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/sidebar/preferences`

Get sidebar preferences

Returns sidebar customization for the current user (default) or the specified role (`?roleId=…`, requires `auth.sidebar.manage`).

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**200** – Current sidebar configuration

Content-Type: `application/json`

```json
{
  "locale": "string",
  "settings": {
    "version": 1,
    "groupOrder": [
      "string"
    ],
    "groupLabels": {
      "key": "string"
    },
    "itemLabels": {
      "key": "string"
    },
    "hiddenItems": [
      "string"
    ],
    "itemOrder": {
      "key": [
        "string"
      ]
    }
  },
  "canApplyToRoles": true,
  "roles": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "hasPreference": true
    }
  ],
  "scope": {
    "type": "user"
  },
  "updatedAt": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing features for role-scope read

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found in current tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/sidebar/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/auth/sidebar/preferences`

Update sidebar preferences

Updates sidebar configuration. With `scope.type === "user"` (default) writes the calling user's personal preferences and may optionally apply the same settings to selected roles via `applyToRoles[]`. With `scope.type === "role"` writes the named role variant directly (requires `auth.sidebar.manage`); `applyToRoles[]` and `clearRoleIds[]` are rejected in this mode.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Preferences saved

Content-Type: `application/json`

```json
{
  "locale": "string",
  "settings": {
    "version": 1,
    "groupOrder": [
      "string"
    ],
    "groupLabels": {
      "key": "string"
    },
    "itemLabels": {
      "key": "string"
    },
    "hiddenItems": [
      "string"
    ],
    "itemOrder": {
      "key": [
        "string"
      ]
    }
  },
  "canApplyToRoles": true,
  "roles": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "hasPreference": true
    }
  ],
  "scope": {
    "type": "user"
  },
  "updatedAt": null,
  "appliedRoles": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "clearedRoles": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing features for role-wide updates

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found in current tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/sidebar/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/auth/sidebar/variants`

List sidebar variants

Returns the named sidebar variants saved by the current user for the current tenant + locale.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Responses

**200** – Variant list

Content-Type: `application/json`

```json
{
  "locale": "string",
  "variants": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "isActive": true,
      "settings": {
        "version": 1,
        "groupOrder": [
          "string"
        ],
        "groupLabels": {
          "key": "string"
        },
        "itemLabels": {
          "key": "string"
        },
        "hiddenItems": [
          "string"
        ],
        "itemOrder": {
          "key": [
            "string"
          ]
        }
      },
      "createdAt": "string",
      "updatedAt": null
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/sidebar/variants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/auth/sidebar/variants`

Create a sidebar variant

Creates a new variant. If `name` is omitted or blank, an auto-name like "My preferences", "My preferences 2", … is assigned.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Variant created

Content-Type: `application/json`

```json
{
  "locale": "string",
  "variant": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "isActive": true,
    "settings": {
      "version": 1,
      "groupOrder": [
        "string"
      ],
      "groupLabels": {
        "key": "string"
      },
      "itemLabels": {
        "key": "string"
      },
      "hiddenItems": [
        "string"
      ],
      "itemOrder": {
        "key": [
          "string"
        ]
      }
    },
    "createdAt": "string",
    "updatedAt": null
  }
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/sidebar/variants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## DELETE `/auth/sidebar/variants/{id}`

Delete a sidebar variant

Soft-deletes the variant (sets deleted_at).

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Variant deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Variant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/auth/sidebar/variants/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/sidebar/variants/{id}`

Get a sidebar variant

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Variant

Content-Type: `application/json`

```json
{
  "locale": "string",
  "variant": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "isActive": true,
    "settings": {
      "version": 1,
      "groupOrder": [
        "string"
      ],
      "groupLabels": {
        "key": "string"
      },
      "itemLabels": {
        "key": "string"
      },
      "hiddenItems": [
        "string"
      ],
      "itemOrder": {
        "key": [
          "string"
        ]
      }
    },
    "createdAt": "string",
    "updatedAt": null
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Variant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/sidebar/variants/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/auth/sidebar/variants/{id}`

Update a sidebar variant

Updates the variant's name, settings, and/or isActive flag. Setting `isActive: true` deactivates other variants in the same scope (only one active per user/tenant/locale).

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Variant updated

Content-Type: `application/json`

```json
{
  "locale": "string",
  "variant": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "isActive": true,
    "settings": {
      "version": 1,
      "groupOrder": [
        "string"
      ],
      "groupLabels": {
        "key": "string"
      },
      "itemLabels": {
        "key": "string"
      },
      "hiddenItems": [
        "string"
      ],
      "itemOrder": {
        "key": [
          "string"
        ]
      }
    },
    "createdAt": "string",
    "updatedAt": null
  }
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Variant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/sidebar/variants/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## DELETE `/auth/users`

Delete user

Deletes a user by identifier. Rejected when the target is the last active holder of a protected role in the tenant. Undo support is provided via the command bus.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. User identifier |

### Responses

**200** – User deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – User cannot be deleted, or is the last active holder of a protected role

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/auth/users?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/auth/users`

List users

Returns users for the effective selected tenant and organization scope. Search matches email, organization name, and role name. Super administrators may scope the response via the topbar context, organization filters, or role filters. Pass scopeToActiveOrganization=1 to restrict results to the caller's active organization (used by recipient/assignee pickers so suggestions stay within the org that owns the resulting record). Pass ids=<uuid>,<uuid> (max 100) to resolve a known set of users in one request, for example to label a list of foreign keys; it intersects with id and roleId, and a supplied ids value that contains no valid identifier matches nothing.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated user identifiers, at most 100 |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| name | query | any | Optional |
| organizationId | query | any | Optional |
| scopeToActiveOrganization | query | any | Optional |
| roleIds | query | any | Optional |

### Responses

**200** – User collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "user@example.com",
      "name": null,
      "organizationId": null,
      "organizationName": null,
      "tenantId": null,
      "tenantName": null,
      "roles": [
        "string"
      ],
      "isConfirmed": true,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/users?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/auth/users`

Create user

Creates a new confirmed user within the specified organization, optional display name, and optional roles.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "name": null,
  "organizationId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – User created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload or duplicate email

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Attempted to assign privileged roles

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/users" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"name\": null,
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/auth/users`

Update user

Updates profile fields including display name, organization assignment, credentials, or role memberships. A destination organization must be within the caller's descendant-expanded organization scope. Retained and newly assigned roles must belong to the destination tenant and be grantable by the caller. Setting isConfirmed=false deactivates the account: the user can no longer sign in and every active session is revoked; isConfirmed=true reactivates it. A tenant cannot drop below a protected role's minimum active holder count, so revoking the role from, deactivating, moving, or deleting the last active administrator is rejected.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "name": null
}
```

### Responses

**200** – User updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload, duplicate email, or the update would remove the last active holder of a protected role

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Destination organization is outside caller scope, or a retained or assigned role is not grantable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – User or destination organization not found in the caller tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/users" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": null
}"
```

## GET `/auth/users/acl`

Fetch user ACL

Returns custom ACL overrides for a user, scoped to the requested tenant when supplied and to the actor or target user tenant otherwise.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| userId | query | any | Required |
| tenantId | query | any | Optional |

### Responses

**200** – User ACL entry

Content-Type: `application/json`

```json
{
  "hasCustomAcl": true,
  "isSuperAdmin": true,
  "features": [
    "string"
  ],
  "organizations": null,
  "updatedAt": null
}
```

**400** – Invalid user id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient privileges for the requested tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/users/acl?userId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/auth/users/acl`

Update user ACL

Updates a per-user ACL override. Omitted super admin, feature, and organization fields preserve their stored values. Authorization evaluates the merged ACL, so a partial request returns 403 when a preserved grant is outside the actor's grantable ACL. An organization-scoped non-super-admin override requires at least one feature grant.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "userId": "00000000-0000-4000-8000-000000000000",
  "organizations": null
}
```

### Responses

**200** – User ACL updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "sanitized": true
}
```

**400** – Invalid payload or unresolved tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient privileges to modify ACL

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/auth/users/acl" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"userId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizations\": null
}"
```

## GET `/auth/users/consents`

List user consents

Returns all consent records for a given user, with integrity verification status.

**Tags:** Auth

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| userId | query | any | Required |

### Responses

**200** – Consent list returned

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/auth/users/consents?userId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/auth/users/resend-invite`

Resend invitation email

Resends the invitation email to a user who has not yet set up their password. Generates a new 48-hour setup token and invalidates prior tokens.

**Tags:** Authentication & Accounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Invite email sent

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request origin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – User already has a password

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Validation error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Rate limit exceeded

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Invitation email origin is not configured

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/auth/users/resend-invite" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/business_rules/execute`

Execute rules for given context

Manually executes applicable business rules for the specified entity type, event, and data. Supports dry-run mode to test rules without executing actions.

**Tags:** Business Rules

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityType": "string",
  "dryRun": false
}
```

### Responses

**200** – Rules executed successfully

Content-Type: `application/json`

```json
{
  "allowed": true,
  "executedRules": [
    {
      "ruleId": "string",
      "ruleName": "string",
      "conditionResult": true,
      "executionTime": 1
    }
  ],
  "totalExecutionTime": 1
}
```

**400** – Invalid request payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Execution error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/business_rules/execute" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\",
  \"dryRun\": false
}"
```

## POST `/business_rules/execute/{ruleId}`

Execute a specific rule by its database UUID

Directly executes a specific business rule identified by its UUID, bypassing the normal entityType/eventType discovery mechanism. Useful for workflows and targeted rule execution.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| ruleId | path | any | Required. The database UUID of the business rule to execute |

### Request Body

Content-Type: `application/json`

```json
{
  "dryRun": false
}
```

### Responses

**200** – Rule executed successfully

Content-Type: `application/json`

```json
{
  "success": true,
  "ruleId": "string",
  "ruleName": "string",
  "conditionResult": true,
  "actionsExecuted": null,
  "executionTime": 1
}
```

**400** – Invalid request payload or rule ID

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Rule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Execution error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/business_rules/execute/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"dryRun\": false
}"
```

## GET `/business_rules/logs`

List rule execution logs

Returns rule execution history for the current tenant and organization with filtering and pagination. Useful for audit trails and debugging.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| ruleId | query | any | Optional |
| entityId | query | any | Optional |
| entityType | query | any | Optional |
| executionResult | query | any | Optional |
| executedBy | query | any | Optional |
| executedAtFrom | query | any | Optional |
| executedAtTo | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Rule execution logs collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "ruleId": "string",
      "ruleName": "string",
      "ruleType": "string",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "entityType": "string",
      "executionResult": "SUCCESS",
      "inputContext": null,
      "outputContext": null,
      "errorMessage": null,
      "executionTimeMs": 1,
      "executedAt": "string",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": null,
      "executedBy": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/logs?page=1&pageSize=50&sortDir=desc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/business_rules/logs/{id}`

Get execution log detail

Returns detailed information about a specific rule execution, including full context and results.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Log entry details

Content-Type: `application/json`

```json
{
  "id": "string",
  "rule": {
    "id": "00000000-0000-4000-8000-000000000000",
    "ruleId": "string",
    "ruleName": "string",
    "ruleType": "string",
    "entityType": "string"
  },
  "entityId": "00000000-0000-4000-8000-000000000000",
  "entityType": "string",
  "executionResult": "SUCCESS",
  "inputContext": null,
  "outputContext": null,
  "errorMessage": null,
  "executionTimeMs": 1,
  "executedAt": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": null,
  "executedBy": null
}
```

**400** – Invalid log id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Log entry not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/logs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/business_rules/openmercato-call-options`

List OpenMercato call action options

Returns executable Open Mercato API endpoint options and safe API key profile metadata for business-rule actions.

**Tags:** Business Rules

**Requires authentication.**

### Responses

**200** – OpenMercato call options

Content-Type: `application/json`

```json
{
  "endpoints": [
    {
      "id": "string",
      "path": "string",
      "method": "GET",
      "label": "string",
      "summary": null,
      "operationId": null
    }
  ],
  "apiKeys": [
    {
      "id": "string",
      "name": "string",
      "keyPrefix": "string",
      "organizationId": null,
      "organizationName": null,
      "roles": [
        {
          "id": "string",
          "name": null
        }
      ]
    }
  ]
}
```

**400** – Tenant context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing required features

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/openmercato-call-options" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/business_rules/rules`

Delete business rule

Soft deletes a business rule by identifier.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. Business rule identifier |

### Responses

**200** – Business rule deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Business rule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/business_rules/rules?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/business_rules/rules`

List business rules

Returns business rules for the current tenant and organization with filtering and pagination.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| ruleId | query | any | Optional |
| ruleType | query | any | Optional |
| entityType | query | any | Optional |
| eventType | query | any | Optional |
| enabled | query | any | Optional |
| ruleCategory | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Business rules collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "ruleId": "string",
      "ruleName": "string",
      "description": null,
      "ruleType": "GUARD",
      "ruleCategory": null,
      "entityType": "string",
      "eventType": null,
      "enabled": true,
      "priority": 1,
      "version": 1,
      "effectiveFrom": null,
      "effectiveTo": null,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/rules?page=1&pageSize=50&sortDir=desc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/business_rules/rules`

Create business rule

Creates a new business rule for the current tenant and organization.

**Tags:** Business Rules

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "ruleId": "string",
  "ruleName": "string",
  "description": null,
  "ruleType": "GUARD",
  "ruleCategory": null,
  "entityType": "string",
  "eventType": null,
  "enabled": true,
  "priority": 100,
  "version": 1,
  "effectiveFrom": null,
  "effectiveTo": null,
  "tenantId": "string",
  "organizationId": "string",
  "createdBy": null,
  "conditionExpression": null,
  "successActions": null,
  "failureActions": null
}
```

### Responses

**201** – Business rule created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/business_rules/rules" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"ruleId\": \"string\",
  \"ruleName\": \"string\",
  \"description\": null,
  \"ruleType\": \"GUARD\",
  \"ruleCategory\": null,
  \"entityType\": \"string\",
  \"eventType\": null,
  \"enabled\": true,
  \"priority\": 100,
  \"version\": 1,
  \"effectiveFrom\": null,
  \"effectiveTo\": null,
  \"tenantId\": \"string\",
  \"organizationId\": \"string\",
  \"createdBy\": null,
  \"conditionExpression\": null,
  \"successActions\": null,
  \"failureActions\": null
}"
```

## PUT `/business_rules/rules`

Update business rule

Updates an existing business rule.

**Tags:** Business Rules

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "description": null,
  "ruleCategory": null,
  "eventType": null,
  "enabled": true,
  "priority": 100,
  "version": 1,
  "effectiveFrom": null,
  "effectiveTo": null,
  "conditionExpression": null,
  "successActions": null,
  "failureActions": null,
  "id": "string"
}
```

### Responses

**200** – Business rule updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Business rule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/business_rules/rules" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"ruleCategory\": null,
  \"eventType\": null,
  \"enabled\": true,
  \"priority\": 100,
  \"version\": 1,
  \"effectiveFrom\": null,
  \"effectiveTo\": null,
  \"conditionExpression\": null,
  \"successActions\": null,
  \"failureActions\": null,
  \"id\": \"string\"
}"
```

## GET `/business_rules/rules/{id}`

Fetch business rule by ID

Returns complete details of a business rule including conditions and actions.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Business rule detail

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "ruleId": "string",
  "ruleName": "string",
  "description": null,
  "ruleType": "GUARD",
  "ruleCategory": null,
  "entityType": "string",
  "eventType": null,
  "successActions": null,
  "failureActions": null,
  "enabled": true,
  "priority": 1,
  "version": 1,
  "effectiveFrom": null,
  "effectiveTo": null,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "createdBy": null,
  "updatedBy": null,
  "createdAt": "string",
  "updatedAt": "string"
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Business rule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/rules/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/business_rules/sets`

Delete rule set

Soft deletes a rule set by identifier.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. Rule set identifier |

### Responses

**200** – Rule set deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Rule set not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/business_rules/sets?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/business_rules/sets`

List rule sets

Returns rule sets for the current tenant and organization with filtering and pagination.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| setId | query | any | Optional |
| enabled | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Rule sets collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "setId": "string",
      "setName": "string",
      "description": null,
      "enabled": true,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdBy": null,
      "updatedBy": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/sets?page=1&pageSize=50&sortDir=asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/business_rules/sets`

Create rule set

Creates a new rule set for organizing business rules.

**Tags:** Business Rules

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "setId": "string",
  "setName": "string",
  "description": null,
  "enabled": true,
  "tenantId": "string",
  "organizationId": "string",
  "createdBy": null
}
```

### Responses

**201** – Rule set created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/business_rules/sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"setId\": \"string\",
  \"setName\": \"string\",
  \"description\": null,
  \"enabled\": true,
  \"tenantId\": \"string\",
  \"organizationId\": \"string\",
  \"createdBy\": null
}"
```

## PUT `/business_rules/sets`

Update rule set

Updates an existing rule set.

**Tags:** Business Rules

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "description": null,
  "enabled": true,
  "id": "string"
}
```

### Responses

**200** – Rule set updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Rule set not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/business_rules/sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"enabled\": true,
  \"id\": \"string\"
}"
```

## GET `/business_rules/sets/{id}`

Get rule set detail

Returns detailed information about a specific rule set, including all member rules.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Rule set details

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "setId": "string",
  "setName": "string",
  "description": null,
  "enabled": true,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "createdBy": null,
  "updatedBy": null,
  "createdAt": "string",
  "updatedAt": "string",
  "members": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "ruleId": "00000000-0000-4000-8000-000000000000",
      "ruleName": "string",
      "ruleType": "string",
      "sequence": 1,
      "enabled": true
    }
  ]
}
```

**400** – Invalid rule set id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Rule set not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/business_rules/sets/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/business_rules/sets/{id}/members`

Remove rule from set

Removes a business rule from a rule set (hard delete).

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| memberId | query | any | Required. Member identifier |

### Responses

**200** – Member removed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Member not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/business_rules/sets/:id/members?memberId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/business_rules/sets/{id}/members`

Add rule to set

Adds a business rule to a rule set with specified sequence and enabled state.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "ruleId": "00000000-0000-4000-8000-000000000000",
  "sequence": 0,
  "enabled": true
}
```

### Responses

**201** – Member added

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Rule set or rule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Rule already in set

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/business_rules/sets/:id/members" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"ruleId\": \"00000000-0000-4000-8000-000000000000\",
  \"sequence\": 0,
  \"enabled\": true
}"
```

## PUT `/business_rules/sets/{id}/members`

Update set member

Updates sequence or enabled state of a rule set member.

**Tags:** Business Rules

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "memberId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Member updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Member not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/business_rules/sets/:id/members" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"memberId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/catalog/bulk-delete`

Start bulk deleting catalog products

**Tags:** Product Catalog

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/bulk-delete" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/catalog/categories`

Delete category

Deletes a category by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Category deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/categories" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/categories`

List categories

Returns a paginated collection of categories scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| view | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| status | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated categories

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "slug": null,
      "description": null,
      "parentId": null,
      "parentName": null,
      "depth": 1,
      "treePath": "string",
      "pathLabel": "string",
      "childCount": 1,
      "descendantCount": 1,
      "isActive": true,
      "updatedAt": null,
      "organizationId": null,
      "tenantId": "00000000-0000-4000-8000-000000000000"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/categories?view=manage&page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/categories`

Create category

Creates a new product category.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "slug": null,
  "parentId": null
}
```

### Responses

**201** – Category created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/categories" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"slug\": null,
  \"parentId\": null
}"
```

## PUT `/catalog/categories`

Update category

Updates an existing category by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "slug": null,
  "parentId": null
}
```

### Responses

**200** – Category updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/categories" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"slug\": null,
  \"parentId\": null
}"
```

## GET `/catalog/dictionaries/{key}`

Get dictionary entries by key

Returns dictionary entries for a specific key (e.g., currency, unit).

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| key | path | any | Required |

### Responses

**200** – Dictionary entries

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "entries": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": "string",
      "color": null,
      "icon": null
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/dictionaries/:key" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/catalog/offers`

Delete offer

Deletes an offer by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Offer deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/offers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/offers`

List offers

Returns a paginated collection of offers scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| productId | query | any | Optional |
| channelId | query | any | Optional |
| channelIds | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |
| withDeleted | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated offers

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "productId": null,
      "organizationId": null,
      "tenantId": null,
      "channelId": null,
      "title": "string",
      "description": null,
      "defaultMediaId": null,
      "defaultMediaUrl": null,
      "metadata": null,
      "isActive": null,
      "createdAt": null,
      "updatedAt": null,
      "product": null,
      "productChannelPrice": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/offers?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/offers`

Create offer

Creates a new offer linking a product to a sales channel.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "channelId": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "defaultMediaId": null,
  "defaultMediaUrl": null,
  "productId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Offer created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/offers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"channelId\": \"00000000-0000-4000-8000-000000000000\",
  \"title\": \"string\",
  \"defaultMediaId\": null,
  \"defaultMediaUrl\": null,
  \"productId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/catalog/offers`

Update offer

Updates an existing offer by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "defaultMediaId": null,
  "defaultMediaUrl": null
}
```

### Responses

**200** – Offer updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/offers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"defaultMediaId\": null,
  \"defaultMediaUrl\": null
}"
```

## DELETE `/catalog/option-schemas`

Delete option schema

Deletes an option schema by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Option Schema deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/option-schemas" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/option-schemas`

List option schemas

Returns a paginated collection of option schemas scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |
| withDeleted | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated option schemas

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "code": null,
      "description": null,
      "schema": null,
      "metadata": null,
      "is_active": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/option-schemas?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/option-schemas`

Create option schema

Creates a new option schema template for product configurations.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "schema": {
    "options": [
      {
        "code": "string",
        "label": "string",
        "inputType": "select"
      }
    ]
  }
}
```

### Responses

**201** – Option Schema created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/option-schemas" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"schema\": {
    \"options\": [
      {
        \"code\": \"string\",
        \"label\": \"string\",
        \"inputType\": \"select\"
      }
    ]
  }
}"
```

## PUT `/catalog/option-schemas`

Update option schema

Updates an existing option schema by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Option Schema updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/option-schemas" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/catalog/price-kinds`

Delete price kind

Deletes a price kind by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Price Kind deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/price-kinds" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/price-kinds`

List price kinds

Returns a paginated collection of price kinds scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| isPromotion | query | any | Optional |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated price kinds

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "organization_id": null,
      "tenant_id": null,
      "code": "string",
      "title": "string",
      "display_mode": null,
      "currency_code": null,
      "is_promotion": null,
      "is_active": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/price-kinds?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/price-kinds`

Create price kind

Creates a new price kind for categorizing product prices.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "code": "string",
  "title": "string",
  "displayMode": "excluding-tax"
}
```

### Responses

**201** – Price Kind created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/price-kinds" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"code\": \"string\",
  \"title\": \"string\",
  \"displayMode\": \"excluding-tax\"
}"
```

## PUT `/catalog/price-kinds`

Update price kind

Updates an existing price kind by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "displayMode": "excluding-tax"
}
```

### Responses

**200** – Price Kind updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/price-kinds" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"displayMode\": \"excluding-tax\"
}"
```

## DELETE `/catalog/prices`

Delete price

Deletes a price by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Price deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/prices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/prices`

List prices

Returns a paginated collection of prices scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| productId | query | any | Optional |
| variantId | query | any | Optional |
| offerId | query | any | Optional |
| channelId | query | any | Optional |
| currencyCode | query | any | Optional |
| priceKindId | query | any | Optional |
| kind | query | any | Optional |
| userId | query | any | Optional |
| userGroupId | query | any | Optional |
| customerId | query | any | Optional |
| customerGroupId | query | any | Optional |
| quantity | query | any | Optional |
| quantityUnit | query | any | Optional |
| withDeleted | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated prices

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "product_id": null,
      "variant_id": null,
      "offer_id": null,
      "currency_code": null,
      "price_kind_id": null,
      "kind": null,
      "min_quantity": null,
      "max_quantity": null,
      "unit_price_net": null,
      "unit_price_gross": null,
      "tax_rate": null,
      "tax_amount": null,
      "channel_id": null,
      "user_id": null,
      "user_group_id": null,
      "customer_id": null,
      "customer_group_id": null,
      "metadata": null,
      "starts_at": null,
      "ends_at": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/prices?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/prices`

Create price

Creates a new price entry for a product or variant.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string",
  "priceKindId": "00000000-0000-4000-8000-000000000000",
  "taxRateId": null
}
```

### Responses

**201** – Price created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/prices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\",
  \"priceKindId\": \"00000000-0000-4000-8000-000000000000\",
  \"taxRateId\": null
}"
```

## PUT `/catalog/prices`

Update price

Updates an existing price by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "taxRateId": null
}
```

### Responses

**200** – Price updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/prices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"taxRateId\": null
}"
```

## GET `/catalog/product-media`

List product media

Returns a list of media attachments for a specific product.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| productId | query | any | Required |

### Responses

**200** – List of product media

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fileName": "string",
      "url": "string",
      "thumbnailUrl": "string"
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/product-media?productId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/catalog/product-unit-conversions`

Delete product unit conversion

Deletes a product unit conversion by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Product unit conversion deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/product-unit-conversions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/product-unit-conversions`

List product unit conversions

Returns a paginated collection of product unit conversions scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| productId | query | any | Optional |
| unitCode | query | any | Optional |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated product unit conversions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "product_id": "00000000-0000-4000-8000-000000000000",
      "unit_code": "string",
      "to_base_factor": 1,
      "sort_order": null,
      "is_active": null,
      "metadata": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/product-unit-conversions?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/product-unit-conversions`

Create product unit conversion

Creates a product unit conversion.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "productId": "00000000-0000-4000-8000-000000000000",
  "unitCode": "string",
  "toBaseFactor": 1
}
```

### Responses

**201** – Product unit conversion created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/product-unit-conversions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"productId\": \"00000000-0000-4000-8000-000000000000\",
  \"unitCode\": \"string\",
  \"toBaseFactor\": 1
}"
```

## PUT `/catalog/product-unit-conversions`

Update product unit conversion

Updates an existing product unit conversion by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Product unit conversion updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/product-unit-conversions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/catalog/products`

Delete product

Deletes a product by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Product deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/products" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/products`

List products

Returns a paginated collection of products scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| status | query | any | Optional |
| isActive | query | any | Optional |
| configurable | query | any | Optional |
| productType | query | any | Optional |
| channelIds | query | any | Optional |
| channelId | query | any | Optional |
| categoryIds | query | any | Optional |
| tagIds | query | any | Optional |
| offerId | query | any | Optional |
| userId | query | any | Optional |
| userGroupId | query | any | Optional |
| customerId | query | any | Optional |
| customerGroupId | query | any | Optional |
| quantity | query | any | Optional |
| quantityUnit | query | any | Optional |
| priceDate | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |
| customFieldset | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated products

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "subtitle": null,
      "description": null,
      "sku": null,
      "handle": null,
      "product_type": null,
      "status_entry_id": null,
      "primary_currency_code": null,
      "default_unit": null,
      "default_sales_unit": null,
      "default_sales_unit_quantity": null,
      "uom_rounding_scale": null,
      "uom_rounding_mode": null,
      "unit_price_enabled": null,
      "unit_price_reference_unit": null,
      "unit_price_base_quantity": null,
      "default_media_id": null,
      "default_media_url": null,
      "weight_value": null,
      "weight_unit": null,
      "dimensions": null,
      "is_configurable": null,
      "is_active": null,
      "country_of_origin_code": null,
      "pkwiu_code": null,
      "cn_code": null,
      "hs_code": null,
      "tax_classification_code": null,
      "gtu_codes": null,
      "age_min": null,
      "is_excise_good": null,
      "excise_category": null,
      "requires_prescription": null,
      "hazmat_class": null,
      "un_number": null,
      "hazmat_packing_group": null,
      "contains_lithium_battery": null,
      "launch_at": null,
      "end_of_life_at": null,
      "available_from": null,
      "available_until": null,
      "min_order_qty": null,
      "max_order_qty": null,
      "order_qty_increment": null,
      "requires_shipping": null,
      "is_quote_only": null,
      "seo_title": null,
      "seo_description": null,
      "canonical_url": null,
      "metadata": null,
      "custom_fieldset_code": null,
      "option_schema_id": null,
      "created_at": null,
      "updated_at": null,
      "pricing": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/products?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/products`

Create product

Creates a new product in the catalog.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "sku": null,
  "taxRateId": null,
  "taxRate": null,
  "productType": "simple",
  "defaultUnit": null,
  "defaultSalesUnit": null,
  "unitPriceReferenceUnit": null,
  "defaultMediaId": null,
  "defaultMediaUrl": null,
  "weightValue": null,
  "weightUnit": null,
  "dimensions": null,
  "optionSchemaId": null,
  "customFieldsetCode": null,
  "countryOfOriginCode": null,
  "pkwiuCode": null,
  "cnCode": null,
  "hsCode": null,
  "taxClassificationCode": null,
  "gtuCodes": null,
  "ageMin": null,
  "exciseCategory": null,
  "hazmatClass": null,
  "unNumber": null,
  "hazmatPackingGroup": null,
  "launchAt": null,
  "endOfLifeAt": null,
  "availableFrom": null,
  "availableUntil": null,
  "minOrderQty": null,
  "maxOrderQty": null,
  "orderQtyIncrement": null,
  "seoTitle": null,
  "seoDescription": null,
  "canonicalUrl": null
}
```

### Responses

**201** – Product created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/products" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"title\": \"string\",
  \"sku\": null,
  \"taxRateId\": null,
  \"taxRate\": null,
  \"productType\": \"simple\",
  \"defaultUnit\": null,
  \"defaultSalesUnit\": null,
  \"unitPriceReferenceUnit\": null,
  \"defaultMediaId\": null,
  \"defaultMediaUrl\": null,
  \"weightValue\": null,
  \"weightUnit\": null,
  \"dimensions\": null,
  \"optionSchemaId\": null,
  \"customFieldsetCode\": null,
  \"countryOfOriginCode\": null,
  \"pkwiuCode\": null,
  \"cnCode\": null,
  \"hsCode\": null,
  \"taxClassificationCode\": null,
  \"gtuCodes\": null,
  \"ageMin\": null,
  \"exciseCategory\": null,
  \"hazmatClass\": null,
  \"unNumber\": null,
  \"hazmatPackingGroup\": null,
  \"launchAt\": null,
  \"endOfLifeAt\": null,
  \"availableFrom\": null,
  \"availableUntil\": null,
  \"minOrderQty\": null,
  \"maxOrderQty\": null,
  \"orderQtyIncrement\": null,
  \"seoTitle\": null,
  \"seoDescription\": null,
  \"canonicalUrl\": null
}"
```

## PUT `/catalog/products`

Update product

Updates an existing product by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "sku": null,
  "taxRateId": null,
  "taxRate": null,
  "defaultUnit": null,
  "defaultSalesUnit": null,
  "unitPriceReferenceUnit": null,
  "defaultMediaId": null,
  "defaultMediaUrl": null,
  "weightValue": null,
  "weightUnit": null,
  "dimensions": null,
  "optionSchemaId": null,
  "customFieldsetCode": null,
  "countryOfOriginCode": null,
  "pkwiuCode": null,
  "cnCode": null,
  "hsCode": null,
  "taxClassificationCode": null,
  "gtuCodes": null,
  "ageMin": null,
  "exciseCategory": null,
  "hazmatClass": null,
  "unNumber": null,
  "hazmatPackingGroup": null,
  "launchAt": null,
  "endOfLifeAt": null,
  "availableFrom": null,
  "availableUntil": null,
  "minOrderQty": null,
  "maxOrderQty": null,
  "orderQtyIncrement": null,
  "seoTitle": null,
  "seoDescription": null,
  "canonicalUrl": null
}
```

### Responses

**200** – Product updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/products" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"sku\": null,
  \"taxRateId\": null,
  \"taxRate\": null,
  \"defaultUnit\": null,
  \"defaultSalesUnit\": null,
  \"unitPriceReferenceUnit\": null,
  \"defaultMediaId\": null,
  \"defaultMediaUrl\": null,
  \"weightValue\": null,
  \"weightUnit\": null,
  \"dimensions\": null,
  \"optionSchemaId\": null,
  \"customFieldsetCode\": null,
  \"countryOfOriginCode\": null,
  \"pkwiuCode\": null,
  \"cnCode\": null,
  \"hsCode\": null,
  \"taxClassificationCode\": null,
  \"gtuCodes\": null,
  \"ageMin\": null,
  \"exciseCategory\": null,
  \"hazmatClass\": null,
  \"unNumber\": null,
  \"hazmatPackingGroup\": null,
  \"launchAt\": null,
  \"endOfLifeAt\": null,
  \"availableFrom\": null,
  \"availableUntil\": null,
  \"minOrderQty\": null,
  \"maxOrderQty\": null,
  \"orderQtyIncrement\": null,
  \"seoTitle\": null,
  \"seoDescription\": null,
  \"canonicalUrl\": null
}"
```

## GET `/catalog/settings`

Read catalog settings

**Tags:** Catalog

**Requires authentication.**

### Responses

**200** – Catalog settings

Content-Type: `application/json`

```json
{
  "unitPriceDisplayEnabled": true
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/catalog/settings`

Update catalog settings

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "unitPriceDisplayEnabled": true
}
```

### Responses

**200** – Updated catalog settings

Content-Type: `application/json`

```json
{
  "unitPriceDisplayEnabled": true
}
```

**400** – Invalid request body

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"unitPriceDisplayEnabled\": true
}"
```

## GET `/catalog/tags`

List product tags

Returns a paginated collection of product tags scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| search | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Paginated product tags

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "slug": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/tags?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/catalog/variants`

Delete variant

Deletes a variant by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Variant deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/catalog/variants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/catalog/variants`

List variants

Returns a paginated collection of variants scoped to the authenticated organization.

**Tags:** Catalog

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| productId | query | any | Optional |
| sku | query | any | Optional |
| isActive | query | any | Optional |
| isDefault | query | any | Optional |
| withDeleted | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated variants

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "product_id": null,
      "name": null,
      "sku": null,
      "barcode": null,
      "gtin_type": null,
      "hs_code": null,
      "status_entry_id": null,
      "is_default": null,
      "is_active": null,
      "weight_value": null,
      "weight_unit": null,
      "dimensions": null,
      "metadata": null,
      "option_values": null,
      "custom_fieldset_code": null,
      "default_media_id": null,
      "default_media_url": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/catalog/variants?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/catalog/variants`

Create variant

Creates a new product variant.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "productId": "00000000-0000-4000-8000-000000000000",
  "gtinType": null,
  "hsCode": null,
  "defaultMediaId": null,
  "defaultMediaUrl": null,
  "taxRateId": null,
  "taxRate": null,
  "customFieldsetCode": null
}
```

### Responses

**201** – Variant created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/catalog/variants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"productId\": \"00000000-0000-4000-8000-000000000000\",
  \"gtinType\": null,
  \"hsCode\": null,
  \"defaultMediaId\": null,
  \"defaultMediaUrl\": null,
  \"taxRateId\": null,
  \"taxRate\": null,
  \"customFieldsetCode\": null
}"
```

## PUT `/catalog/variants`

Update variant

Updates an existing variant by id.

**Tags:** Catalog

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "gtinType": null,
  "hsCode": null,
  "defaultMediaId": null,
  "defaultMediaUrl": null,
  "taxRateId": null,
  "taxRate": null,
  "customFieldsetCode": null
}
```

### Responses

**200** – Variant updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/catalog/variants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"gtinType\": null,
  \"hsCode\": null,
  \"defaultMediaId\": null,
  \"defaultMediaUrl\": null,
  \"taxRateId\": null,
  \"taxRate\": null,
  \"customFieldsetCode\": null
}"
```

## GET `/channel_discord/ai-auto-reply/channels`

List the AI auto-reply state of every Discord channel in scope

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**200** – One row per Discord channel the caller may see

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/channel_discord/ai-auto-reply/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/channel_discord/channels/{id}/ai-auto-reply`

Read a Discord channel's AI auto-reply configuration

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Current settings plus the agents this channel may be pointed at

Content-Type: `application/json`

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found, not a Discord channel in scope, or not the caller’s to see

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/channel_discord/channels/:id/ai-auto-reply" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/channel_discord/channels/{id}/ai-auto-reply`

Update a Discord channel's AI auto-reply configuration

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Settings stored

Content-Type: `application/json`

**400** – Invalid payload, AI module absent, agent not eligible, or the auto-reply principal lacks the agent’s required features

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found, or not a Discord channel in this scope

Content-Type: `application/json`

**409** – The channel changed since the form was loaded

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/channel_discord/channels/:id/ai-auto-reply" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/channel_discord/interactions`

Verify (Ed25519, fail-closed) and dispatch a Discord interaction

**Tags:** ChannelDiscord

### Responses

**200** – Verified interaction — PONG for the handshake, a deferred ack for a dispatched slash command / component / modal submission, an empty autocomplete result, or an ephemeral message when the interaction cannot be dispatched

Content-Type: `application/json`

**400** – Verified but malformed interaction body

Content-Type: `application/json`

**401** – Signature verification failed against every candidate channel, or the signed timestamp is outside the replay window

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/channel_discord/interactions" \
  -H "Accept: application/json"
```

## GET `/checkout/links`

GET /checkout/links

**Tags:** Checkout

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/links" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/checkout/links`

POST /checkout/links

**Tags:** Checkout

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/checkout/links" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/checkout/links/{id}`

DELETE /checkout/links/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/checkout/links/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/links/{id}`

GET /checkout/links/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/links/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/checkout/links/{id}`

PUT /checkout/links/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/checkout/links/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/pay/{slug}`

GET /checkout/pay/{slug}

**Tags:** Checkout

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| slug | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/pay/:slug" \
  -H "Accept: application/json"
```

## GET `/checkout/pay/{slug}/status/{transactionId}`

GET /checkout/pay/{slug}/status/{transactionId}

**Tags:** Checkout

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| slug | path | any | Required |
| transactionId | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/pay/:slug/status/:transactionId" \
  -H "Accept: application/json"
```

## POST `/checkout/pay/{slug}/submit`

POST /checkout/pay/{slug}/submit

**Tags:** Checkout

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| slug | path | any | Required |

### Responses

**201** – Success response

Content-Type: `application/json`

**429** – Too many payment attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Rate limiting could not be enforced, so the payment was rejected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/checkout/pay/:slug/submit" \
  -H "Accept: application/json"
```

## POST `/checkout/pay/{slug}/verify-password`

POST /checkout/pay/{slug}/verify-password

**Tags:** Checkout

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| slug | path | any | Required |

### Responses

**201** – Success response

Content-Type: `application/json`

**429** – Too many password attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Rate limiting could not be enforced, so the attempt was rejected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/checkout/pay/:slug/verify-password" \
  -H "Accept: application/json"
```

## GET `/checkout/templates`

GET /checkout/templates

**Tags:** Checkout

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/checkout/templates`

POST /checkout/templates

**Tags:** Checkout

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/checkout/templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/checkout/templates/{id}`

DELETE /checkout/templates/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/checkout/templates/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/templates/{id}`

GET /checkout/templates/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/templates/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/checkout/templates/{id}`

PUT /checkout/templates/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/checkout/templates/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/templates/{id}/preview`

GET /checkout/templates/{id}/preview

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/templates/:id/preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/transactions`

GET /checkout/transactions

**Tags:** Checkout

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/transactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/transactions/{id}`

GET /checkout/transactions/{id}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/transactions/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/checkout/transactions/by-gateway/{gatewayTransactionId}`

GET /checkout/transactions/by-gateway/{gatewayTransactionId}

**Tags:** Checkout

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| gatewayTransactionId | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/checkout/transactions/by-gateway/:gatewayTransactionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/communication_channels/admin/channels/{id}`

Admin delete (soft-delete) a tenant-wide communication channel

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Channel deleted

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found or not a tenant-wide channel

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/communication_channels/admin/channels/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/communication_channels/channels`

List communication channels for the current tenant

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**200** – Channel list (paginated)

Content-Type: `application/json`

**400** – Invalid query parameters

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/communication_channels/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/communication_channels/channels/{id}`

DELETE /communication_channels/channels/{id}

**Tags:** Communication Channels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/communication_channels/channels/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/communication_channels/channels/{id}`

Get a single communication channel by id

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Channel detail

Content-Type: `application/json`

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/communication_channels/channels/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/communication_channels/channels/{id}/health`

Snapshot of channel delivery health (last 24h)

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Health snapshot

Content-Type: `application/json`

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/communication_channels/channels/:id/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/channels/{id}/import-history`

Queue a backlog import for a channel (Spec B § Phase B6)

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "sinceDays": 30,
  "maxMessages": 1000
}
```

### Responses

**202** – Import job queued; returns { progressJobId }

Content-Type: `application/json`

**400** – Invalid channel id or unsupported provider

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found / not accessible

Content-Type: `application/json`

**409** – Channel is not connected (requires reauth / error)

Content-Type: `application/json`

**429** – Another import is already running for this channel

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/:id/import-history" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"sinceDays\": 30,
  \"maxMessages\": 1000
}"
```

## POST `/communication_channels/channels/{id}/poll-now`

Manually trigger a poll cycle for a channel (demo / operator override)

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**202** – Poll job enqueued

Content-Type: `application/json`

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found

Content-Type: `application/json`

**409** – Channel disabled, not connected, or push-driven (never polled)

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/:id/poll-now" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/channels/{id}/push/register`

Force-register push delivery for a channel (Spec C § Phase C5)

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**202** – Push registration attempted; check result.pushStatus

Content-Type: `application/json`

**400** – Invalid id or unsupported provider

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Missing push.manage feature

Content-Type: `application/json`

**404** – Channel not found

Content-Type: `application/json`

**409** – Provider does not support push (IMAP)

Content-Type: `application/json`

**502** – Provider returned an error during registration

Content-Type: `application/json`

**503** – Webhook base URL or Pub/Sub topic not configured

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/:id/push/register" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/channels/{id}/set-primary`

Mark a per-user channel as primary

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Channel set as primary (or already primary)

Content-Type: `application/json`

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Channel not found or not owned by current user

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/:id/set-primary" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/channels/{id}/test-send`

Diagnostic — send a test message through the channel without persisting

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Test send result

Content-Type: `application/json`

**400** – Invalid channel id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Not allowed to manage this channel

Content-Type: `application/json`

**404** – Channel or adapter not found

Content-Type: `application/json`

**409** – Channel not connected

Content-Type: `application/json`

**422** – Invalid request body

Content-Type: `application/json`

**502** – Provider error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/:id/test-send" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/channels/connect/credentials`

Connect a credential-based per-user channel (IMAP/SMTP)

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**201** – Channel connected

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Provider is tenant-scoped — use the tenant connect route

Content-Type: `application/json`

**404** – Unknown provider

Content-Type: `application/json`

**409** – Mailbox already connected via another provider

Content-Type: `application/json`

**422** – Invalid body or credential validation failed

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/connect/credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/channels/connect/tenant-credentials`

Connect a tenant-wide credential-based channel (push: FCM/APNs/Expo)

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**201** – Channel connected

Content-Type: `application/json`

**400** – Provider is not tenant-scoped

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Unknown provider

Content-Type: `application/json`

**422** – Invalid body or credential validation failed

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/channels/connect/tenant-credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/communication_channels/me/channels`

List the current user's connected channels

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**200** – List of user-owned channels

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/communication_channels/me/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/messages/{messageId}/reactions`

Add a reaction to a channel-linked message

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| messageId | path | any | Required |

### Responses

**201** – Reaction added

Content-Type: `application/json`

**400** – Invalid messageId

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Channel is owned by another user

Content-Type: `application/json`

**409** – Message not channel-linked or duplicate reaction

Content-Type: `application/json`

**422** – Invalid request body

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/messages/:messageId/reactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/communication_channels/messages/{messageId}/reactions/{reactionId}`

Remove a reaction from a channel-linked message

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| messageId | path | any | Required |
| reactionId | path | any | Required |

### Responses

**204** – Reaction removed

**400** – Invalid params

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Channel is owned by another user

Content-Type: `application/json`

**404** – Reaction not found or not owned by current user

Content-Type: `application/json`

**409** – Message not channel-linked

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/communication_channels/messages/:messageId/reactions/:reactionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/communication_channels/oauth/{provider}/callback`

OAuth callback — exchange code, persist credentials, create per-user channel

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| provider | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

**302** – Redirect back to returnUrl with flash query params

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/communication_channels/oauth/:provider/callback" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/oauth/{provider}/initiate`

Start a per-user channel OAuth flow

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| provider | path | any | Required |

### Responses

**200** – Authorize URL + state cookie set

Content-Type: `application/json`

**400** – Invalid provider or unsupported (no OAuth)

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**422** – Invalid request body

Content-Type: `application/json`

**502** – Adapter failed to build authorize URL

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/oauth/:provider/initiate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/send-as-user`

Send a message through the current user's own channel

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**202** – Message persisted; outbound delivery enqueued

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Cannot send through a channel you don't own

Content-Type: `application/json`

**404** – Channel not found

Content-Type: `application/json`

**409** – Channel in a non-deliverable transitional status

Content-Type: `application/json`

**422** – Invalid body, or channel requires_reauth / disconnected

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/send-as-user" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/test-seed`

Test-only: seed a connected channel, ingest a real inbound message, or emit a seeded inbound link (env-gated)

**Tags:** CommunicationChannels

**Requires authentication.**

### Responses

**201** – Channel seeded / inbound message emitted

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Test channel seeding disabled (production default), or the requested channel does not belong to the caller

Content-Type: `application/json`

**422** – Invalid request body

Content-Type: `application/json`

**500** – Seed failed

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/test-seed" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/communication_channels/threads/{threadId}/assign`

Reassign a channel-linked conversation to a different owner

**Tags:** CommunicationChannels

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| threadId | path | any | Required |

### Responses

**200** – Conversation reassigned (or unchanged)

Content-Type: `application/json`

**400** – Invalid threadId

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Conversation not channel-linked

Content-Type: `application/json`

**422** – Invalid request body

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/communication_channels/threads/:threadId/assign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/communication_channels/webhook/{provider}`

Process an inbound channel webhook (Slack, WhatsApp, Email, ...)

**Tags:** CommunicationChannels

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| provider | path | any | Required |

### Responses

**202** – Webhook accepted for async processing

Content-Type: `application/json`

**401** – Signature verification failed against every candidate channel

Content-Type: `application/json`

**404** – Unknown provider

Content-Type: `application/json`

**413** – Webhook payload too large

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/webhook/:provider" \
  -H "Accept: application/json"
```

## POST `/communication_channels/webhooks/gmail`

Gmail Pub/Sub push notification webhook (Spec C § Phase C2)

**Tags:** CommunicationChannels

### Responses

**204** – Notification verified + history-sync job enqueued

**400** – Body not a valid Pub/Sub envelope

Content-Type: `application/json`

**401** – Invalid JWT or email claim

Content-Type: `application/json`

**403** – Wrong audience

Content-Type: `application/json`

**413** – Webhook payload too large

Content-Type: `application/json`

**503** – Webhook not configured / Google certs unreachable

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/communication_channels/webhooks/gmail" \
  -H "Accept: application/json"
```

## GET `/configs/cache`

Get cache statistics

Returns detailed cache statistics including total entries and breakdown by cache segments. Requires cache service to be available.

**Tags:** Configs

**Requires authentication.**

### Responses

**200** – Cache statistics

Content-Type: `application/json`

```json
{
  "generatedAt": "string",
  "totalKeys": 1,
  "segments": [
    {
      "segment": "string",
      "resource": null,
      "method": null,
      "path": null,
      "keyCount": 1,
      "keys": [
        "string"
      ]
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to resolve cache stats

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Cache service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/configs/cache" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/configs/cache`

Purge cache

Purges cache entries. Supports two actions: purgeAll (clears entire cache) or purgeSegment (clears specific segment). Returns updated cache statistics after purge.

**Tags:** Configs

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "action": "purgeAll"
}
```

### Responses

**200** – Cache segment cleared successfully

Content-Type: `application/json`

```json
{
  "action": "purgeSegment",
  "segment": "string",
  "deleted": 1,
  "stats": {
    "generatedAt": "string",
    "totalKeys": 1,
    "segments": [
      {
        "segment": "string",
        "resource": null,
        "method": null,
        "path": null,
        "keyCount": 1,
        "keys": [
          "string"
        ]
      }
    ]
  }
}
```

**400** – Invalid request - missing segment identifier for purgeSegment action

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to purge cache

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Cache service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/configs/cache" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"action\": \"purgeAll\"
}"
```

## DELETE `/configs/module-telemetry`

Clear module telemetry data

Development-only endpoint that clears in-memory module telemetry and local process telemetry files.

**Tags:** Configs

**Requires authentication.**

### Responses

**200** – Module telemetry cleared

Content-Type: `application/json`

```json
{
  "cleared": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden outside development mode

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/configs/module-telemetry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/configs/module-telemetry`

Get module resource usage telemetry

Returns in-process module resource attribution for API routes, event subscribers, and queue workers.

**Tags:** Configs

**Requires authentication.**

### Responses

**200** – Module resource usage report

Content-Type: `application/json`

```json
{
  "generatedAt": "string",
  "startedAt": "string",
  "enabled": true,
  "bucketIntervalMs": 1,
  "totals": {
    "modules": 1,
    "operations": 1,
    "calls": 1,
    "errors": 1,
    "totalDurationMs": 1,
    "totalCpuMs": 1,
    "positiveHeapDeltaBytes": 1,
    "positiveRssDeltaBytes": 1
  },
  "thresholds": {
    "p95DurationMs": 1,
    "cpuMs": 1,
    "positiveHeapDeltaBytes": 1,
    "positiveRssDeltaBytes": 1,
    "errors": 1
  },
  "modules": [
    {
      "moduleId": "string",
      "calls": 1,
      "errors": 1,
      "totalDurationMs": 1,
      "p95DurationMs": 1,
      "totalCpuMs": 1,
      "positiveHeapDeltaBytes": 1,
      "positiveRssDeltaBytes": 1,
      "surfaces": [
        {
          "surface": "api",
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuMs": 1,
          "positiveHeapDeltaBytes": 1,
          "positiveRssDeltaBytes": 1
        }
      ],
      "topOperations": [
        {
          "moduleId": "string",
          "surface": "api",
          "operation": "string",
          "resourceId": null,
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "maxDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuUserMs": 1,
          "totalCpuSystemMs": 1,
          "maxCpuMs": 1,
          "totalHeapDeltaBytes": 1,
          "positiveHeapDeltaBytes": 1,
          "maxHeapDeltaBytes": 1,
          "totalRssDeltaBytes": 1,
          "positiveRssDeltaBytes": 1,
          "maxRssDeltaBytes": 1,
          "firstSeenAt": "string",
          "lastSeenAt": "string"
        }
      ],
      "candidateReasons": [
        "string"
      ]
    }
  ],
  "candidates": [
    {
      "moduleId": "string",
      "calls": 1,
      "errors": 1,
      "totalDurationMs": 1,
      "p95DurationMs": 1,
      "totalCpuMs": 1,
      "positiveHeapDeltaBytes": 1,
      "positiveRssDeltaBytes": 1,
      "surfaces": [
        {
          "surface": "api",
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuMs": 1,
          "positiveHeapDeltaBytes": 1,
          "positiveRssDeltaBytes": 1
        }
      ],
      "topOperations": [
        {
          "moduleId": "string",
          "surface": "api",
          "operation": "string",
          "resourceId": null,
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "maxDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuUserMs": 1,
          "totalCpuSystemMs": 1,
          "maxCpuMs": 1,
          "totalHeapDeltaBytes": 1,
          "positiveHeapDeltaBytes": 1,
          "maxHeapDeltaBytes": 1,
          "totalRssDeltaBytes": 1,
          "positiveRssDeltaBytes": 1,
          "maxRssDeltaBytes": 1,
          "firstSeenAt": "string",
          "lastSeenAt": "string"
        }
      ],
      "candidateReasons": [
        "string"
      ]
    }
  ],
  "buckets": [
    {
      "bucketStart": "string",
      "bucketEnd": "string",
      "bucketIntervalMs": 1,
      "stage": "startup",
      "partial": true,
      "totals": {
        "modules": 1,
        "calls": 1,
        "errors": 1,
        "totalDurationMs": 1,
        "totalCpuMs": 1,
        "positiveHeapDeltaBytes": 1,
        "positiveRssDeltaBytes": 1
      },
      "modules": [
        {
          "moduleId": "string",
          "calls": 1,
          "errors": 1,
          "totalDurationMs": 1,
          "p95DurationMs": 1,
          "totalCpuMs": 1,
          "positiveHeapDeltaBytes": 1,
          "positiveRssDeltaBytes": 1,
          "surfaces": [
            {
              "surface": "api",
              "calls": 1,
              "errors": 1,
              "totalDurationMs": 1,
              "p95DurationMs": 1,
              "totalCpuMs": 1,
              "positiveHeapDeltaBytes": 1,
              "positiveRssDeltaBytes": 1
            }
          ],
          "topOperations": [
            {
              "moduleId": "string",
              "surface": "api",
              "operation": "string",
              "resourceId": null,
              "calls": 1,
              "errors": 1,
              "totalDurationMs": 1,
              "maxDurationMs": 1,
              "p95DurationMs": 1,
              "totalCpuUserMs": 1,
              "totalCpuSystemMs": 1,
              "maxCpuMs": 1,
              "totalHeapDeltaBytes": 1,
              "positiveHeapDeltaBytes": 1,
              "maxHeapDeltaBytes": 1,
              "totalRssDeltaBytes": 1,
              "positiveRssDeltaBytes": 1,
              "maxRssDeltaBytes": 1,
              "firstSeenAt": "string",
              "lastSeenAt": "string"
            }
          ],
          "candidateReasons": [
            "string"
          ]
        }
      ]
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/configs/module-telemetry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/configs/system-status`

Get system health status

Returns comprehensive system health information including environment details, version, resource usage, and service connectivity status.

**Tags:** Configs

**Requires authentication.**

### Responses

**200** – System status snapshot

Content-Type: `application/json`

```json
{
  "generatedAt": "string",
  "runtimeMode": "development",
  "categories": [
    {
      "key": "profiling",
      "labelKey": "string",
      "descriptionKey": null,
      "items": [
        {
          "key": "string",
          "category": "profiling",
          "kind": "boolean",
          "labelKey": "string",
          "descriptionKey": "string",
          "docUrl": null,
          "defaultValue": null,
          "state": "enabled",
          "value": null,
          "normalizedValue": null
        }
      ]
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to load system status

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/configs/system-status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/configs/system-status`

Clear system cache

Purges the entire cache for the current tenant. Useful for troubleshooting or forcing fresh data loading.

**Tags:** Configs

**Requires authentication.**

### Responses

**200** – Cache cleared successfully

Content-Type: `application/json`

```json
{
  "cleared": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to purge cache

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Cache service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/configs/system-status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/configs/upgrade-actions`

List pending upgrade actions

Returns a list of pending upgrade actions for the current version. These are one-time setup tasks that need to be executed after upgrading to a new version. Requires organization and tenant context.

**Tags:** Configs

**Requires authentication.**

### Responses

**200** – List of pending upgrade actions

Content-Type: `application/json`

```json
{
  "version": "string",
  "actions": [
    {
      "id": "string",
      "version": "string",
      "message": "string",
      "ctaLabel": "string",
      "successMessage": "string",
      "loadingLabel": "string"
    }
  ]
}
```

**400** – Missing organization or tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to load upgrade actions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/configs/upgrade-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/configs/upgrade-actions`

Execute upgrade action

Executes a specific upgrade action by ID. Typically used for one-time setup tasks like seeding example data after version upgrade. Returns execution status and localized success message.

**Tags:** Configs

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "actionId": "string"
}
```

### Responses

**200** – Upgrade action executed successfully

Content-Type: `application/json`

```json
{
  "status": "string",
  "message": "string",
  "version": "string"
}
```

**400** – Invalid request body or missing context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Upgrade actions are disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to execute upgrade action

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/configs/upgrade-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"actionId\": \"string\"
}"
```

## DELETE `/currencies/currencies`

Delete currency

Deletes a currency by id.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Currency deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/currencies/currencies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/currencies/currencies`

List currencies

Returns a paginated collection of currencies scoped to the authenticated organization.

**Tags:** Currencies

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| isBase | query | any | Optional |
| isActive | query | any | Optional |
| code | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated currencies

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "code": "string",
      "name": "string",
      "symbol": null,
      "decimalPlaces": 1,
      "thousandsSeparator": null,
      "decimalSeparator": null,
      "isBase": true,
      "isActive": true,
      "createdAt": null,
      "updatedAt": null,
      "organizationId": "string",
      "tenantId": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/currencies/currencies?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/currencies/currencies`

Create currency

Creates a new currency.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "string",
  "tenantId": "string",
  "code": "string",
  "name": "string",
  "symbol": null,
  "thousandsSeparator": null,
  "decimalSeparator": null
}
```

### Responses

**201** – Currency created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/currencies/currencies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"string\",
  \"tenantId\": \"string\",
  \"code\": \"string\",
  \"name\": \"string\",
  \"symbol\": null,
  \"thousandsSeparator\": null,
  \"decimalSeparator\": null
}"
```

## PUT `/currencies/currencies`

Update currency

Updates an existing currency by id.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "string",
  "symbol": null,
  "thousandsSeparator": null,
  "decimalSeparator": null
}
```

### Responses

**200** – Currency updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/currencies/currencies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\",
  \"symbol\": null,
  \"thousandsSeparator\": null,
  \"decimalSeparator\": null
}"
```

## GET `/currencies/currencies/options`

List currency options

Returns currencies formatted for select inputs.

**Tags:** Currencies

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| q | query | any | Optional |
| query | query | any | Optional |
| search | query | any | Optional |
| includeInactive | query | any | Optional |
| limit | query | any | Optional |

### Responses

**200** – Option list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
```

**400** – Invalid query

Content-Type: `application/json`

```json
{
  "items": []
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "items": []
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/currencies/currencies/options?limit=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/currencies/exchange-rates`

Delete exchangerate

Deletes an exchange rate by id.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – ExchangeRate deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/currencies/exchange-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/currencies/exchange-rates`

List exchangerates

Returns a paginated collection of exchangerates scoped to the authenticated organization.

**Tags:** Currencies

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| fromCurrencyCode | query | any | Optional |
| toCurrencyCode | query | any | Optional |
| isActive | query | any | Optional |
| source | query | any | Optional |
| type | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated exchangerates

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fromCurrencyCode": "string",
      "toCurrencyCode": "string",
      "rate": "string",
      "date": "string",
      "source": "string",
      "type": null,
      "isActive": true,
      "createdAt": null,
      "updatedAt": null,
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/currencies/exchange-rates?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/currencies/exchange-rates`

Create exchangerate

Creates a new exchange rate.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "string",
  "tenantId": "string",
  "fromCurrencyCode": "string",
  "toCurrencyCode": "string",
  "rate": "string",
  "type": null
}
```

### Responses

**201** – ExchangeRate created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/currencies/exchange-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"string\",
  \"tenantId\": \"string\",
  \"fromCurrencyCode\": \"string\",
  \"toCurrencyCode\": \"string\",
  \"rate\": \"string\",
  \"type\": null
}"
```

## PUT `/currencies/exchange-rates`

Update exchangerate

Updates an existing exchange rate by id.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "string",
  "type": null
}
```

### Responses

**200** – ExchangeRate updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/currencies/exchange-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\",
  \"type\": null
}"
```

## DELETE `/currencies/fetch-configs`

Delete currency fetch configuration

Deletes a currency fetch configuration by id.

**Tags:** Currencies

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. Currency fetch configuration identifier to delete |

### Responses

**200** – Currency fetch configuration deleted successfully

Content-Type: `application/json`

```json
{
  "success": true
}
```

**400** – Bad request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/currencies/fetch-configs?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/currencies/fetch-configs`

List currency fetch configurations

Returns all currency fetch configurations scoped to the authenticated organization.

**Tags:** Currencies

**Requires authentication.**

### Responses

**200** – A list of currency fetch configurations

Content-Type: `application/json`

```json
{
  "configs": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "provider": "string",
      "isEnabled": true,
      "syncTime": null,
      "lastSyncAt": null,
      "lastSyncStatus": null,
      "lastSyncMessage": null,
      "lastSyncCount": null,
      "config": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/currencies/fetch-configs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/currencies/fetch-configs`

Create currency fetch configuration

Creates a new currency fetch configuration.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "provider": "NBP",
  "isEnabled": false,
  "syncTime": null,
  "config": null
}
```

### Responses

**201** – Currency fetch configuration created successfully

Content-Type: `application/json`

```json
{
  "config": {
    "id": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "provider": "string",
    "isEnabled": true,
    "syncTime": null,
    "lastSyncAt": null,
    "lastSyncStatus": null,
    "lastSyncMessage": null,
    "lastSyncCount": null,
    "config": null,
    "createdAt": "string",
    "updatedAt": "string"
  }
}
```

**400** – Bad request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/currencies/fetch-configs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"provider\": \"NBP\",
  \"isEnabled\": false,
  \"syncTime\": null,
  \"config\": null
}"
```

## PUT `/currencies/fetch-configs`

Update currency fetch configuration

Updates an existing currency fetch configuration by id.

**Tags:** Currencies

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "syncTime": null,
  "config": null,
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Currency fetch configuration updated successfully

Content-Type: `application/json`

```json
{
  "config": {
    "id": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "provider": "string",
    "isEnabled": true,
    "syncTime": null,
    "lastSyncAt": null,
    "lastSyncStatus": null,
    "lastSyncMessage": null,
    "lastSyncCount": null,
    "config": null,
    "createdAt": "string",
    "updatedAt": "string"
  }
}
```

**400** – Bad request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/currencies/fetch-configs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"syncTime\": null,
  \"config\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/currencies/fetch-rates`

Fetch currency rates

Fetches currency exchange rates from configured providers for a specific date.

**Tags:** Currencies

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Currency rates fetched successfully

Content-Type: `application/json`

```json
{
  "totalFetched": 1,
  "byProvider": {
    "key": {
      "count": 1
    }
  },
  "errors": [
    "string"
  ]
}
```

**400** – Bad request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "totalFetched": 1,
  "byProvider": {
    "key": {
      "count": 1
    }
  },
  "errors": [
    "string"
  ]
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/currencies/fetch-rates" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/customer_accounts/admin/demo-accounts`

List seeded demo portal accounts (admin)

Returns the example-data portal accounts that exist in the caller’s organization and can still be logged into with the credentials the seeding hook created them with. Accounts that were deactivated, left unverified, soft-deleted, or had their password changed are omitted, as is every account when example data was not seeded.

**Tags:** Customer Accounts Admin

**Requires authentication.**

### Responses

**200** – Seeded demo accounts present in the current organization

Content-Type: `application/json`

```json
{
  "ok": true,
  "items": [
    {
      "email": "user@example.com",
      "password": "string",
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "name": "string",
          "slug": "string"
        }
      ]
    }
  ]
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/demo-accounts" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/customer_accounts/admin/domain-mappings`

Remove a custom domain

Removes the domain mapping identified by ?id=. Cache and Traefik routing drain within TTL.

**Tags:** CustomerAccounts

**Requires authentication.**

### Responses

**200** – OK

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Bad request

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customer_accounts/admin/domain-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customer_accounts/admin/domain-mappings`

List domain mappings

Returns all custom-domain mappings for the current tenant, optionally filtered by organization.

**Tags:** CustomerAccounts

**Requires authentication.**

### Responses

**200** – OK

Content-Type: `application/json`

```json
{
  "ok": true,
  "domainMappings": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "hostname": "string",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "provider": "traefik",
      "status": "pending",
      "verifiedAt": null,
      "lastDnsCheckAt": null,
      "dnsFailureReason": null,
      "tlsFailureReason": null,
      "tlsRetryCount": 1,
      "cnameTarget": null,
      "aRecordTarget": null,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "config": {
    "cnameTarget": null,
    "aRecordTarget": null
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/domain-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customer_accounts/admin/domain-mappings`

Register a custom domain

Registers a new custom domain mapping for an organization. Verifies via DNS asynchronously.

**Tags:** CustomerAccounts

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "hostname": "string",
  "organizationId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Created

Content-Type: `application/json`

```json
{
  "ok": true,
  "domainMapping": {
    "id": "00000000-0000-4000-8000-000000000000",
    "hostname": "string",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "provider": "traefik",
    "status": "pending",
    "verifiedAt": null,
    "lastDnsCheckAt": null,
    "dnsFailureReason": null,
    "tlsFailureReason": null,
    "tlsRetryCount": 1,
    "cnameTarget": null,
    "aRecordTarget": null,
    "createdAt": "string",
    "updatedAt": null
  }
}
```

**400** – Validation error

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**409** – Conflict

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/domain-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"hostname\": \"string\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/customer_accounts/admin/domain-mappings/{id}/health-check`

Trigger TLS health check

Runs an HTTPS probe to verify Traefik has provisioned a certificate. On success: transitions the mapping to active.

**Tags:** CustomerAccounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – OK

Content-Type: `application/json`

```json
{
  "ok": true,
  "domainMapping": {
    "id": "00000000-0000-4000-8000-000000000000",
    "hostname": "string",
    "status": "string",
    "tlsRetryCount": 1,
    "tlsFailureReason": null
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/domain-mappings/:id/health-check" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customer_accounts/admin/domain-mappings/{id}/verify`

Trigger DNS verification

Runs DNS verification (CNAME → A → reverse-resolve fallback) for the domain mapping. Returns diagnostics on failure.

**Tags:** CustomerAccounts

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – OK — see status

Content-Type: `application/json`

```json
{
  "ok": true,
  "domainMapping": {
    "id": "00000000-0000-4000-8000-000000000000",
    "hostname": "string",
    "status": "string",
    "verifiedAt": null,
    "lastDnsCheckAt": null,
    "dnsFailureReason": null
  },
  "diagnostics": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/domain-mappings/:id/verify" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customer_accounts/admin/roles`

List customer roles (admin)

Returns all customer roles for the tenant.

**Tags:** Customer Accounts Admin

### Responses

**200** – Role list

Content-Type: `application/json`

```json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "slug": "string",
      "description": null,
      "isDefault": true,
      "isSystem": true,
      "customerAssignable": true,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/roles" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/admin/roles`

Create customer role (admin)

Creates a new customer role with an empty ACL.

**Tags:** Customer Accounts Admin

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "slug": "string"
}
```

### Responses

**201** – Role created

Content-Type: `application/json`

```json
{
  "ok": true,
  "role": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "slug": "string",
    "description": null,
    "isDefault": true,
    "isSystem": true,
    "customerAssignable": true,
    "createdAt": "string"
  }
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**409** – Slug already exists

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/roles" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"slug\": \"string\"
}"
```

## DELETE `/customer_accounts/admin/roles/{id}`

Delete customer role (admin)

Soft deletes a customer role and its ACL. The default role (auto-assigned to new portal users) and roles with assigned users cannot be deleted.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Role deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Default role or has assigned users

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/admin/roles/{id}`

Get customer role detail (admin)

Returns full customer role details including ACL features.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Role detail with ACL

Content-Type: `application/json`

```json
{
  "ok": true,
  "role": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "slug": "string",
    "description": null,
    "isDefault": true,
    "isSystem": true,
    "customerAssignable": true,
    "createdAt": "string",
    "updatedAt": null,
    "acl": {
      "features": [
        "string"
      ],
      "isPortalAdmin": true
    }
  }
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/admin/roles/{id}`

Update customer role (admin)

Updates a customer role. System roles are protected from name changes.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Role updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed or system role restriction

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## PUT `/customer_accounts/admin/roles/{id}/acl`

Update customer role ACL (admin)

Updates the ACL (features and portal admin flag) for a customer role. Invalidates RBAC cache after update.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "features": [
    "string"
  ]
}
```

### Responses

**200** – ACL updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "updatedAt": "string"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**409** – Stale ACL write (optimistic-lock conflict)

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/admin/roles/00000000-0000-4000-8000-000000000000/acl" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"features\": [
    \"string\"
  ]
}"
```

## GET `/customer_accounts/admin/users`

List customer users (admin)

Returns a paginated list of customer users with roles. Supports filtering by status, company, role, and search.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| status | query | any | Optional |
| customerEntityId | query | any | Optional |
| roleId | query | any | Optional |
| search | query | any | Optional |

### Responses

**200** – Paginated user list

Content-Type: `application/json`

```json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "string",
      "displayName": "string",
      "emailVerified": true,
      "isActive": true,
      "lockedUntil": null,
      "lastLoginAt": null,
      "customerEntityId": null,
      "personEntityId": null,
      "createdAt": "string",
      "updatedAt": null,
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "name": "string",
          "slug": "string"
        }
      ]
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/users" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/admin/users`

Create customer user (admin)

Creates a new customer user directly. Staff-initiated, bypasses signup flow.

**Tags:** Customer Accounts Admin

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "password": "string",
  "displayName": "string"
}
```

### Responses

**201** – User created

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string"
  }
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**409** – Email already exists

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/users" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"password\": \"string\",
  \"displayName\": \"string\"
}"
```

## GET `/customer_accounts/admin/users-invite`

List pending customer invitations (admin)

Lists invitations that are still pending — not accepted, not cancelled, and not expired — for the caller's tenant and organization. The invitation token is never returned.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| personEntityId | query | any | Optional |
| customerEntityId | query | any | Optional |
| email | query | any | Optional |

### Responses

**200** – Pending invitations

Content-Type: `application/json`

```json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "string",
      "displayName": null,
      "customerEntityId": null,
      "personEntityId": null,
      "roleIds": [
        "00000000-0000-4000-8000-000000000000"
      ],
      "invitedByUserId": null,
      "expiresAt": "string",
      "createdAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/users-invite" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/admin/users-invite`

Invite customer user (admin)

Creates a staff-initiated invitation for a new customer user. The invitedByUserId is set from the staff auth context.

**Tags:** Customer Accounts Admin

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "roleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

### Responses

**201** – Invitation created

Content-Type: `application/json`

```json
{
  "ok": true,
  "invitation": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "customerEntityId": null,
    "personEntityId": null,
    "expiresAt": "string"
  }
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many invitation requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**502** – Invitation email could not be sent

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/users-invite" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"roleIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
```

## DELETE `/customer_accounts/admin/users/{id}`

Delete customer user (admin)

Soft deletes a customer user and revokes all their active sessions.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – User deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/admin/users/{id}`

Get customer user detail (admin)

Returns full customer user details including CRM links, roles, and active session count.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – User detail

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string",
    "emailVerified": true,
    "isActive": true,
    "lockedUntil": null,
    "lastLoginAt": null,
    "failedLoginAttempts": 1,
    "customerEntityId": null,
    "personEntityId": null,
    "createdAt": "string",
    "updatedAt": null,
    "roles": [
      {
        "id": "00000000-0000-4000-8000-000000000000",
        "name": "string",
        "slug": "string"
      }
    ],
    "activeSessionCount": 1
  }
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/admin/users/{id}`

Update customer user (admin)

Updates a customer user. Staff can update status, lock, CRM links, and roles. Role assignment bypasses customer_assignable check.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "lockedUntil": null,
  "personEntityId": null,
  "customerEntityId": null
}
```

### Responses

**200** – User updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed or role not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"lockedUntil\": null,
  \"personEntityId\": null,
  \"customerEntityId\": null
}"
```

## POST `/customer_accounts/admin/users/{id}/reset-password`

Reset customer user password (admin)

Allows staff to set a new password for a customer user.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "newPassword": "string"
}
```

### Responses

**200** – Password reset

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000/reset-password" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"newPassword\": \"string\"
}"
```

## POST `/customer_accounts/admin/users/{id}/send-reset-link`

Send password reset link for customer user (admin)

Creates a password reset token for a customer user and returns a reset link URL. The admin must prepend the appropriate portal domain/slug to the relative URL.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Reset link generated

Content-Type: `application/json`

```json
{
  "ok": true,
  "resetLink": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000/send-reset-link" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/admin/users/{id}/verify-email`

Verify customer user email (admin)

Allows staff to manually mark a customer user email as verified.

**Tags:** Customer Accounts Admin

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Email verified

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/admin/users/00000000-0000-4000-8000-000000000000/verify-email" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/domain-check`

Verify a hostname is allowed for TLS provisioning

Called by Traefik before issuing a Let's Encrypt certificate. Requires the X-Domain-Check-Secret header to match DOMAIN_CHECK_SECRET.

**Tags:** CustomerAccounts

### Responses

**200** – Hostname allowed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Hostname not registered or not yet verified

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**503** – Server misconfiguration

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/domain-check" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/domain-resolve`

Single-host resolve for the Node middleware

Internal endpoint used by the portal middleware to populate its in-memory cache. Requires X-Domain-Resolve-Secret header.

**Tags:** CustomerAccounts

### Responses

**200** – OK

Content-Type: `application/json`

```json
{
  "ok": true,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "orgSlug": null,
  "status": "active"
}
```

**400** – Bad request

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**503** – Server misconfiguration

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/domain-resolve" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/domain-resolve/all`

Batch warm-up for the Node middleware

Returns every active domain mapping in a single payload so the middleware can populate its cache on process start. Requires X-Domain-Resolve-Secret header.

**Tags:** CustomerAccounts

### Responses

**200** – OK

Content-Type: `application/json`

```json
{
  "ok": true,
  "domains": [
    {
      "hostname": "string",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "orgSlug": null,
      "status": "active"
    }
  ]
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Server misconfiguration

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/domain-resolve/all" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/email/verify`

Verify customer email address

Validates the email verification token and marks the email as verified.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "token": "string"
}
```

### Responses

**200** – Email verified

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid or expired token

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/email/verify" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\"
}"
```

## POST `/customer_accounts/invitations/accept`

Accept customer invitation

Accepts an invitation, creates the user account, assigns roles, and auto-logs in.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "token": "string",
  "password": "string",
  "displayName": "string"
}
```

### Responses

**201** – Invitation accepted and user created

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "user@example.com",
    "displayName": "string",
    "emailVerified": true
  },
  "resolvedFeatures": [
    "string"
  ]
}
```

**400** – Invalid or expired invitation

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**409** – An account with this email address already exists

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/invitations/accept" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\",
  \"password\": \"string\",
  \"displayName\": \"string\"
}"
```

## POST `/customer_accounts/login`

Authenticate customer credentials

Validates customer credentials and issues JWT + session cookies.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "password": "string"
}
```

### Responses

**200** – Login successful

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "user@example.com",
    "displayName": "string",
    "emailVerified": true
  },
  "resolvedFeatures": [
    "string"
  ]
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Invalid credentials

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many login attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"password\": \"string\"
}"
```

## POST `/customer_accounts/magic-link/request`

Request magic link login

Sends a magic link to the customer email. Always returns 200 to prevent enumeration.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com"
}
```

### Responses

**200** – Request accepted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**429** – Too many requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/magic-link/request" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\"
}"
```

## POST `/customer_accounts/magic-link/verify`

Verify magic link token

Validates the magic link token, auto-verifies email, and creates a session.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "token": "string"
}
```

### Responses

**200** – Login successful

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "user@example.com",
    "displayName": "string",
    "emailVerified": true
  },
  "resolvedFeatures": [
    "string"
  ]
}
```

**400** – Invalid or expired token

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Account not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/magic-link/verify" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\"
}"
```

## POST `/customer_accounts/password/reset-confirm`

Confirm customer password reset

Validates the reset token and sets a new password. Revokes all existing sessions.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "token": "string",
  "password": "string"
}
```

### Responses

**200** – Password reset successful

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid or expired token

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/password/reset-confirm" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"string\",
  \"password\": \"string\"
}"
```

## POST `/customer_accounts/password/reset-request`

Request customer password reset

Initiates a password reset flow. Always returns 200 to prevent email enumeration.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com"
}
```

### Responses

**200** – Request accepted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**429** – Too many requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/password/reset-request" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\"
}"
```

## GET `/customer_accounts/portal/events/stream`

Subscribe to portal events via SSE (Portal Event Bridge)

Long-lived SSE connection that receives server-side events marked with portalBroadcast: true. Events are filtered by the customer's tenant, organization, and recipient user audience.

**Tags:** Customer Portal

### Responses

**200** – Event stream (text/event-stream)

Content-Type: `application/json`

**401** – Not authenticated

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/events/stream" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/portal/feature-check`

Check customer portal feature access

Checks which of the requested features the authenticated customer user has. Used by portal menu injection for feature-gating.

**Tags:** Customer Portal

### Request Body

Content-Type: `application/json`

```json
{
  "features": [
    "string"
  ]
}
```

### Responses

**200** – Feature check result

Content-Type: `application/json`

```json
{
  "ok": true,
  "granted": [
    "string"
  ]
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/portal/feature-check" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"features\": [
    \"string\"
  ]
}"
```

## POST `/customer_accounts/portal/logout`

Customer logout

Revokes the current session and clears authentication cookies.

**Tags:** Customer Portal

### Responses

**200** – Logged out

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/portal/logout" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/portal/nav`

Portal sidebar navigation

Returns the portal sidebar for the authenticated customer. Items are derived from each portal page's `nav` metadata and filtered by `requireCustomerFeatures` against concrete effective features.

**Tags:** Customer Portal

### Responses

**200** – Portal sidebar groups

Content-Type: `application/json`

```json
{
  "ok": true,
  "orgSlug": "string",
  "groups": [
    {
      "id": "main",
      "items": [
        {
          "id": "string",
          "label": "string",
          "href": "string",
          "order": 1
        }
      ]
    }
  ],
  "grantedFeatures": [
    "string"
  ],
  "isPortalAdmin": true
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Organization not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/nav" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/portal/notifications`

List customer notifications

Returns paginated notifications for the authenticated customer user. Dismissed notifications are excluded by default unless ?status=dismissed is specified.

**Tags:** Customer Portal

### Responses

**200** – Notification list

Content-Type: `application/json`

```json
{
  "ok": true,
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "type": "string",
      "title": "string",
      "body": null,
      "titleKey": null,
      "bodyKey": null,
      "titleVariables": null,
      "bodyVariables": null,
      "icon": null,
      "severity": "info",
      "status": "unread",
      "actions": [
        {
          "id": "string",
          "label": "string"
        }
      ],
      "sourceModule": null,
      "sourceEntityType": null,
      "sourceEntityId": null,
      "linkHref": null,
      "createdAt": "string",
      "readAt": null,
      "actionTaken": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/notifications" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/portal/notifications/{id}/dismiss`

Dismiss notification

Dismisses a single notification for the authenticated customer user.

**Tags:** Customer Portal

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Notification dismissed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Notification not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/portal/notifications/00000000-0000-4000-8000-000000000000/dismiss" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/portal/notifications/{id}/read`

Mark notification as read

Marks a single notification as read for the authenticated customer user.

**Tags:** Customer Portal

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Notification marked as read

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Notification not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/portal/notifications/00000000-0000-4000-8000-000000000000/read" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/portal/notifications/mark-all-read`

Mark all notifications as read

Marks all unread notifications as read for the authenticated customer user.

**Tags:** Customer Portal

### Responses

**200** – All notifications marked as read

Content-Type: `application/json`

```json
{
  "ok": true,
  "count": 1
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/portal/notifications/mark-all-read" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/portal/notifications/unread-count`

Get unread notification count

Returns the number of unread notifications for the authenticated customer user.

**Tags:** Customer Portal

### Responses

**200** – Unread count

Content-Type: `application/json`

```json
{
  "ok": true,
  "unreadCount": 1
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/notifications/unread-count" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/portal/password-change`

Change customer password

Changes the authenticated customer user password after verifying the current password. Revokes all existing sessions.

**Tags:** Customer Portal

### Request Body

Content-Type: `application/json`

```json
{
  "currentPassword": "string",
  "newPassword": "string"
}
```

### Responses

**200** – Password changed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Current password incorrect or validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/portal/password-change" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"currentPassword\": \"string\",
  \"newPassword\": \"string\"
}"
```

## GET `/customer_accounts/portal/profile`

Get customer profile

Returns the authenticated customer user profile with roles and permissions.

**Tags:** Customer Portal

### Responses

**200** – Profile data

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string",
    "emailVerified": true,
    "customerEntityId": null,
    "personEntityId": null,
    "isActive": true,
    "lastLoginAt": null,
    "createdAt": "string"
  },
  "roles": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "slug": "string"
    }
  ],
  "resolvedFeatures": [
    "string"
  ],
  "isPortalAdmin": true
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/profile" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/portal/profile`

Update customer profile

Updates the authenticated customer user profile.

**Tags:** Customer Portal

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Profile updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "user": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "displayName": "string"
  }
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/portal/profile" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/customer_accounts/portal/sessions`

List customer sessions

Returns active sessions for the authenticated customer user.

**Tags:** Customer Portal

### Responses

**200** – Session list

Content-Type: `application/json`

```json
{
  "ok": true,
  "sessions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "ipAddress": null,
      "userAgent": null,
      "lastUsedAt": null,
      "createdAt": "string",
      "expiresAt": "string",
      "isCurrent": true
    }
  ]
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/sessions" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/portal/sessions-refresh`

Refresh customer JWT from session token

Uses the session cookie to issue a fresh JWT access token.

**Tags:** Customer Portal

### Responses

**200** – Token refreshed

Content-Type: `application/json`

```json
{
  "ok": true,
  "resolvedFeatures": [
    "string"
  ]
}
```

**401** – Invalid session

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/portal/sessions-refresh" \
  -H "Accept: application/json"
```

## DELETE `/customer_accounts/portal/sessions/{id}`

Revoke a customer session

Revokes a specific session (not the current one).

**Tags:** Customer Portal

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Session revoked

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Cannot revoke current session

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Session not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customer_accounts/portal/sessions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## GET `/customer_accounts/portal/users`

List company portal users

Lists portal users associated with the same company. Paginated (default pageSize 25, max 100).

**Tags:** Customer Portal

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Paginated user list

Content-Type: `application/json`

```json
{
  "ok": true,
  "users": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "email": "string",
      "displayName": "string",
      "emailVerified": true,
      "isActive": true,
      "lastLoginAt": null,
      "createdAt": "string",
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "name": "string",
          "slug": "string"
        }
      ]
    }
  ],
  "total": 1,
  "totalPages": 1,
  "page": 1,
  "pageSize": 1
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customer_accounts/portal/users" \
  -H "Accept: application/json"
```

## POST `/customer_accounts/portal/users-invite`

Invite a user to the company portal

Creates an invitation for a new user to join the company portal.

**Tags:** Customer Portal

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "roleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

### Responses

**201** – Invitation created

Content-Type: `application/json`

```json
{
  "ok": true,
  "invitation": {
    "id": "00000000-0000-4000-8000-000000000000",
    "email": "string",
    "expiresAt": "string"
  }
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions or non-assignable role

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many invitation requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**502** – Invitation email could not be sent

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/portal/users-invite" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"roleIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
```

## DELETE `/customer_accounts/portal/users/{id}`

Delete a company portal user

Soft deletes a portal user and revokes all their sessions.

**Tags:** Customer Portal

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – User deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Cannot delete self

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customer_accounts/portal/users/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## PUT `/customer_accounts/portal/users/{id}/roles`

Update portal user roles

Assigns new roles to a company portal user.

**Tags:** Customer Portal

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "roleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

### Responses

**200** – Roles updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Not authenticated

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – User not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customer_accounts/portal/users/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
```

## POST `/customer_accounts/signup`

Register a new customer account

Accepts a signup request and always returns 202 to prevent account enumeration.

**Tags:** Customer Authentication

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "password": "string",
  "displayName": "string"
}
```

### Responses

**202** – Signup accepted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed or invalid request origin

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**429** – Too many signup attempts

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Signup email origin is not configured

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customer_accounts/signup" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"password\": \"string\",
  \"displayName\": \"string\"
}"
```

## DELETE `/customers/activities`

Delete activity

DEPRECATED (sunset 2026-06-30): Deletes an activity. Use DELETE /api/customers/interactions instead.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Activity deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/activities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/activities`

List activitys

Returns a paginated collection of activitys scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| entityId | query | any | Optional |
| dealId | query | any | Optional |
| activityType | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated activitys

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "activityType": "string",
      "subject": null,
      "body": null,
      "occurredAt": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null,
      "entityId": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "dealId": null,
      "dealTitle": null,
      "customValues": null,
      "activityTypeLabel": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/activities?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/activities`

Create activity

DEPRECATED (sunset 2026-06-30): Creates a timeline activity. Use POST /api/customers/interactions instead.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "00000000-0000-4000-8000-000000000000",
  "activityType": "string",
  "phoneNumber": null,
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**201** – Activity created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/activities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"activityType\": \"string\",
  \"phoneNumber\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## PUT `/customers/activities`

Update activity

DEPRECATED (sunset 2026-06-30): Updates an activity. Use PUT /api/customers/interactions instead.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "phoneNumber": null,
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**200** – Activity updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/activities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"phoneNumber\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## DELETE `/customers/addresses`

Delete address

Deletes an address by id. The identifier may be included in the body or query.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Address deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/addresses`

List addresss

Returns a paginated collection of addresss scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| entityId | query | any | Optional |
| id | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated addresss

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entity_id": "00000000-0000-4000-8000-000000000000",
      "name": null,
      "purpose": null,
      "company_name": null,
      "address_line1": null,
      "address_line2": null,
      "building_number": null,
      "flat_number": null,
      "city": null,
      "region": null,
      "postal_code": null,
      "country": null,
      "latitude": null,
      "longitude": null,
      "is_primary": null,
      "organization_id": null,
      "tenant_id": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/addresses?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/addresses`

Create address

Creates a customer address record and associates it with the referenced entity.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "addressLine1": "string",
  "latitude": null,
  "longitude": null
}
```

### Responses

**201** – Address created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"addressLine1\": \"string\",
  \"latitude\": null,
  \"longitude\": null
}"
```

## PUT `/customers/addresses`

Update address

Updates fields on an existing customer address.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "latitude": null,
  "longitude": null
}
```

### Responses

**200** – Address updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"latitude\": null,
  \"longitude\": null
}"
```

## GET `/customers/assignable-staff`

DEPRECATED: use GET /api/staff/team-members/assignable instead.

Deprecated. Returns 308 Permanent Redirect to /api/staff/team-members/assignable preserving the query string. Will be removed no earlier than the next major release.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |

### Responses

**200** – Assignable staff members (only reachable by following the redirect).

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "teamMemberId": "00000000-0000-4000-8000-000000000000",
      "userId": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "email": null,
      "teamName": null,
      "user": null,
      "team": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

**308** – Permanent redirect to /api/staff/team-members/assignable.

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/assignable-staff?page=1&pageSize=24" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/customers/comments`

Delete comment

Deletes a comment identified by `id` supplied via body or query string.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Comment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/comments`

List comments

Returns a paginated collection of comments scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| entityId | query | any | Optional |
| dealId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated comments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entity_id": null,
      "deal_id": null,
      "body": null,
      "author_user_id": null,
      "appearance_icon": null,
      "appearance_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/comments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/comments`

Create comment

Adds a comment to a customer timeline.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "body": "string",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**201** – Comment created

Content-Type: `application/json`

```json
{
  "id": null,
  "authorUserId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## PUT `/customers/comments`

Update comment

Updates an existing timeline comment.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**200** – Comment updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## DELETE `/customers/companies`

Delete company

Deletes a company by id. The identifier can be provided via body or query.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Company deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**422** – Company has dependent records (people, deals, or direct staff); unlink or reassign before delete.

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "COMPANY_HAS_DEPENDENTS"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/companies`

List companies

Returns a paginated collection of companies scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| email | query | any | Optional |
| emailStartsWith | query | any | Optional |
| emailContains | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| status | query | any | Optional |
| lifecycleStage | query | any | Optional |
| source | query | any | Optional |
| hasEmail | query | any | Optional |
| hasPhone | query | any | Optional |
| hasNextInteraction | query | any | Optional |
| createdFrom | query | any | Optional |
| createdTo | query | any | Optional |
| id | query | any | Optional |
| tagIds | query | any | Optional |
| tagIdsEmpty | query | any | Optional |
| excludeIds | query | any | Optional |
| excludeLinkedPersonId | query | any | Optional |
| excludeLinkedCompanyId | query | any | Optional |
| excludeLinkedDealId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated companies

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "description": null,
      "owner_user_id": null,
      "primary_email": null,
      "primary_phone": null,
      "status": null,
      "lifecycle_stage": null,
      "source": null,
      "next_interaction_at": null,
      "next_interaction_name": null,
      "next_interaction_ref_id": null,
      "next_interaction_icon": null,
      "next_interaction_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/companies?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/companies`

Create company

Creates a company record and associated profile data.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "displayName": "string",
  "description": null,
  "primaryEmail": null,
  "primaryPhone": null,
  "nextInteraction": null,
  "legalName": null,
  "brandName": null,
  "domain": null,
  "websiteUrl": null,
  "sizeBucket": null,
  "annualRevenue": null
}
```

### Responses

**201** – Company created

Content-Type: `application/json`

```json
{
  "id": null,
  "companyId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"displayName\": \"string\",
  \"description\": null,
  \"primaryEmail\": null,
  \"primaryPhone\": null,
  \"nextInteraction\": null,
  \"legalName\": null,
  \"brandName\": null,
  \"domain\": null,
  \"websiteUrl\": null,
  \"sizeBucket\": null,
  \"annualRevenue\": null
}"
```

## PUT `/customers/companies`

Update company

Updates company profile fields, tags, or custom attributes.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "primaryEmail": null,
  "primaryPhone": null,
  "nextInteraction": null,
  "legalName": null,
  "brandName": null,
  "domain": null,
  "websiteUrl": null,
  "sizeBucket": null,
  "annualRevenue": null
}
```

### Responses

**200** – Company updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"primaryEmail\": null,
  \"primaryPhone\": null,
  \"nextInteraction\": null,
  \"legalName\": null,
  \"brandName\": null,
  \"domain\": null,
  \"websiteUrl\": null,
  \"sizeBucket\": null,
  \"annualRevenue\": null
}"
```

## GET `/customers/companies/{id}`

Fetch company with related data

Returns a company customer record with optional related resources such as addresses, comments, activities, interactions, deals, todos, and linked people.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| include | query | any | Optional. Comma-separated list of relations to include (addresses, comments, activities, interactions, deals, todos, people). |

### Responses

**200** – Company detail payload

Content-Type: `application/json`

```json
{
  "interactionMode": "canonical",
  "company": {
    "id": "00000000-0000-4000-8000-000000000000",
    "displayName": null,
    "description": null,
    "ownerUserId": null,
    "primaryEmail": null,
    "primaryPhone": null,
    "status": null,
    "lifecycleStage": null,
    "source": null,
    "nextInteractionAt": null,
    "nextInteractionName": null,
    "nextInteractionRefId": null,
    "nextInteractionIcon": null,
    "nextInteractionColor": null,
    "organizationId": null,
    "tenantId": null,
    "temperature": null,
    "renewalQuarter": null,
    "createdAt": "string",
    "updatedAt": "string"
  },
  "profile": null,
  "customFields": {},
  "tags": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "color": null
    }
  ],
  "addresses": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": null,
      "purpose": null,
      "addressLine1": null,
      "addressLine2": null,
      "buildingNumber": null,
      "flatNumber": null,
      "city": null,
      "region": null,
      "postalCode": null,
      "country": null,
      "latitude": null,
      "longitude": null,
      "isPrimary": null,
      "createdAt": "string"
    }
  ],
  "comments": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "body": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "dealId": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null
    }
  ],
  "activities": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "activityType": "string",
      "subject": null,
      "body": null,
      "occurredAt": null,
      "dealId": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null
    }
  ],
  "interactions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityId": null,
      "interactionType": "string",
      "title": null,
      "body": null,
      "status": "string",
      "scheduledAt": null,
      "occurredAt": null,
      "priority": null,
      "authorUserId": null,
      "ownerUserId": null,
      "dealId": null,
      "organizationId": null,
      "tenantId": null,
      "authorName": null,
      "authorEmail": null,
      "dealTitle": null,
      "customValues": null,
      "appearanceIcon": null,
      "appearanceColor": null,
      "source": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "deals": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "status": null,
      "pipelineStage": null,
      "valueAmount": null,
      "valueCurrency": null,
      "probability": null,
      "expectedCloseAt": null,
      "ownerUserId": null,
      "source": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "todos": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "todoId": "00000000-0000-4000-8000-000000000000",
      "todoSource": "string",
      "createdAt": "string",
      "createdByUserId": null,
      "title": null,
      "isDone": null,
      "priority": null,
      "severity": null,
      "description": null,
      "dueAt": null,
      "todoOrganizationId": null,
      "customValues": null
    }
  ],
  "people": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": null,
      "primaryEmail": null,
      "primaryPhone": null,
      "status": null,
      "lifecycleStage": null,
      "jobTitle": null,
      "department": null,
      "createdAt": "string",
      "organizationId": null,
      "source": null,
      "temperature": null,
      "linkedAt": null
    }
  ],
  "viewer": {
    "userId": null,
    "name": null,
    "email": null
  }
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden — caller lacks the required feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Company not found, or its organization is not in the caller’s scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/companies/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/companies/{id}/people`

List linked people for a company

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sort | query | any | Optional |

### Responses

**200** – Paginated linked people

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "primaryEmail": null,
      "primaryPhone": null,
      "status": null,
      "lifecycleStage": null,
      "jobTitle": null,
      "department": null,
      "createdAt": "string",
      "organizationId": null,
      "temperature": null,
      "source": null,
      "linkedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/companies/:id/people?page=1&pageSize=20&sort=name-asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/customers/companies/{id}/roles`

Remove a company role assignment

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| roleId | query | any | Required |

### Responses

**200** – Role deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/companies/00000000-0000-4000-8000-000000000000/roles?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/companies/{id}/roles`

List roles for a company

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Role assignments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityType": "company",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "userId": "00000000-0000-4000-8000-000000000000",
      "userName": null,
      "userEmail": null,
      "userPhone": null,
      "roleType": "string",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/companies/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/companies/{id}/roles`

Assign a role to a company

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "roleType": "string",
  "userId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Role created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Role already assigned

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/companies/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleType\": \"string\",
  \"userId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/customers/companies/{id}/roles`

Update a company role assignment

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| roleId | query | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "userId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Role updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/companies/00000000-0000-4000-8000-000000000000/roles?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"userId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/dashboard/widgets/customer-todos`

Fetch recent customer tasks

Returns the most recent customer tasks for display on dashboards, including legacy compatibility rows when needed.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |

### Responses

**200** – Widget payload

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "todoId": "00000000-0000-4000-8000-000000000000",
      "todoSource": "string",
      "todoTitle": null,
      "createdAt": "string",
      "organizationId": null,
      "entity": {
        "id": null,
        "displayName": null,
        "kind": null,
        "ownerUserId": null
      }
    }
  ]
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Requested scope is not accessible

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Widget failed to load

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dashboard/widgets/customer-todos?limit=5" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/dashboard/widgets/new-customers`

Fetch recently created customers

Returns the latest customers created within the scoped tenant/organization for dashboard display.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |
| kind | query | any | Optional |

### Responses

**200** – Widget payload

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": null,
      "kind": null,
      "organizationId": null,
      "createdAt": "string",
      "ownerUserId": null
    }
  ]
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Requested scope is not accessible

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Widget failed to load

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dashboard/widgets/new-customers?limit=5" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/dashboard/widgets/new-deals`

Fetch recently created deals

Returns the latest deals created within the scoped tenant/organization for dashboard display.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |

### Responses

**200** – Widget payload

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "status": null,
      "organizationId": null,
      "createdAt": "string",
      "ownerUserId": null,
      "valueAmount": null,
      "valueCurrency": null
    }
  ]
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Requested scope is not accessible

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Widget failed to load

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dashboard/widgets/new-deals?limit=5" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/dashboard/widgets/next-interactions`

Fetch upcoming customer interactions

Lists upcoming (or optionally past) customer interaction reminders ordered by interaction date.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |
| includePast | query | any | Optional |

### Responses

**200** – Widget payload

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": null,
      "kind": null,
      "organizationId": null,
      "nextInteractionAt": null,
      "nextInteractionName": null,
      "nextInteractionIcon": null,
      "nextInteractionColor": null,
      "ownerUserId": null
    }
  ],
  "now": "string"
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Requested scope is not accessible

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Widget failed to load

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dashboard/widgets/next-interactions?limit=5" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/customers/deals`

Delete deal

Deletes a deal by `id`. The identifier may be provided in the body or query parameters.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Deal deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/deals" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/deals`

List deals

Returns a paginated collection of deals scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| status | query | any | Optional |
| pipelineStage | query | any | Optional |
| pipelineId | query | any | Optional |
| pipelineStageId | query | any | Optional |
| ownerUserId | query | any | Optional |
| expectedCloseAtFrom | query | any | Optional |
| expectedCloseAtTo | query | any | Optional |
| isStuck | query | any | Optional |
| isOverdue | query | any | Optional |
| needsAttention | query | any | Optional |
| valueCurrency | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| personEntityId | query | any | Optional. Deprecated; use personId |
| companyEntityId | query | any | Optional. Deprecated; use companyId |
| personId | query | any | Optional |
| companyId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated deals

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "description": null,
      "status": null,
      "pipeline_stage": null,
      "pipeline_id": null,
      "pipeline_stage_id": null,
      "value_amount": null,
      "value_currency": null,
      "probability": null,
      "expected_close_at": null,
      "owner_user_id": null,
      "source": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null,
      "organizationId": null,
      "tenantId": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/deals`

Create deal

Creates a sales deal, optionally associating people and companies.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "ownerUserId": null,
  "primaryPersonEntityId": null
}
```

### Responses

**201** – Deal created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/deals" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"title\": \"string\",
  \"ownerUserId\": null,
  \"primaryPersonEntityId\": null
}"
```

## PUT `/customers/deals`

Update deal

Updates pipeline position, metadata, or associations for an existing deal.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "ownerUserId": null,
  "primaryPersonEntityId": null
}
```

### Responses

**200** – Deal updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/deals" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"ownerUserId\": null,
  \"primaryPersonEntityId\": null
}"
```

## GET `/customers/deals/{id}`

Fetch deal with associations and pipeline context

Returns a deal with linked people, companies, closure fields, optional pipeline history, custom fields, and viewer context.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| include | query | any | Optional |

### Responses

**200** – Deal detail payload

Content-Type: `application/json`

```json
{
  "deal": {
    "id": "00000000-0000-4000-8000-000000000000",
    "title": null,
    "description": null,
    "status": null,
    "pipelineStage": null,
    "pipelineId": null,
    "pipelineStageId": null,
    "valueAmount": null,
    "valueCurrency": null,
    "probability": null,
    "expectedCloseAt": null,
    "ownerUserId": null,
    "source": null,
    "closureOutcome": null,
    "lossReasonId": null,
    "lossNotes": null,
    "organizationId": null,
    "tenantId": null,
    "createdAt": "string",
    "updatedAt": "string"
  },
  "people": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "subtitle": null,
      "kind": "person"
    }
  ],
  "companies": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "subtitle": null,
      "kind": "company"
    }
  ],
  "customFields": {},
  "viewer": {
    "userId": null,
    "name": null,
    "email": null
  },
  "pipelineStages": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "order": 1,
      "color": null,
      "icon": null
    }
  ],
  "stageTransitions": [
    {
      "stageId": "00000000-0000-4000-8000-000000000000",
      "stageLabel": "string",
      "stageOrder": 1,
      "transitionedAt": "string"
    }
  ],
  "owner": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden — caller lacks the required feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Deal not found, or its organization is not in the caller’s scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/deals/{id}/companies`

List linked companies for a deal

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sort | query | any | Optional |

### Responses

**200** – Paginated linked companies

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "subtitle": null,
      "kind": "company",
      "linkedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/:id/companies?page=1&pageSize=20&sort=label-asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/deals/{id}/people`

List linked people for a deal

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sort | query | any | Optional |

### Responses

**200** – Paginated linked people

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "subtitle": null,
      "kind": "person",
      "linkedAt": "string",
      "isPrimary": true
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/:id/people?page=1&pageSize=20&sort=label-asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/deals/{id}/stats`

Fetch analytics for a closed deal

Returns week-to-date closure counts, sales cycle length, quarter ranking, and loss reason context for a closed deal.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Deal closure stats payload

Content-Type: `application/json`

```json
{
  "dealValue": null,
  "dealCurrency": null,
  "closureOutcome": "won",
  "closedAt": "string",
  "pipelineName": null,
  "dealsClosedThisPeriod": 1,
  "salesCycleDays": null,
  "dealRankInQuarter": null,
  "lossReason": null
}
```

**400** – Deal is not closed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden — caller lacks the required feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Deal not found, or its organization is not in the caller’s scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/:id/stats" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/deals/aggregate`

Per-stage counts and currency totals for kanban lane headers

Returns per-stage counts and totals for deals, with values converted to the tenant base currency where rates are available. Used to power kanban lane headers without loading every deal.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| pipelineId | query | any | Optional |
| search | query | any | Optional |
| status | query | any | Optional |
| ownerUserId | query | any | Optional |
| personId | query | any | Optional |
| companyId | query | any | Optional |
| isStuck | query | any | Optional |
| isOverdue | query | any | Optional |
| expectedCloseAtFrom | query | any | Optional |
| expectedCloseAtTo | query | any | Optional |

### Responses

**200** – Per-stage aggregate payload

Content-Type: `application/json`

```json
{
  "baseCurrencyCode": null,
  "perStage": [
    {
      "stageId": "string",
      "count": 1,
      "openCount": 1,
      "totalInBaseCurrency": 1,
      "byCurrency": [
        {
          "currency": "string",
          "total": 1,
          "count": 1
        }
      ],
      "convertedAll": true,
      "missingRateCurrencies": [
        "string"
      ]
    }
  ]
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/aggregate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/deals/bulk-update-owner`

Bulk reassign deal owner

Queues a background job that reassigns the listed deals to a new owner (or clears the owner when null).

**Tags:** Customer Relationship Management

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/deals/bulk-update-owner" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/deals/bulk-update-stage`

Bulk update deal pipeline stage

Queues a background job that moves the listed deals to the same pipeline stage. Returns a progress job id to poll for completion.

**Tags:** Customer Relationship Management

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/deals/bulk-update-stage" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/deals/map`

Paginated deals that have a resolvable map location

Returns a page of deals that have a coordinate-bearing linked company/person address, each enriched with one resolved location (company primary first, then earliest created; person addresses as fallback). Deals with no coordinate-bearing address are excluded entirely, so every item carries a non-null location in normal operation; the schema keeps location nullable only for the rare case where the address is deleted between the located-deal resolution and the page fetch.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| status | query | any | Optional |
| pipelineStage | query | any | Optional |
| pipelineId | query | any | Optional |
| pipelineStageId | query | any | Optional |
| ownerUserId | query | any | Optional |
| expectedCloseAtFrom | query | any | Optional |
| expectedCloseAtTo | query | any | Optional |
| isStuck | query | any | Optional |
| isOverdue | query | any | Optional |
| needsAttention | query | any | Optional |
| valueCurrency | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| personEntityId | query | any | Optional. Deprecated; use personId |
| companyEntityId | query | any | Optional. Deprecated; use companyId |
| personId | query | any | Optional |
| companyId | query | any | Optional |

### Responses

**200** – Paged located deals

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "status": null,
      "pipelineId": null,
      "pipelineStageId": null,
      "pipelineStage": null,
      "valueAmount": null,
      "valueCurrency": null,
      "probability": null,
      "expectedCloseAt": null,
      "ownerUserId": null,
      "updatedAt": null,
      "companies": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "label": null
        }
      ],
      "people": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "label": null
        }
      ],
      "location": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing required features

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/map?page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/deals/summary`

Pipeline KPI metrics with period-over-period deltas for the deals list

Returns the four list-level KPI cards (pipeline value, active deals, won this quarter, win rate) with quarter-over-quarter deltas, per-stage open-pipeline breakdown, top owners, and a 6-month win-rate series. Values are converted to the tenant base currency where rates are available; partial conversions are disclosed via convertedAll/missingRateCurrencies.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Deals KPI summary payload

Content-Type: `application/json`

```json
{
  "baseCurrencyCode": null,
  "convertedAll": true,
  "missingRateCurrencies": [
    "string"
  ],
  "pipelineValue": {
    "value": 1,
    "delta": {
      "value": 1,
      "direction": "up"
    },
    "stages": [
      {
        "stage": null,
        "count": 1,
        "value": 1
      }
    ]
  },
  "activeDeals": {
    "value": 1,
    "delta": {
      "value": 1,
      "direction": "up"
    },
    "ownersCount": 1,
    "needAttention": 1,
    "owners": [
      {
        "id": "string",
        "count": 1
      }
    ],
    "ownersOverflow": 1
  },
  "wonThisQuarter": {
    "value": 1,
    "delta": {
      "value": 1,
      "direction": "up"
    },
    "dealsClosed": 1,
    "avgDeal": 1
  },
  "winRate": {
    "value": 1,
    "deltaPp": 1,
    "direction": "up",
    "previousValue": 1,
    "series": [
      {
        "period": "string",
        "rate": 1
      }
    ]
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/deals/summary" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/dictionaries/{kind}`

List dictionary entries

Returns dictionary entries for the requested kind within the currently selected organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| kind | path | any | Required |

### Responses

**200** – Dictionary entries

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null,
      "color": null,
      "icon": null,
      "organizationId": null
    }
  ]
}
```

**400** – Failed to resolve dictionary context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dictionaries/:kind" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/dictionaries/{kind}`

Create or override dictionary entry

Creates a dictionary entry (or updates the existing entry for the same value) within the current organization scope.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| kind | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "value": "string"
}
```

### Responses

**200** – Dictionary entry updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": null,
  "color": null,
  "icon": null,
  "organizationId": null
}
```

**201** – Dictionary entry created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": null,
  "color": null,
  "icon": null,
  "organizationId": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Duplicate value conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/dictionaries/:kind" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"value\": \"string\"
}"
```

## DELETE `/customers/dictionaries/{kind}/{id}`

Delete dictionary entry

Removes a customer dictionary entry by identifier.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| kind | path | any | Required |
| id | path | any | Required |

### Responses

**200** – Entry deleted

Content-Type: `application/json`

```json
{
  "success": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Entry not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Entry is in use and cannot be deleted

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/dictionaries/:kind/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/customers/dictionaries/{kind}/{id}`

Update dictionary entry

Updates value, label, color, or icon for an existing customer dictionary entry.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| kind | path | any | Required |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Updated dictionary entry

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": null,
  "color": null,
  "icon": null,
  "organizationId": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Entry not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Duplicate value conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/customers/dictionaries/:kind/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/customers/dictionaries/currency`

Resolve currency dictionary

Returns the active currency dictionary for the current organization scope, falling back to shared entries when required.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Currency dictionary entries

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "entries": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Currency dictionary missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dictionaries/currency" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/dictionaries/kind-settings`

List kind settings

Returns selection mode and visibility settings for each dictionary kind.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Kind settings

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "kind": "string",
      "selectionMode": "single",
      "visibleInTags": true,
      "sortOrder": 1
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/dictionaries/kind-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/customers/dictionaries/kind-settings`

Update kind setting

Creates or updates settings for a specific dictionary kind.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "kind": "string"
}
```

### Responses

**200** – Setting updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "kind": "string",
  "selectionMode": "single",
  "visibleInTags": true,
  "sortOrder": 1
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/customers/dictionaries/kind-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"kind\": \"string\"
}"
```

## DELETE `/customers/interactions`

Delete interaction

Soft-deletes an interaction identified by `id`. Accepts id via body or query string.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Interaction deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/interactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/interactions`

List interactions

Returns a paginated collection of interactions scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| cursor | query | any | Optional |
| entityId | query | any | Optional |
| dealId | query | any | Optional |
| status | query | any | Optional |
| interactionType | query | any | Optional |
| type | query | any | Optional |
| excludeInteractionType | query | any | Optional |
| search | query | any | Optional |
| from | query | any | Optional |
| to | query | any | Optional |
| recurrenceMasters | query | any | Optional |
| pinned | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated interactions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityId": null,
      "dealId": null,
      "interactionType": "string",
      "title": null,
      "body": null,
      "status": "string",
      "scheduledAt": null,
      "occurredAt": null,
      "priority": null,
      "authorUserId": null,
      "ownerUserId": null,
      "externalMessageId": null,
      "appearanceIcon": null,
      "appearanceColor": null,
      "source": null,
      "duration": null,
      "durationMinutes": null,
      "location": null,
      "allDay": null,
      "recurrenceRule": null,
      "recurrenceEnd": null,
      "participants": null,
      "reminderMinutes": null,
      "visibility": null,
      "linkedEntities": null,
      "guestPermissions": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": null,
      "updatedAt": null,
      "authorName": null,
      "authorEmail": null,
      "dealTitle": null,
      "customValues": null
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/interactions?limit=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/interactions`

Create interaction

Creates a new interaction linked to a customer entity or deal.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

No example available for this content type.

### Responses

**201** – Interaction created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/interactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/customers/interactions`

Update interaction

Updates fields for an existing interaction.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

No example available for this content type.

### Responses

**200** – Interaction updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/interactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/customers/interactions/{id}/visibility`

Flip an email interaction visibility (private ↔ shared)

**Tags:** Customers, Email

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Updated

Content-Type: `application/json`

**400** – Invalid id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Email not found or not visible to caller

Content-Type: `application/json`

**422** – Invalid body

Content-Type: `application/json`

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/customers/interactions/:id/visibility" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/interactions/cancel`

Cancel an interaction

Marks an interaction as canceled.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Interaction canceled

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Interaction not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/interactions/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/customers/interactions/complete`

Complete an interaction

Marks an interaction as done and sets occurredAt to current time (or a provided timestamp).

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Interaction completed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Interaction not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/interactions/complete" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/interactions/conflicts`

Detect scheduling conflicts

Checks for overlapping planned interactions within the requested time window.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| date | query | any | Required |
| startTime | query | any | Required |
| duration | query | any | Required |
| excludeId | query | any | Optional |
| userId | query | any | Optional |
| timezoneOffsetMinutes | query | any | Optional |

### Responses

**200** – Conflict detection result

Content-Type: `application/json`

```json
{
  "ok": true,
  "result": {
    "hasConflicts": true,
    "conflicts": [
      {
        "id": "string",
        "title": null,
        "startTime": "string",
        "endTime": "string",
        "type": "string"
      }
    ]
  }
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/interactions/conflicts?date=string&startTime=string&duration=1" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/interactions/counts`

Get interaction counts by type

Returns per-type interaction counts scoped to an entity.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Required |
| status | query | any | Optional |

### Responses

**200** – Counts by interaction type

Content-Type: `application/json`

```json
{
  "ok": true,
  "result": {
    "call": 1,
    "email": 1,
    "meeting": 1,
    "note": 1,
    "task": 1,
    "total": 1
  }
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/interactions/counts?entityId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/interactions/tasks`

List customertasks

Returns a paginated collection of customertasks scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| all | query | any | Optional |
| entityId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated customertasks

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "todoId": "string",
      "todoSource": "string",
      "todoTitle": null,
      "todoIsDone": null,
      "todoPriority": null,
      "todoSeverity": null,
      "todoDescription": null,
      "todoDueAt": null,
      "todoCustomValues": null,
      "todoOrganizationId": null,
      "organizationId": "string",
      "tenantId": "string",
      "createdAt": "string",
      "externalHref": null,
      "customer": {
        "id": null,
        "displayName": null,
        "kind": null
      }
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/interactions/tasks?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/labels`

List labels

Returns labels for the current user within the selected organization. Optionally includes assignment status for a specific entity.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Labels list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "slug": "string",
      "label": "string"
    }
  ],
  "assignedIds": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/labels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/labels`

Create label

Creates a new label scoped to the current user and selected organization.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "label": "string"
}
```

### Responses

**201** – Label created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "slug": "string",
  "label": "string"
}
```

**409** – Duplicate slug

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/labels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"label\": \"string\"
}"
```

## POST `/customers/labels/assign`

Assign label

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "labelId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Already assigned

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**201** – Assigned

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**404** – Label or entity not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/labels/assign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"labelId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/customers/labels/unassign`

Unassign label

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "labelId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Unassigned

Content-Type: `application/json`

```json
{
  "id": null
}
```

**404** – Label or entity not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/labels/unassign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"labelId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/customers/people`

Delete person

Deletes a person by id. Request body or query may provide the identifier.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Person deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**422** – Person has dependent records (e.g. linked deals); unlink or reassign before delete.

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "PERSON_HAS_DEPENDENTS"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/people" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/people`

List people

Returns a paginated collection of people scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| email | query | any | Optional |
| emailStartsWith | query | any | Optional |
| emailContains | query | any | Optional |
| status | query | any | Optional |
| lifecycleStage | query | any | Optional |
| source | query | any | Optional |
| hasEmail | query | any | Optional |
| hasPhone | query | any | Optional |
| hasNextInteraction | query | any | Optional |
| createdFrom | query | any | Optional |
| createdTo | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| id | query | any | Optional |
| tagIds | query | any | Optional |
| tagIdsEmpty | query | any | Optional |
| excludeIds | query | any | Optional |
| excludeLinkedCompanyId | query | any | Optional |
| excludeLinkedDealId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated people

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "description": null,
      "owner_user_id": null,
      "primary_email": null,
      "primary_phone": null,
      "status": null,
      "lifecycle_stage": null,
      "source": null,
      "next_interaction_at": null,
      "next_interaction_name": null,
      "next_interaction_ref_id": null,
      "next_interaction_icon": null,
      "next_interaction_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/people`

Create person

Creates a person contact using scoped organization and tenant identifiers.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "primaryEmail": null,
  "primaryPhone": null,
  "nextInteraction": null,
  "firstName": "string",
  "lastName": "string",
  "linkedInUrl": null,
  "twitterUrl": null,
  "companyEntityId": null
}
```

### Responses

**201** – Person created

Content-Type: `application/json`

```json
{
  "id": null,
  "personId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/people" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"primaryEmail\": null,
  \"primaryPhone\": null,
  \"nextInteraction\": null,
  \"firstName\": \"string\",
  \"lastName\": \"string\",
  \"linkedInUrl\": null,
  \"twitterUrl\": null,
  \"companyEntityId\": null
}"
```

## PUT `/customers/people`

Update person

Updates contact details or custom fields for a person.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "primaryEmail": null,
  "primaryPhone": null,
  "nextInteraction": null,
  "linkedInUrl": null,
  "twitterUrl": null,
  "companyEntityId": null
}
```

### Responses

**200** – Person updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/people" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"primaryEmail\": null,
  \"primaryPhone\": null,
  \"nextInteraction\": null,
  \"linkedInUrl\": null,
  \"twitterUrl\": null,
  \"companyEntityId\": null
}"
```

## GET `/customers/people/{id}`

Fetch person with related data

Returns a person customer record with optional related resources such as addresses, comments, activities, interactions, deals, and todos.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| include | query | any | Optional. Comma-separated list of relations to include (addresses, comments, activities, interactions, deals, todos). |

### Responses

**200** – Person detail payload

Content-Type: `application/json`

```json
{
  "interactionMode": "canonical",
  "person": {
    "id": "00000000-0000-4000-8000-000000000000",
    "displayName": null,
    "description": null,
    "ownerUserId": null,
    "primaryEmail": null,
    "primaryPhone": null,
    "status": null,
    "lifecycleStage": null,
    "source": null,
    "nextInteractionAt": null,
    "nextInteractionName": null,
    "nextInteractionRefId": null,
    "nextInteractionIcon": null,
    "nextInteractionColor": null,
    "organizationId": null,
    "tenantId": null,
    "createdAt": "string",
    "updatedAt": "string"
  },
  "profile": null,
  "customFields": {},
  "tags": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "color": null
    }
  ],
  "addresses": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": null,
      "purpose": null,
      "addressLine1": null,
      "addressLine2": null,
      "buildingNumber": null,
      "flatNumber": null,
      "city": null,
      "region": null,
      "postalCode": null,
      "country": null,
      "latitude": null,
      "longitude": null,
      "isPrimary": null,
      "createdAt": "string"
    }
  ],
  "comments": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "body": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "dealId": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null
    }
  ],
  "activities": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "activityType": "string",
      "subject": null,
      "body": null,
      "occurredAt": null,
      "dealId": null,
      "authorUserId": null,
      "authorName": null,
      "authorEmail": null,
      "createdAt": "string",
      "appearanceIcon": null,
      "appearanceColor": null
    }
  ],
  "interactions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityId": null,
      "interactionType": "string",
      "title": null,
      "body": null,
      "status": "string",
      "scheduledAt": null,
      "occurredAt": null,
      "priority": null,
      "authorUserId": null,
      "ownerUserId": null,
      "dealId": null,
      "organizationId": null,
      "tenantId": null,
      "authorName": null,
      "authorEmail": null,
      "dealTitle": null,
      "customValues": null,
      "appearanceIcon": null,
      "appearanceColor": null,
      "source": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "deals": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "status": null,
      "pipelineStage": null,
      "valueAmount": null,
      "valueCurrency": null,
      "probability": null,
      "expectedCloseAt": null,
      "ownerUserId": null,
      "source": null,
      "closureOutcome": null,
      "lossReasonId": null,
      "lossNotes": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "todos": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "todoId": "00000000-0000-4000-8000-000000000000",
      "todoSource": "string",
      "createdAt": "string",
      "createdByUserId": null,
      "title": null,
      "isDone": null,
      "priority": null,
      "severity": null,
      "description": null,
      "dueAt": null,
      "todoOrganizationId": null,
      "customValues": null
    }
  ],
  "isPrimary": true,
  "companies": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "isPrimary": true
    }
  ],
  "viewer": {
    "userId": null,
    "name": null,
    "email": null
  }
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden — caller lacks the required feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Person not found, or its organization is not in the caller’s scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/people/{id}/companies`

List linked companies for a person

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Linked company rows

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "companyId": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "isPrimary": true
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people/:id/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/people/{id}/companies`

Link a company to a person

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "companyId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Linked company row

Content-Type: `application/json`

```json
{
  "ok": true,
  "result": {
    "id": "00000000-0000-4000-8000-000000000000",
    "companyId": "00000000-0000-4000-8000-000000000000",
    "displayName": "string",
    "isPrimary": true
  }
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/people/:id/companies" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"companyId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/customers/people/{id}/companies/{linkId}`

Remove a linked company from a person

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| linkId | path | any | Required |

### Responses

**200** – Deletion result

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/people/:id/companies/:linkId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/customers/people/{id}/companies/{linkId}`

Update a linked company for a person

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| linkId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Updated company link

Content-Type: `application/json`

```json
{
  "ok": true,
  "result": null
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/customers/people/:id/companies/:linkId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/customers/people/{id}/companies/enriched`

Get enriched company data for a person's linked companies

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sort | query | any | Optional |

### Responses

**200** – Enriched company rows with profile, billing, tags, deals and more

Content-Type: `application/json`

```json
{
  "items": [
    {
      "linkId": "00000000-0000-4000-8000-000000000000",
      "companyId": "00000000-0000-4000-8000-000000000000",
      "displayName": "string",
      "isPrimary": true,
      "subtitle": null,
      "profile": null,
      "billing": null,
      "primaryAddress": null,
      "tags": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "label": "string",
          "color": null
        }
      ],
      "roles": [
        {
          "id": "00000000-0000-4000-8000-000000000000",
          "roleValue": "string"
        }
      ],
      "activeDeal": null,
      "lastContactAt": null,
      "clv": null,
      "status": null,
      "lifecycleStage": null,
      "temperature": null,
      "renewalQuarter": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people/:id/companies/enriched?page=1&pageSize=20&sort=name-asc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/people/{id}/email-threads`

List a Person's email threads (Gmail-style conversation grouping)

**Tags:** Customers, Email

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Email threads for the person, grouped by conversation

Content-Type: `application/json`

**400** – Invalid person id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Missing customers.people.view feature

Content-Type: `application/json`

**404** – Person not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people/:id/email-threads" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/people/{id}/emails`

Compose + send an email anchored to a Person

**Tags:** Customers, Email

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Email queued for send

Content-Type: `application/json`

**400** – Invalid person id

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**403** – Missing customers.email.compose feature or mutation guard rejection

Content-Type: `application/json`

**404** – Person or channel not found

Content-Type: `application/json`

**409** – Channel not connected

Content-Type: `application/json`

**422** – Invalid request body

Content-Type: `application/json`

**500** – Send failed

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/people/:id/emails" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/customers/people/{id}/roles`

Remove a person role assignment

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| roleId | query | any | Required |

### Responses

**200** – Role deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/people/00000000-0000-4000-8000-000000000000/roles?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/customers/people/{id}/roles`

List roles for a person

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Role assignments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityType": "company",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "userId": "00000000-0000-4000-8000-000000000000",
      "userName": null,
      "userEmail": null,
      "userPhone": null,
      "roleType": "string",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/people/{id}/roles`

Assign a role to a person

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "roleType": "string",
  "userId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Role created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Role already assigned

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/people/00000000-0000-4000-8000-000000000000/roles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleType\": \"string\",
  \"userId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/customers/people/{id}/roles`

Update a person role assignment

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| roleId | query | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "userId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Role updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/people/00000000-0000-4000-8000-000000000000/roles?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"userId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/people/check-phone`

Find person by phone digits

Performs an exact digits comparison (stripping non-numeric characters) to determine whether a customer contact matches the provided phone fragment.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| digits | query | any | Required |

### Responses

**200** – Matching contact (if any)

Content-Type: `application/json`

```json
{
  "match": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/people/check-phone" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/customers/pipeline-stages`

Delete pipeline stage

Deletes a pipeline stage. Returns 409 if active deals use this stage.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Stage deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**404** – Stage not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Stage has active deals

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/pipeline-stages" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/pipeline-stages`

List pipeline stages

Returns pipeline stages for the authenticated organization, optionally filtered by pipelineId.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| pipelineId | query | any | Optional |

### Responses

**200** – Stage list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "pipelineId": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "order": 1,
      "color": null,
      "icon": null,
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ],
  "total": 1
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/pipeline-stages" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/pipeline-stages`

Create pipeline stage

Creates a new pipeline stage.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "pipelineId": "00000000-0000-4000-8000-000000000000",
  "label": "string",
  "color": null,
  "icon": null
}
```

### Responses

**201** – Stage created

Content-Type: `application/json`

```json
{
  "id": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/pipeline-stages" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"pipelineId\": \"00000000-0000-4000-8000-000000000000\",
  \"label\": \"string\",
  \"color\": null,
  \"icon\": null
}"
```

## PUT `/customers/pipeline-stages`

Update pipeline stage

Updates an existing pipeline stage.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "color": null,
  "icon": null
}
```

### Responses

**200** – Stage updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Stage not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/pipeline-stages" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"color\": null,
  \"icon\": null
}"
```

## POST `/customers/pipeline-stages/reorder`

Reorder pipeline stages

Updates the order of pipeline stages in bulk.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "stages": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "order": 1
    }
  ]
}
```

### Responses

**200** – Stages reordered

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/pipeline-stages/reorder" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"stages\": [
    {
      \"id\": \"00000000-0000-4000-8000-000000000000\",
      \"order\": 1
    }
  ]
}"
```

## DELETE `/customers/pipelines`

Delete pipeline

Deletes a pipeline. Returns 409 if active deals exist.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Pipeline deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**404** – Pipeline not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Pipeline has active deals

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/pipelines" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/pipelines`

List pipelines

Returns a list of pipelines scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| isDefault | query | any | Optional |

### Responses

**200** – Pipeline list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "isDefault": true,
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ],
  "total": 1
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/pipelines" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/pipelines`

Create pipeline

Creates a new pipeline within the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string"
}
```

### Responses

**201** – Pipeline created

Content-Type: `application/json`

```json
{
  "id": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/pipelines" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\"
}"
```

## PUT `/customers/pipelines`

Update pipeline

Updates an existing pipeline.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Pipeline updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Pipeline not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/pipelines" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/settings/address-format`

Retrieve address format

Returns the current address formatting preference for the selected organization.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Current address format

Content-Type: `application/json`

```json
{
  "addressFormat": "string"
}
```

**400** – Organization context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/settings/address-format" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/customers/settings/address-format`

Update address format

Updates the address format preference for the selected organization.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "addressFormat": "line_first"
}
```

### Responses

**200** – Updated address format

Content-Type: `application/json`

```json
{
  "addressFormat": "string"
}
```

**400** – Invalid payload or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/settings/address-format" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"addressFormat\": \"line_first\"
}"
```

## GET `/customers/settings/dictionary-sort-modes`

Retrieve dictionary sort modes

Returns entry sort preferences for customer dictionaries in the selected organization.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Current dictionary sort modes

Content-Type: `application/json`

```json
{
  "dictionarySortModes": {
    "key": "label_asc"
  }
}
```

**400** – Organization context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/settings/dictionary-sort-modes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/customers/settings/dictionary-sort-modes`

Update dictionary sort modes

Updates entry sort preferences for customer dictionaries in the selected organization.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "dictionarySortModes": {
    "key": "label_asc"
  }
}
```

### Responses

**200** – Updated dictionary sort modes

Content-Type: `application/json`

```json
{
  "dictionarySortModes": {
    "key": "label_asc"
  }
}
```

**400** – Invalid payload or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/customers/settings/dictionary-sort-modes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"dictionarySortModes\": {
    \"key\": \"label_asc\"
  }
}"
```

## GET `/customers/settings/stuck-threshold`

Retrieve stuck-threshold days

Returns the current stuck-deal threshold (in days) for the selected organization.

**Tags:** Customers

**Requires authentication.**

### Responses

**200** – Current threshold

Content-Type: `application/json`

```json
{
  "stuckThresholdDays": 1
}
```

**400** – Organization context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/settings/stuck-threshold" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/customers/settings/stuck-threshold`

Update stuck-threshold days

Updates the stuck-deal threshold for the selected organization.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "stuckThresholdDays": 1
}
```

### Responses

**200** – Updated threshold

Content-Type: `application/json`

```json
{
  "stuckThresholdDays": 1
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/settings/stuck-threshold" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"stuckThresholdDays\": 1
}"
```

## DELETE `/customers/tags`

Delete tag

Deletes a tag identified by `id`. The identifier may be provided via body or query string.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Tag deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/tags`

List tags

Returns a paginated collection of tags scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated tags

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "slug": "string",
      "label": "string",
      "color": null,
      "description": null,
      "organization_id": null,
      "tenant_id": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/tags?page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/tags`

Create tag

Creates a tag scoped to the current tenant and organization.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "slug": "string",
  "label": "string"
}
```

### Responses

**201** – Tag created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"slug\": \"string\",
  \"label\": \"string\"
}"
```

## PUT `/customers/tags`

Update tag

Updates label, color, or description for an existing tag.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Tag updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/customers/tags/assign`

Assign tag to customer entity

Links a tag to a customer entity within the validated tenant / organization scope.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "tagId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Tag assigned to customer

Content-Type: `application/json`

```json
{
  "id": null
}
```

**400** – Validation or assignment failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient tenant/organization access

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/tags/assign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"tagId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/customers/tags/unassign`

Remove tag from customer entity

Detaches a tag from a customer entity within the validated tenant / organization scope.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "tagId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Tag unassigned from customer

Content-Type: `application/json`

```json
{
  "id": null
}
```

**400** – Validation or unassignment failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient tenant/organization access

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/tags/unassign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"tagId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/customers/todos`

Delete customertodo

DEPRECATED (sunset 2026-06-30): Deletes a customer task. Use DELETE /api/customers/interactions instead.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – CustomerTodo deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/customers/todos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/customers/todos`

List customertodos

Returns a paginated collection of customertodos scoped to the authenticated organization.

**Tags:** Customers

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| all | query | any | Optional |
| entityId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated customertodos

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "todoId": "string",
      "todoSource": "string",
      "todoTitle": null,
      "todoIsDone": null,
      "todoPriority": null,
      "todoSeverity": null,
      "todoDescription": null,
      "todoDueAt": null,
      "todoCustomValues": null,
      "todoOrganizationId": null,
      "todoUpdatedAt": null,
      "organizationId": "string",
      "tenantId": "string",
      "createdAt": "string",
      "externalHref": null,
      "customer": {
        "id": null,
        "displayName": null,
        "kind": null
      }
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/customers/todos?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/customers/todos`

Create customertodo

DEPRECATED (sunset 2026-06-30): Creates a customer task. Use POST /api/customers/interactions instead.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "todoSource": "customers:interaction"
}
```

### Responses

**201** – CustomerTodo created

Content-Type: `application/json`

```json
{
  "linkId": null,
  "todoId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/customers/todos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"title\": \"string\",
  \"todoSource\": \"customers:interaction\"
}"
```

## PUT `/customers/todos`

Update customertodo

DEPRECATED (sunset 2026-06-30): Updates a customer task. Use PUT /api/customers/interactions instead.

**Tags:** Customers

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – CustomerTodo updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/customers/todos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/dashboards/layout`

Load the current dashboard layout

Returns the saved widget layout together with the widgets the current user is allowed to place.

**Tags:** Dashboards

**Requires authentication.**

### Responses

**200** – Current dashboard layout and available widgets.

Content-Type: `application/json`

```json
{
  "layout": {
    "items": [
      {
        "id": "00000000-0000-4000-8000-000000000000",
        "widgetId": "string",
        "order": 1
      }
    ]
  },
  "allowedWidgetIds": [
    "string"
  ],
  "canConfigure": true,
  "context": {
    "userId": "00000000-0000-4000-8000-000000000000",
    "tenantId": null,
    "organizationId": null,
    "userName": null,
    "userEmail": null,
    "userLabel": "string"
  },
  "widgets": [
    {
      "id": "string",
      "title": "string",
      "description": null,
      "defaultSize": "sm",
      "defaultEnabled": true,
      "defaultSettings": null,
      "features": [
        "string"
      ],
      "moduleId": "string",
      "icon": null,
      "loaderKey": "string",
      "supportsRefresh": true
    }
  ]
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dashboards/layout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/dashboards/layout`

Persist dashboard layout changes

Saves the provided widget ordering, sizes, and settings for the current user.

**Tags:** Dashboards

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "widgetId": "string",
      "order": 1
    }
  ]
}
```

### Responses

**200** – Layout updated successfully.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid layout payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing dashboards.configure feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Widget registry unavailable — the layout was not saved

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/dashboards/layout" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"items\": [
    {
      \"id\": \"00000000-0000-4000-8000-000000000000\",
      \"widgetId\": \"string\",
      \"order\": 1
    }
  ]
}"
```

## PATCH `/dashboards/layout/{itemId}`

Update a dashboard layout item

Adjusts the size or settings for a single widget within the dashboard layout.

**Tags:** Dashboards

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| itemId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Layout item updated.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload or missing item id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing dashboards.configure feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Item not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/dashboards/layout/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/dashboards/roles/widgets`

Fetch widget assignments for a role

Returns the widgets explicitly assigned to the given role together with the evaluation scope.

**Tags:** Dashboards

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| roleId | query | any | Required |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |

### Responses

**200** – Current widget configuration for the role.

Content-Type: `application/json`

```json
{
  "widgetIds": [
    "string"
  ],
  "hasCustom": true,
  "scope": {
    "tenantId": null,
    "organizationId": null
  }
}
```

**400** – Missing role identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions to manage role widgets

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dashboards/roles/widgets?roleId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/dashboards/roles/widgets`

Update widgets assigned to a role

Persists the widget list for a role within the provided tenant and organization scope.

**Tags:** Dashboards

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "roleId": "00000000-0000-4000-8000-000000000000",
  "widgetIds": [
    "string"
  ]
}
```

### Responses

**200** – Widgets updated successfully.

Content-Type: `application/json`

```json
{
  "ok": true,
  "widgetIds": [
    "string"
  ]
}
```

**400** – Invalid payload or unknown widgets

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions to manage role widgets

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/dashboards/roles/widgets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"roleId\": \"00000000-0000-4000-8000-000000000000\",
  \"widgetIds\": [
    \"string\"
  ]
}"
```

## GET `/dashboards/users/widgets`

Read widget overrides for a user

Returns the widgets inherited and explicitly configured for the requested user within the current scope.

**Tags:** Dashboards

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| userId | query | any | Required |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |

### Responses

**200** – Widget settings for the user.

Content-Type: `application/json`

```json
{
  "mode": "inherit",
  "widgetIds": [
    "string"
  ],
  "hasCustom": true,
  "effectiveWidgetIds": [
    "string"
  ],
  "scope": {
    "tenantId": null,
    "organizationId": null
  }
}
```

**400** – Missing user identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions to manage user widgets

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dashboards/users/widgets?userId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/dashboards/users/widgets`

Update user-specific dashboard widgets

Sets the widget override mode and allowed widgets for a user. Passing `mode: inherit` clears overrides.

**Tags:** Dashboards

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "userId": "00000000-0000-4000-8000-000000000000",
  "mode": "inherit",
  "widgetIds": [
    "string"
  ]
}
```

### Responses

**200** – Overrides saved.

Content-Type: `application/json`

```json
{
  "ok": true,
  "mode": "inherit",
  "widgetIds": [
    "string"
  ]
}
```

**400** – Invalid payload or unknown widgets

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions to manage user widgets

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/dashboards/users/widgets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"userId\": \"00000000-0000-4000-8000-000000000000\",
  \"mode\": \"inherit\",
  \"widgetIds\": [
    \"string\"
  ]
}"
```

## GET `/dashboards/widgets/catalog`

List available dashboard widgets

Returns the catalog of widgets that modules expose, including defaults and feature requirements.

**Tags:** Dashboards

**Requires authentication.**

### Responses

**200** – Widgets available for assignment.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "description": null,
      "defaultSize": "sm",
      "defaultEnabled": true,
      "defaultSettings": null,
      "features": [
        "string"
      ],
      "moduleId": "string",
      "icon": null,
      "loaderKey": "string",
      "supportsRefresh": true
    }
  ]
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions to view widget catalog

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dashboards/widgets/catalog" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/dashboards/widgets/data`

Fetch aggregated data for dashboard widgets

Executes an aggregation query against the specified entity type and returns the result. Supports date range filtering, grouping, and period-over-period comparison.

**Tags:** Dashboards

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityType": "string",
  "metric": {
    "field": "string",
    "aggregate": "count"
  }
}
```

### Responses

**200** – Aggregated data for the widget.

Content-Type: `application/json`

```json
{
  "value": null,
  "data": [
    {
      "value": null
    }
  ],
  "metadata": {
    "fetchedAt": "string",
    "recordCount": 1,
    "currency": null
  }
}
```

**400** – Invalid request payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing analytics.view feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Too many rows to group an encrypted field in application code

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Encryption is configured but the group source cannot currently be resolved

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/dashboards/widgets/data" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\",
  \"metric\": {
    \"field\": \"string\",
    \"aggregate\": \"count\"
  }
}"
```

## POST `/dashboards/widgets/data/batch`

Fetch aggregated data for multiple dashboard widgets in one request

Resolves a batch of widget data requests with a single authentication, RBAC, organization-scope, and database-context setup. Each request is keyed by an opaque widget id and resolved independently, so a failure in one widget does not fail the batch.

**Tags:** Dashboards

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "requests": [
    {
      "id": "string",
      "request": {
        "entityType": "string",
        "metric": {
          "field": "string",
          "aggregate": "count"
        }
      }
    }
  ]
}
```

### Responses

**200** – Per-widget aggregation results keyed by request id.

Content-Type: `application/json`

```json
{
  "results": [
    {
      "id": "string",
      "ok": true,
      "data": {
        "value": null,
        "data": [
          {
            "value": null
          }
        ],
        "metadata": {
          "fetchedAt": "string",
          "recordCount": 1,
          "currency": null
        }
      }
    }
  ]
}
```

**400** – Invalid request payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/dashboards/widgets/data/batch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"requests\": [
    {
      \"id\": \"string\",
      \"request\": {
        \"entityType\": \"string\",
        \"metric\": {
          \"field\": \"string\",
          \"aggregate\": \"count\"
        }
      }
    }
  ]
}"
```

## GET `/data_sync/mappings`

List or create field mappings

**Tags:** Data Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/data_sync/mappings`

List or create field mappings

**Tags:** Data Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/data_sync/mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/data_sync/mappings/{id}`

Get, update, or delete a field mapping

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/data_sync/mappings/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/data_sync/mappings/{id}`

Get, update, or delete a field mapping

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/mappings/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/data_sync/mappings/{id}`

Get, update, or delete a field mapping

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/data_sync/mappings/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/data_sync/options`

List data sync integration options

**Tags:** Data Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/options" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/data_sync/run`

Start a data sync run

**Tags:** Data Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/data_sync/run" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/data_sync/runs`

List sync runs

**Tags:** Data Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/runs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/data_sync/runs/{id}`

Get sync run detail

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/runs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/data_sync/runs/{id}/cancel`

Cancel a running sync

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/data_sync/runs/:id/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/data_sync/runs/{id}/retry`

Retry a failed sync run

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/data_sync/runs/:id/retry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/data_sync/schedules`

List or create sync schedules

**Tags:** Data Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/schedules" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/data_sync/schedules`

List or create sync schedules

**Tags:** Data Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/data_sync/schedules" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/data_sync/schedules/{id}`

Manage a sync schedule

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/data_sync/schedules/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/data_sync/schedules/{id}`

Manage a sync schedule

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/data_sync/schedules/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/data_sync/schedules/{id}`

Manage a sync schedule

**Tags:** Data Sync

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/data_sync/schedules/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/data_sync/validate`

Validate sync connection

**Tags:** Data Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/data_sync/validate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/devices`

List devices

Returns the authenticated user's registered devices (admins may list across users). Response keys are camelCase. The snake_case keys (`user_id`, `device_id`, `last_seen_at`, …) are deprecated aliases of their camelCase counterparts, retained for one minor version and removed in the next; read `userId`, `deviceId`, `lastSeenAt`, … instead.

**Tags:** Devices

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| platform | query | any | Optional |
| userId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated devices

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": null,
      "userId": "00000000-0000-4000-8000-000000000000",
      "deviceId": "string",
      "platform": "ios",
      "clientAppVersion": null,
      "osVersion": null,
      "locale": null,
      "pushProvider": null,
      "pushTokenUpdatedAt": null,
      "lastSeenAt": null,
      "createdAt": null,
      "updatedAt": null,
      "tenant_id": "00000000-0000-4000-8000-000000000000",
      "organization_id": null,
      "user_id": "00000000-0000-4000-8000-000000000000",
      "device_id": "string",
      "client_app_version": null,
      "os_version": null,
      "push_provider": null,
      "push_token_updated_at": null,
      "last_seen_at": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/devices?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/devices`

Create device

Registers (or idempotently upserts) the current user's device for the given deviceId. May include an initial push token.

**Tags:** Devices

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "deviceId": "string",
  "platform": "ios",
  "clientAppVersion": null,
  "osVersion": null,
  "locale": null,
  "pushToken": null,
  "pushProvider": null
}
```

### Responses

**201** – Device created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "deviceId": "string",
  "revived": true
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/devices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"deviceId\": \"string\",
  \"platform\": \"ios\",
  \"clientAppVersion\": null,
  \"osVersion\": null,
  \"locale\": null,
  \"pushToken\": null,
  \"pushProvider\": null
}"
```

## DELETE `/devices/{id}`

Deactivate your device

Soft-deletes a device owned by the current user.

**Tags:** Devices

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Device deactivated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Not the device owner

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Device not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/devices/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/devices/{id}`

Update your device

Updates last-seen, app/OS metadata, and push token for a device owned by the current user. Set pushToken to null to clear a revoked OS permission.

**Tags:** Devices

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "clientAppVersion": null,
  "osVersion": null,
  "locale": null,
  "pushToken": null,
  "pushProvider": null
}
```

### Responses

**200** – Device updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload or id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Not the device owner

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Device not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/devices/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"clientAppVersion\": null,
  \"osVersion\": null,
  \"locale\": null,
  \"pushToken\": null,
  \"pushProvider\": null
}"
```

## GET `/devices/admin/devices`

List devices (admin)

Returns the authenticated user's registered devices (admin) (admins may list across users). Response keys are camelCase. The snake_case keys (`user_id`, `device_id`, `last_seen_at`, …) are deprecated aliases of their camelCase counterparts, retained for one minor version and removed in the next; read `userId`, `deviceId`, `lastSeenAt`, … instead.

**Tags:** Devices

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| platform | query | any | Optional |
| userId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated devices (admin)

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": null,
      "userId": "00000000-0000-4000-8000-000000000000",
      "deviceId": "string",
      "platform": "ios",
      "clientAppVersion": null,
      "osVersion": null,
      "locale": null,
      "pushProvider": null,
      "pushTokenUpdatedAt": null,
      "lastSeenAt": null,
      "createdAt": null,
      "updatedAt": null,
      "tenant_id": "00000000-0000-4000-8000-000000000000",
      "organization_id": null,
      "user_id": "00000000-0000-4000-8000-000000000000",
      "device_id": "string",
      "client_app_version": null,
      "os_version": null,
      "push_provider": null,
      "push_token_updated_at": null,
      "last_seen_at": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/devices/admin/devices?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/devices/admin/devices`

Create device (admin)

Admin: register (idempotently upsert) a device on behalf of any user in the tenant.

**Tags:** Devices

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "deviceId": "string",
  "platform": "ios",
  "clientAppVersion": null,
  "osVersion": null,
  "locale": null,
  "pushToken": null,
  "pushProvider": null,
  "userId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Device (admin) created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "deviceId": "string",
  "revived": true
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/devices/admin/devices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"deviceId\": \"string\",
  \"platform\": \"ios\",
  \"clientAppVersion\": null,
  \"osVersion\": null,
  \"locale\": null,
  \"pushToken\": null,
  \"pushProvider\": null,
  \"userId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/devices/admin/devices/{id}`

Deactivate any device

Admin: soft-delete any device in the tenant.

**Tags:** Devices (admin)

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Device deactivated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing devices.admin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Device not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/devices/admin/devices/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/devices/admin/devices/{id}`

Get any device

Admin: fetch a single device by id (push_token is never returned). Response keys are camelCase. The snake_case keys (`user_id`, `device_id`, `last_seen_at`, …) are deprecated aliases of their camelCase counterparts, retained for one minor version and removed in the next; read `userId`, `deviceId`, `lastSeenAt`, … instead.

**Tags:** Devices (admin)

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Device

Content-Type: `application/json`

```json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "userId": "00000000-0000-4000-8000-000000000000",
    "deviceId": "string",
    "platform": "ios",
    "clientAppVersion": null,
    "osVersion": null,
    "pushProvider": null,
    "pushTokenUpdatedAt": null,
    "lastSeenAt": null,
    "createdAt": null,
    "updatedAt": null,
    "user_id": "00000000-0000-4000-8000-000000000000",
    "device_id": "string",
    "client_app_version": null,
    "os_version": null,
    "push_provider": null,
    "push_token_updated_at": null,
    "last_seen_at": null,
    "created_at": null,
    "updated_at": null
  }
}
```

**400** – Invalid id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing devices.admin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Device not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/devices/admin/devices/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/devices/admin/devices/{id}`

Update any device

Admin: update last-seen, app/OS metadata, and push token for any device. Set pushToken to null to clear it.

**Tags:** Devices (admin)

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "clientAppVersion": null,
  "osVersion": null,
  "locale": null,
  "pushToken": null,
  "pushProvider": null
}
```

### Responses

**200** – Device updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload or id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing devices.admin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Device not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/devices/admin/devices/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"clientAppVersion\": null,
  \"osVersion\": null,
  \"locale\": null,
  \"pushToken\": null,
  \"pushProvider\": null
}"
```

## GET `/dictionaries`

List dictionaries

Returns dictionaries accessible to the current organization, optionally including inactive records.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| includeInactive | query | any | Optional |

### Responses

**200** – Dictionary collection.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "key": "string",
      "name": "string",
      "description": null,
      "isSystem": true,
      "isActive": true,
      "managerVisibility": null,
      "organizationId": null,
      "createdAt": "string",
      "updatedAt": null
    }
  ]
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to load dictionaries

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dictionaries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/dictionaries`

Create dictionary

Registers a dictionary scoped to the current organization.

**Tags:** Dictionaries

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "key": "string",
  "name": "string"
}
```

### Responses

**201** – Dictionary created.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "key": "string",
  "name": "string",
  "description": null,
  "isSystem": true,
  "isActive": true,
  "managerVisibility": null,
  "organizationId": null,
  "createdAt": "string",
  "updatedAt": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Dictionary key already exists

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to create dictionary

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/dictionaries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"key\": \"string\",
  \"name\": \"string\"
}"
```

## DELETE `/dictionaries/{dictionaryId}`

Delete dictionary

Soft deletes the dictionary unless it is the protected currency dictionary.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |

### Responses

**200** – Dictionary archived.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Protected dictionary cannot be deleted

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to delete dictionary

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/dictionaries/{dictionaryId}`

Get dictionary

Returns details for the specified dictionary, including inheritance flags.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |

### Responses

**200** – Dictionary details.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "key": "string",
  "name": "string",
  "description": null,
  "isSystem": true,
  "isActive": true,
  "managerVisibility": null,
  "organizationId": null,
  "createdAt": "string",
  "updatedAt": null
}
```

**400** – Invalid parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to load dictionary

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/dictionaries/{dictionaryId}`

Update dictionary

Updates mutable attributes of the dictionary. Currency dictionaries are protected from modification.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Dictionary updated.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "key": "string",
  "name": "string",
  "description": null,
  "isSystem": true,
  "isActive": true,
  "managerVisibility": null,
  "organizationId": null,
  "createdAt": "string",
  "updatedAt": null
}
```

**400** – Validation failed or protected dictionary

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Dictionary key already exists

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to update dictionary

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/dictionaries/{dictionaryId}/entries`

List dictionary entries

Returns entries for the specified dictionary ordered by its configured entry sort mode. The number of entries returned per request is capped at 500; use `limit` and `offset` with the `total`/`hasMore` response fields to page through larger dictionaries.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |
| limit | query | any | Optional. Maximum entries to return. Defaults to and is capped at 500. |
| offset | query | any | Optional. Number of entries to skip. Defaults to 0. |

### Responses

**200** – Dictionary entries.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": "string",
      "color": null,
      "icon": null,
      "position": 1,
      "isDefault": true,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "total": 1,
  "limit": 1,
  "offset": 1,
  "hasMore": true,
  "sortMode": "label_asc"
}
```

**400** – Invalid parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to load dictionary entries

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000/entries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/dictionaries/{dictionaryId}/entries`

Create dictionary entry

Creates a new entry in the specified dictionary.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "value": "string",
  "color": null,
  "icon": null
}
```

### Responses

**201** – Dictionary entry created.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": "string",
  "color": null,
  "icon": null,
  "position": 1,
  "isDefault": true,
  "createdAt": "string",
  "updatedAt": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to create dictionary entry

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000/entries" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"value\": \"string\",
  \"color\": null,
  \"icon\": null
}"
```

## DELETE `/dictionaries/{dictionaryId}/entries/{entryId}`

Delete dictionary entry

Deletes the specified dictionary entry via the command bus.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |
| entryId | path | any | Required |

### Responses

**200** – Entry deleted.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary or entry not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to delete entry

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/dictionaries/{dictionaryId}/entries/{entryId}`

Update dictionary entry

Updates the specified dictionary entry using the command bus pipeline.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |
| entryId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "color": null,
  "icon": null
}
```

### Responses

**200** – Dictionary entry updated.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "label": "string",
  "color": null,
  "icon": null,
  "position": 1,
  "isDefault": true,
  "createdAt": "string",
  "updatedAt": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary or entry not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to update entry

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"color\": null,
  \"icon\": null
}"
```

## POST `/dictionaries/{dictionaryId}/entries/reorder`

Reorder dictionary entries

Updates the position of dictionary entries for drag-and-drop reordering.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "entries": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "position": 1
    }
  ]
}
```

### Responses

**200** – Entries reordered.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to reorder entries

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/reorder" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entries\": [
    {
      \"id\": \"00000000-0000-4000-8000-000000000000\",
      \"position\": 1
    }
  ]
}"
```

## POST `/dictionaries/{dictionaryId}/entries/set-default`

Set default dictionary entry

Marks the specified entry as the default for this dictionary, clearing any previous default.

**Tags:** Dictionaries

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| dictionaryId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "entryId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Default entry set.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Dictionary or entry not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to set default entry

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/dictionaries/00000000-0000-4000-8000-000000000000/entries/set-default" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entryId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/directory/organization-branding`

Read sidebar branding for the selected organization

Returns the logo URL used by the backend sidebar for the currently selected organization.

**Tags:** Directory

**Requires authentication.**

### Responses

**200** – Organization branding

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "organizationName": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "logoUrl": null,
  "logoPreserveAspectRatio": true,
  "updatedAt": null
}
```

**400** – A concrete organization scope is required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Organization not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/directory/organization-branding" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/directory/organization-branding`

Update sidebar branding for the selected organization

Stores an external image URL or an internal attachment image URL as the selected organization logo.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "logoUrl": null
}
```

### Responses

**200** – Updated organization branding

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "organizationName": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "logoUrl": null,
  "logoPreserveAspectRatio": true,
  "updatedAt": null
}
```

**400** – Save failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Organization branding changed since it was loaded

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid logo URL

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/directory/organization-branding" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"logoUrl\": null
}"
```

## GET `/directory/organization-switcher`

Load organization switcher menu

Returns the hierarchical menu of organizations the current user may switch to within the active tenant.

**Tags:** Directory

**Requires authentication.**

### Responses

**200** – Organization switcher payload.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "depth": 1,
      "selectable": true,
      "children": []
    }
  ],
  "selectedId": null,
  "canManage": true,
  "canViewAllOrganizations": true,
  "tenantId": null,
  "tenants": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "isActive": true
    }
  ],
  "isSuperAdmin": true
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/directory/organization-switcher" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/directory/organizations`

Delete organization

Soft deletes an organization identified by id.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Organization deleted.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing directory.organizations.manage feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/directory/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/directory/organizations`

List organizations

Returns organizations using options, tree, or paginated manage view depending on the `view` parameter.

**Tags:** Directory

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| view | query | any | Optional |
| ids | query | any | Optional |
| tenantId | query | any | Optional |
| includeInactive | query | any | Optional |
| status | query | any | Optional |

### Responses

**200** – Organization data for the requested view.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "parentId": null,
      "parentName": null,
      "tenantId": null,
      "tenantName": null,
      "rootId": null,
      "treePath": null
    }
  ]
}
```

**400** – Invalid query or tenant scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/directory/organizations?page=1&pageSize=50&view=options" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/directory/organizations`

Create organization

Creates a new organization within a tenant and optionally assigns hierarchy relationships.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "slug": null,
  "logoUrl": null,
  "parentId": null
}
```

### Responses

**201** – Organization created.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing directory.organizations.manage feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/directory/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"slug\": null,
  \"logoUrl\": null,
  \"parentId\": null
}"
```

## PUT `/directory/organizations`

Update organization

Updates organization details and hierarchy assignments.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "slug": null,
  "logoUrl": null,
  "parentId": null
}
```

### Responses

**200** – Organization updated.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing directory.organizations.manage feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/directory/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"slug\": null,
  \"logoUrl\": null,
  \"parentId\": null
}"
```

## GET `/directory/organizations/lookup`

Public organization lookup by slug

**Tags:** Directory (Tenants & Organizations)

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/directory/organizations/lookup" \
  -H "Accept: application/json"
```

## DELETE `/directory/tenants`

Delete tenant

Soft deletes the tenant identified by id.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Tenant removed.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing directory.tenants.manage feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/directory/tenants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/directory/tenants`

List tenants

Returns tenants visible to the current user with optional search and pagination.

**Tags:** Directory

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| isActive | query | any | Optional |

### Responses

**200** – Paged list of tenants.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "isActive": true,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Requires super-admin

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/directory/tenants?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/directory/tenants`

Create tenant

Creates a new tenant and returns its identifier.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string"
}
```

### Responses

**201** – Tenant created.

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing directory.tenants.manage feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/directory/tenants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\"
}"
```

## PUT `/directory/tenants`

Update tenant

Updates tenant properties such as name or activation state.

**Tags:** Directory

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Tenant updated.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing directory.tenants.manage feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/directory/tenants" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/directory/tenants/lookup`

Public tenant lookup

**Tags:** Directory (Tenants & Organizations)

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/directory/tenants/lookup" \
  -H "Accept: application/json"
```

## GET `/documents`

List visible documents

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| id | query | any | Optional |
| archived | query | any | Optional |
| favorite | query | any | Required |
| folderId | query | any | Optional |
| entityType | query | any | Optional |
| entityId | query | any | Optional |

### Responses

**200** – Visible document metadata

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": "string",
      "folderId": null,
      "ownerUserId": "00000000-0000-4000-8000-000000000000",
      "ownerLabel": null,
      "createdByUserId": "00000000-0000-4000-8000-000000000000",
      "isActive": true,
      "archivedAt": null,
      "isFavorite": true,
      "sharedWithCount": 1,
      "createdAt": "string",
      "updatedAt": "string",
      "relationshipTier": null,
      "capabilities": {
        "canView": true,
        "canComment": true,
        "canEdit": true,
        "canShare": true,
        "canDelete": true,
        "canCreate": true,
        "canManageTemplates": true,
        "canArchive": true,
        "canDuplicate": true
      }
    }
  ],
  "collectionCapabilities": {
    "canCreateDocument": true,
    "canCreateFolder": true,
    "canLinkDocuments": true,
    "canInstantiateTemplate": true,
    "canManageTemplates": true
  },
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents?page=1&pageSize=50&archived=exclude" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents`

Create document

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "title": "string",
  "folderId": null
}
```

### Responses

**201** – Document created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"title\": \"string\",
  \"folderId\": null
}"
```

## DELETE `/documents/{id}`

Delete document

Transactionally releases every document-owned attachment row and its quota usage, soft-deletes the document record, then runs reference-checked provider cleanup after commit. Because attachment bytes cannot be restored, this operation is intentionally not undoable.

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Document deleted

Content-Type: `application/json`

```json
{
  "ok": true,
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}`

Get document metadata

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Document metadata

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "folderId": null,
  "ownerUserId": "00000000-0000-4000-8000-000000000000",
  "createdByUserId": "00000000-0000-4000-8000-000000000000",
  "isActive": true,
  "archivedAt": null,
  "isFavorite": true,
  "isWatching": true,
  "createdAt": "string",
  "updatedAt": "string",
  "tier": "owner",
  "canShare": true,
  "capabilities": {
    "canView": true,
    "canComment": true,
    "canEdit": true,
    "canShare": true,
    "canDelete": true,
    "canCreate": true,
    "canManageTemplates": true,
    "canArchive": true,
    "canDuplicate": true
  }
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/documents/{id}`

Update document metadata

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "folderId": null
}
```

### Responses

**200** – Document updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"folderId\": null
}"
```

## POST `/documents/{id}/archive`

Archive a document, making it read-only and hidden from default listings

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Archived document state

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "archivedAt": null,
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Document not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Document changed concurrently

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/attachments`

Upload document attachment

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `multipart/form-data`

```text
file=string
```

### Responses

**201** – Document-scoped attachment uploaded

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "attachmentId": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "url": "string"
}
```

**400** – Payload validation error, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Attachment too large

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Attachment service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: multipart/form-data" \
  -d "{
  \"file\": \"string\"
}"
```

## DELETE `/documents/{id}/attachments/{attachmentId}`

Detach a document-scoped attachment

Transactionally removes the document attachment row and quota usage, then runs reference-checked provider cleanup after commit. This operation is audited and intentionally not undoable.

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| attachmentId | path | any | Required |

### Responses

**200** – Attachment deletion committed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict or attachment still referenced

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/attachments/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}/attachments/{attachmentId}`

Read a document-scoped attachment

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| attachmentId | path | any | Required |

### Responses

**200** – Attachment bytes

Content-Type: `application/json`

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Attachment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Partition misconfigured

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Attachment service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/attachments/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}/collab-token`

Mint document collaboration token

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Collaboration token

Content-Type: `application/json`

```json
{
  "token": "string",
  "url": null,
  "documentId": "string",
  "tier": "owner",
  "expiresInSec": 1,
  "expiresAt": "string",
  "userName": "string",
  "userColor": "string",
  "canEdit": true,
  "readOnly": true,
  "user": {
    "id": "string",
    "name": "string",
    "color": "string"
  }
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/collab-token" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}/comments`

List document comments

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Required |

### Responses

**200** – Threaded document comments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "documentId": "00000000-0000-4000-8000-000000000000",
      "parentCommentId": null,
      "authorUserId": "00000000-0000-4000-8000-000000000000",
      "body": "string",
      "anchor": null,
      "mentions": [
        {
          "userId": "00000000-0000-4000-8000-000000000000"
        }
      ],
      "resolvedAt": null,
      "resolvedByUserId": null,
      "createdAt": "string",
      "updatedAt": "string",
      "canResolve": true,
      "replies": []
    }
  ],
  "userLabels": {
    "key": {
      "label": "string"
    }
  },
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1,
  "totalComments": 1,
  "truncated": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/comments?page=1" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/documents/{id}/comments`

Resolve or unresolve document comment

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "resolved": true
}
```

### Responses

**200** – Comment resolution updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "resolvedAt": null,
  "resolvedByUserId": null,
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Comment not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"resolved\": true
}"
```

## POST `/documents/{id}/comments`

Create document comment

Mentions may be sent out-of-band as mentions: [{ userId }]. Legacy bracketed @[user-uuid] tokens in the comment body are still honored.

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "body": "string",
  "anchor": null,
  "parentCommentId": null
}
```

### Responses

**201** – Comment created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body or document comment limit exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"body\": \"string\",
  \"anchor\": null,
  \"parentCommentId\": null
}"
```

## POST `/documents/{id}/comments/access-check`

Check which mentioned users lack access

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "userIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

### Responses

**200** – Mention access check result

Content-Type: `application/json`

```json
{
  "withoutAccess": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "withoutAccessUsers": [
    {
      "userId": "00000000-0000-4000-8000-000000000000",
      "label": null,
      "secondary": null
    }
  ]
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/comments/access-check" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"userIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
```

## GET `/documents/{id}/content`

Get document content

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Document content

Content-Type: `application/json`

```json
{
  "contentHtml": "string",
  "contentText": "string",
  "updatedAt": null
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Stored document content exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/content" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/documents/{id}/content`

Update document content

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "contentHtml": "string",
  "contentText": null
}
```

### Responses

**200** – Content persisted

Content-Type: `application/json`

```json
{
  "ok": true,
  "updatedAt": null
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Content changed since it was loaded

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Document content exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/content" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"contentHtml\": \"string\",
  \"contentText\": null
}"
```

## POST `/documents/{id}/duplicate`

Create a copy of a visible document owned by the acting user

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**201** – Copy created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "copiedAttachments": 1,
  "copiedLinks": 1,
  "droppedLinks": 1
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Document not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Source exceeds the duplicate fanout bounds, or The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/duplicate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/documents/{id}/export`

Export document

Returns a binary .docx or PDF file attachment for a document.

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| format | query | any | Optional |

### Responses

**200** – Document export file

Content-Type: `application/octet-stream`

```text
string
```

**400** – Unsupported format, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Document or generated export exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Export runtime is unavailable, overloaded, or timed out

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/export" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/export`

Export a paginated DOCX document

Returns a DOCX attachment using the editor pagination snapshot supplied by the client.

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| format | query | any | Optional |

### Request Body

Content-Type: `application/json`

```json
{
  "contentHtml": "string",
  "pageBreakMarker": "string"
}
```

### Responses

**200** – Paginated DOCX export file

Content-Type: `application/vnd.openxmlformats-officedocument.wordprocessingml.document`

```text
string
```

**400** – Invalid pagination snapshot or unsupported format, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Document or generated export exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Export runtime is unavailable, overloaded, or timed out

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/export" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"contentHtml\": \"string\",
  \"pageBreakMarker\": \"string\"
}"
```

## DELETE `/documents/{id}/favorite`

Remove the current user star from a document

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Favorite state

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "active": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/favorite" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/favorite`

Star a document for the current user

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Favorite state

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "active": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Document not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/favorite" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}/links`

List entity links visible to the document viewer

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Document entity links

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityType": "customer-person",
      "entityId": null,
      "label": "string",
      "href": null,
      "canOpen": true,
      "archivedAt": null,
      "source": "chip",
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body or document link limit exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/links" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/links`

Link a document to an entity

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "entityType": "customer-person",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "label": "string",
  "href": "string",
  "source": "chip"
}
```

### Responses

**201** – Link created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "entityType": "customer-person",
  "entityId": null,
  "label": "string",
  "href": null,
  "canOpen": true,
  "archivedAt": null,
  "source": "chip",
  "createdAt": "string",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Document link limit exceeded

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Target lookup unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/links" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"customer-person\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"label\": \"string\",
  \"href\": \"string\",
  \"source\": \"chip\"
}"
```

## DELETE `/documents/{id}/links/{linkId}`

Soft-delete a document entity link

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| linkId | path | any | Required |

### Responses

**200** – Link deleted

Content-Type: `application/json`

```json
{
  "ok": true,
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Link not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/links/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}/principals`

List principals eligible for document mentions or sharing

Returns a bounded, document-authorized user or role page without requiring broad Auth administration grants.

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| mode | query | any | Optional |
| type | query | any | Optional |
| search | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Eligible principal page

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "secondary": null
    }
  ],
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
```

**400** – Invalid picker query, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Document capability denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/principals?mode=share&type=user&page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/documents/{id}/shares`

Remove document share

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Share removed

Content-Type: `application/json`

```json
{
  "ok": true,
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/shares" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/documents/{id}/shares`

List document shares

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Document shares

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "documentId": "00000000-0000-4000-8000-000000000000",
      "principalType": "user",
      "principalId": "00000000-0000-4000-8000-000000000000",
      "permission": "viewer",
      "createdByUserId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "principalLabel": null,
      "principalSecondary": null
    }
  ],
  "truncated": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/shares" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/shares`

Share document

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "principalType": "user",
  "principalId": "00000000-0000-4000-8000-000000000000",
  "permission": "viewer"
}
```

### Responses

**201** – Document shared

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/shares" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"principalType\": \"user\",
  \"principalId\": \"00000000-0000-4000-8000-000000000000\",
  \"permission\": \"viewer\"
}"
```

## PUT `/documents/{id}/shares`

Update document share

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "permission": "viewer"
}
```

### Responses

**200** – Share updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/shares" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"permission\": \"viewer\"
}"
```

## POST `/documents/{id}/unarchive`

Restore an archived document to its active editable state

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Active document state

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "archivedAt": null,
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Document not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Document changed concurrently

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/unarchive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/documents/{id}/versions`

List document versions

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Document version metadata

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "label": null,
      "createdByUserId": "00000000-0000-4000-8000-000000000000",
      "createdByLabel": null,
      "createdAt": "string"
    }
  ],
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/versions?page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/versions`

Create document version snapshot

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "label": null
}
```

### Responses

**201** – Version snapshot created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "label": null,
  "createdByUserId": "00000000-0000-4000-8000-000000000000",
  "createdAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body, document content, or version history exceeds its safe storage bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/versions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"label\": null
}"
```

## GET `/documents/{id}/versions/{versionId}`

Read a sanitized historical document preview

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| versionId | path | any | Required |

### Responses

**200** – Historical document preview

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "label": null,
  "creatorLabel": "string",
  "createdAt": "string",
  "contentHtml": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Version not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Version snapshot is invalid, or The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/versions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/versions/{versionId}/restore`

Restore and materialize a historical document version

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| versionId | path | any | Required |

### Responses

**200** – Restored document content

Content-Type: `application/json`

```json
{
  "contentHtml": "string",
  "contentText": "string",
  "updatedAt": "string",
  "restoredVersionId": "00000000-0000-4000-8000-000000000000",
  "preRestoreVersionId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Version or content not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Document content changed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Version snapshot is invalid, or The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/versions/00000000-0000-4000-8000-000000000000/restore" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/documents/{id}/watch`

Stop watching a document (allowed even after access loss)

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Watch state

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "active": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/watch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/{id}/watch`

Watch a document for activity notifications

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Watch state

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "active": true
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Document not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Watcher limit reached, or The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/00000000-0000-4000-8000-000000000000/watch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/documents/folders`

Delete document folder

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Folder deleted

Content-Type: `application/json`

```json
{
  "ok": true,
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/folders" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/documents/folders`

List document folders

**Tags:** Documents

**Requires authentication.**

### Responses

**200** – Folder tree

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "parentFolderId": null,
      "ownerUserId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "canEdit": true,
      "visibility": "owned",
      "children": []
    }
  ],
  "total": 1
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/folders" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/folders`

Create document folder

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "parentFolderId": null
}
```

### Responses

**201** – Folder created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/folders" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"parentFolderId\": null
}"
```

## PUT `/documents/folders`

Update document folder

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "parentFolderId": null
}
```

### Responses

**200** – Folder updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Invalid folder hierarchy, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/documents/folders" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"parentFolderId\": null
}"
```

## POST `/documents/instantiate`

Atomically create document metadata, content, and entity links

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "templateUpdatedAt": "string",
  "title": "string",
  "locale": "string",
  "effectiveDate": "string",
  "slots": [
    {
      "slot": "string",
      "entityType": "customer-person",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "href": "string",
      "values": {
        "key": "string"
      }
    }
  ],
  "templateId": "00000000-0000-4000-8000-000000000000",
  "folderId": null,
  "previewDigest": "string"
}
```

### Responses

**201** – Document instantiated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string",
  "links": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityType": "string",
      "label": "string",
      "href": "string"
    }
  ]
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Template or folder not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Preview or template revision changed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Target lookup unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/instantiate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"templateUpdatedAt\": \"string\",
  \"title\": \"string\",
  \"locale\": \"string\",
  \"effectiveDate\": \"string\",
  \"slots\": [
    {
      \"slot\": \"string\",
      \"entityType\": \"customer-person\",
      \"entityId\": \"00000000-0000-4000-8000-000000000000\",
      \"label\": \"string\",
      \"href\": \"string\",
      \"values\": {
        \"key\": \"string\"
      }
    }
  ],
  \"templateId\": \"00000000-0000-4000-8000-000000000000\",
  \"folderId\": null,
  \"previewDigest\": \"string\"
}"
```

## DELETE `/documents/templates`

Delete document template

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Template deleted

Content-Type: `application/json`

```json
{
  "ok": true,
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/documents/templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/documents/templates`

List document templates

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| search | query | any | Optional |
| isActive | query | any | Optional |
| includeBody | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Template list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "description": null,
      "contextSlots": null,
      "isActive": true,
      "updatedAt": "string",
      "createdAt": "string"
    }
  ],
  "total": 1,
  "capabilities": {
    "canManageTemplates": true
  },
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/templates`

Create document template

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "description": null,
  "bodyHtml": "string",
  "contextSlots": null
}
```

### Responses

**201** – Template created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"bodyHtml\": \"string\",
  \"contextSlots\": null
}"
```

## PUT `/documents/templates`

Update document template

**Tags:** Documents

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "contextSlots": null
}
```

### Responses

**200** – Template updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": "string"
}
```

**400** – Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/documents/templates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"contextSlots\": null
}"
```

## GET `/documents/templates/{templateId}`

Get a document template including its body

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| templateId | path | any | Required |

### Responses

**200** – Template detail

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "description": null,
  "bodyHtml": "string",
  "contextSlots": null,
  "isActive": true,
  "updatedAt": "string",
  "createdAt": "string"
}
```

**400** – Invalid template id, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Template not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/documents/templates/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/documents/templates/{templateId}/preview`

Render a template preview without writing data

**Tags:** Documents

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| templateId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "templateUpdatedAt": "string",
  "title": "string",
  "locale": "string",
  "effectiveDate": "string",
  "slots": [
    {
      "slot": "string",
      "entityType": "customer-person",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "label": "string",
      "href": "string",
      "values": {
        "key": "string"
      }
    }
  ]
}
```

### Responses

**200** – Rendered template preview

Content-Type: `application/json`

```json
{
  "contentHtml": "string",
  "unresolvedTokens": [
    "string"
  ],
  "templateUpdatedAt": "string",
  "previewDigest": "string"
}
```

**400** – Validation failed, or Organization scope could not be resolved (`code: organization_scope_required`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Template not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Template revision changed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Request body exceeds the safe resource bound

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – The selected organization no longer resolves (`code: organization_selection_invalid`)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Target lookup unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/documents/templates/00000000-0000-4000-8000-000000000000/preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"templateUpdatedAt\": \"string\",
  \"title\": \"string\",
  \"locale\": \"string\",
  \"effectiveDate\": \"string\",
  \"slots\": [
    {
      \"slot\": \"string\",
      \"entityType\": \"customer-person\",
      \"entityId\": \"00000000-0000-4000-8000-000000000000\",
      \"label\": \"string\",
      \"href\": \"string\",
      \"values\": {
        \"key\": \"string\"
      }
    }
  ]
}"
```

## DELETE `/entities/definitions`

Soft delete custom field definition

Marks the specified definition inactive and tombstones it for the current scope.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "key": "string"
}
```

### Responses

**200** – Definition deleted

Content-Type: `application/json`

```json
{
  "ok": true,
  "version": null
}
```

**400** – Missing entity id or key

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Definition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/entities/definitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"key\": \"string\"
}"
```

## GET `/entities/definitions`

List active custom field definitions

Returns active custom field definitions for the supplied entity ids, respecting tenant scope and tombstones.

**Tags:** Entities

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Optional |
| entityIds | query | any | Optional |
| fieldset | query | any | Optional |

### Responses

**200** – Definition list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "key": "string",
      "kind": "string",
      "label": "string",
      "entityId": "string"
    }
  ]
}
```

**400** – Missing entity id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/definitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/entities/definitions`

Upsert custom field definition

Creates or updates a custom field definition for the current tenant/org scope.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "key": "string",
  "kind": "text"
}
```

### Responses

**200** – Definition saved

Content-Type: `application/json`

```json
{
  "ok": true,
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "key": "string",
    "kind": "string",
    "configJson": {}
  }
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/entities/definitions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"key\": \"string\",
  \"kind\": \"text\"
}"
```

## POST `/entities/definitions.batch`

Save multiple custom field definitions

Creates or updates multiple definitions for a single entity in one transaction.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "definitions": [
    {
      "key": "string",
      "kind": "text"
    }
  ]
}
```

### Responses

**200** – Definitions saved

Content-Type: `application/json`

```json
{
  "ok": true,
  "version": null
}
```

**400** – Validation error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/entities/definitions.batch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"definitions\": [
    {
      \"key\": \"string\",
      \"kind\": \"text\"
    }
  ]
}"
```

## GET `/entities/definitions.manage`

Get management snapshot

Returns scoped custom field definitions (including inactive tombstones) for administration interfaces.

**Tags:** Entities

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Required |

### Responses

**200** – Scoped definitions and deleted keys

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "key": "string",
      "kind": "string",
      "configJson": null,
      "organizationId": null,
      "tenantId": null
    }
  ],
  "deletedKeys": [
    "string"
  ],
  "version": null
}
```

**400** – Missing entity id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication or feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/definitions.manage?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/entities/definitions.restore`

Restore definition

Reactivates a previously soft-deleted definition within the current tenant/org scope.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "key": "string"
}
```

### Responses

**200** – Definition restored

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing entity id or key

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Definition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/entities/definitions.restore" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"key\": \"string\"
}"
```

## GET `/entities/encryption`

Fetch encryption map

Returns the encrypted field map for the current tenant/organization scope.

**Tags:** Entities

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Required |

### Responses

**200** – Map

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "fields": [
    {
      "field": "string",
      "hashField": null
    }
  ],
  "updatedAt": null
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/encryption?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/entities/encryption`

Upsert encryption map

Creates or updates the encryption map for the current tenant/organization scope. Enforces optimistic locking when the caller sends the expected version header.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "tenantId": null,
  "organizationId": null,
  "fields": [
    {
      "field": "string",
      "hashField": null
    }
  ]
}
```

### Responses

**200** – Saved

Content-Type: `application/json`

```json
{
  "ok": true,
  "updatedAt": null
}
```

**409** – Optimistic-lock conflict (stale write)

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

**422** – Selected organization is unavailable

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "organization_selection_invalid"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/entities/encryption" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"tenantId\": null,
  \"organizationId\": null,
  \"fields\": [
    {
      \"field\": \"string\",
      \"hashField\": null
    }
  ]
}"
```

## DELETE `/entities/entities`

Soft delete custom entity

Marks the specified custom entity inactive within the current scope.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string"
}
```

### Responses

**200** – Entity deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing entity id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Entity not found in scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/entities/entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\"
}"
```

## GET `/entities/entities`

List available entities

Returns generated and custom entities scoped to the caller with field counts per entity.

**Tags:** Entities

**Requires authentication.**

### Responses

**200** – List of entities

Content-Type: `application/json`

```json
{
  "items": [
    {
      "entityId": "string",
      "source": "code",
      "label": "string",
      "count": 1
    }
  ]
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/entities/entities`

Upsert custom entity

Creates or updates a tenant/org scoped custom entity definition.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "label": "string",
  "description": null,
  "showInSidebar": false,
  "accessRestricted": false
}
```

### Responses

**200** – Entity saved

Content-Type: `application/json`

```json
{
  "ok": true,
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "entityId": "string",
    "label": "string"
  }
}
```

**400** – Validation error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/entities/entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"label\": \"string\",
  \"description\": null,
  \"showInSidebar\": false,
  \"accessRestricted\": false
}"
```

## GET `/entities/entity-settings`

Get custom entity settings

Returns the tenant-scoped default-restricted policy for new custom entities.

**Tags:** Entities

**Requires authentication.**

### Responses

**200** – Current settings

Content-Type: `application/json`

```json
{
  "newEntitiesRestrictedByDefault": true,
  "updatedAt": null
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/entity-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/entities/entity-settings`

Update custom entity settings

Sets the tenant-scoped default-restricted policy for new custom entities.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "newEntitiesRestrictedByDefault": true
}
```

### Responses

**200** – Updated settings

Content-Type: `application/json`

```json
{
  "ok": true,
  "newEntitiesRestrictedByDefault": true,
  "updatedAt": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "code": "string",
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/entities/entity-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"newEntitiesRestrictedByDefault\": true
}"
```

## DELETE `/entities/records`

Delete record

Soft deletes the specified record within the current tenant/org scope.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "recordId": "string"
}
```

### Responses

**200** – Record deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing entity id or record id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Record not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/entities/records" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"recordId\": \"string\"
}"
```

## GET `/entities/records`

List records

Returns paginated records for the supplied entity. Supports custom field filters, exports, and soft-delete toggles.

**Tags:** Entities

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Required |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| search | query | any | Optional |
| searchFields | query | any | Optional |
| withDeleted | query | any | Optional |
| format | query | any | Optional |
| exportScope | query | any | Optional |
| export_scope | query | any | Optional |
| all | query | any | Optional |
| full | query | any | Optional |

### Responses

**200** – Paginated records

Content-Type: `application/json`

```json
{
  "items": [
    {}
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Missing entity id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/records?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/entities/records`

Create record

Creates a record for the given entity. When `recordId` is omitted or not a UUID the data engine will generate one automatically.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "values": {}
}
```

### Responses

**200** – Record created

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/entities/records" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"values\": {}
}"
```

## PUT `/entities/records`

Update record

Updates an existing record. If the provided recordId is not a UUID the record will be created instead to support optimistic flows.

**Tags:** Entities

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityId": "string",
  "recordId": "string",
  "values": {}
}
```

### Responses

**200** – Record updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/entities/records" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityId\": \"string\",
  \"recordId\": \"string\",
  \"values\": {}
}"
```

## GET `/entities/relations/options`

List relation options

Returns up to 200 option entries for populating relation dropdowns, automatically resolving label fields when omitted. An entityId that matches neither an active custom entity nor a registered ORM entity yields an empty option list.

**Tags:** Entities

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Required |
| labelField | query | any | Optional |
| q | query | any | Optional |
| ids | query | any | Optional |
| routeContextFields | query | any | Optional |

### Responses

**200** – Option list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/relations/options?entityId=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/entities/sidebar-entities`

Get sidebar entities

Returns custom entities flagged with `showInSidebar` for the current tenant/org scope.

**Tags:** Entities

**Requires authentication.**

### Responses

**200** – Sidebar entities for navigation

Content-Type: `application/json`

```json
{
  "items": [
    {
      "entityId": "string",
      "label": "string",
      "href": "string"
    }
  ]
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/entities/sidebar-entities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/eudr/dashboard/widgets/compliance-overview`

Compliance overview

**Tags:** EUDR

**Requires authentication.**

### Responses

**200** – EUDR compliance overview metrics

Content-Type: `application/json`

```json
{
  "deadline": {
    "date": "2026-12-30",
    "daysLeft": 1
  },
  "statements": {
    "total": 1,
    "byStatus": {
      "key": 1
    },
    "notReady": 1,
    "missingReference": 1
  },
  "queues": {}
}
```

**400** – Invalid organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Compliance overview loading failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/dashboard/widgets/compliance-overview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/eudr/evidence-submissions`

Delete evidence submission

Deletes an EUDR supplier evidence submission by id. Request body or query may provide the identifier.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Evidence submission deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/eudr/evidence-submissions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/eudr/evidence-submissions`

List evidence submissions

Returns a paginated collection of evidence submissions scoped to the authenticated organization.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| commodity | query | any | Optional |
| status | query | any | Optional |
| supplierEntityId | query | any | Optional |
| statementId | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated evidence submissions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "supplierEntityId": null,
      "supplierSnapshot": null,
      "commodity": null,
      "productMappingId": null,
      "statementId": null,
      "originCountry": null,
      "geolocation": null,
      "quantityKg": null,
      "batchNumber": null,
      "harvestFrom": null,
      "harvestTo": null,
      "producerName": null,
      "status": null,
      "completenessScore": 1,
      "missingFields": [
        "string"
      ],
      "warnings": [
        "string"
      ],
      "notes": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/evidence-submissions?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/evidence-submissions`

Create evidence submission

Creates an EUDR supplier evidence submission for the scoped organization.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "supplierEntityId": "00000000-0000-4000-8000-000000000000",
  "supplierSnapshot": null,
  "commodity": "cattle",
  "productMappingId": null,
  "statementId": null,
  "originCountry": null,
  "geolocation": null,
  "quantityKg": null,
  "batchNumber": null,
  "harvestFrom": null,
  "harvestTo": null,
  "producerName": null,
  "notes": null
}
```

### Responses

**201** – Evidence submission created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/evidence-submissions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"supplierEntityId\": \"00000000-0000-4000-8000-000000000000\",
  \"supplierSnapshot\": null,
  \"commodity\": \"cattle\",
  \"productMappingId\": null,
  \"statementId\": null,
  \"originCountry\": null,
  \"geolocation\": null,
  \"quantityKg\": null,
  \"batchNumber\": null,
  \"harvestFrom\": null,
  \"harvestTo\": null,
  \"producerName\": null,
  \"notes\": null
}"
```

## PUT `/eudr/evidence-submissions`

Update evidence submission

Updates an EUDR supplier evidence submission.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "supplierSnapshot": null,
  "productMappingId": null,
  "statementId": null,
  "originCountry": null,
  "geolocation": null,
  "quantityKg": null,
  "batchNumber": null,
  "harvestFrom": null,
  "harvestTo": null,
  "producerName": null,
  "notes": null
}
```

### Responses

**200** – Evidence submission updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/eudr/evidence-submissions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"supplierSnapshot\": null,
  \"productMappingId\": null,
  \"statementId\": null,
  \"originCountry\": null,
  \"geolocation\": null,
  \"quantityKg\": null,
  \"batchNumber\": null,
  \"harvestFrom\": null,
  \"harvestTo\": null,
  \"producerName\": null,
  \"notes\": null
}"
```

## DELETE `/eudr/mitigation-actions`

Delete mitigation action

Deletes an EUDR mitigation action by id. Request body or query may provide the identifier.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Mitigation action deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/eudr/mitigation-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/eudr/mitigation-actions`

List mitigation actions

Returns a paginated collection of mitigation actions scoped to the authenticated organization.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| riskAssessmentId | query | any | Optional |
| status | query | any | Optional |
| actionType | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated mitigation actions

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "riskAssessmentId": null,
      "actionType": null,
      "title": null,
      "description": null,
      "status": null,
      "dueDate": null,
      "completedAt": null,
      "notes": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/mitigation-actions?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/mitigation-actions`

Create mitigation action

Creates an EUDR mitigation action for the scoped organization.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "riskAssessmentId": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "description": null,
  "dueDate": null,
  "notes": null
}
```

### Responses

**201** – Mitigation action created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/mitigation-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"riskAssessmentId\": \"00000000-0000-4000-8000-000000000000\",
  \"title\": \"string\",
  \"description\": null,
  \"dueDate\": null,
  \"notes\": null
}"
```

## PUT `/eudr/mitigation-actions`

Update mitigation action

Updates an EUDR mitigation action.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "dueDate": null,
  "notes": null
}
```

### Responses

**200** – Mitigation action updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/eudr/mitigation-actions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"dueDate\": null,
  \"notes\": null
}"
```

## DELETE `/eudr/plots`

Delete plot

Deletes an EUDR supplier plot by id. Request body or query may provide the identifier.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Plot deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/eudr/plots" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/eudr/plots`

List plots

Returns a paginated collection of plots scoped to the authenticated organization.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| supplierEntityId | query | any | Optional |
| plotType | query | any | Optional |
| isActive | query | any | Optional |
| originCountry | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated plots

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "supplierEntityId": null,
      "supplierSnapshot": null,
      "name": null,
      "externalId": null,
      "originCountry": null,
      "plotType": null,
      "areaHa": null,
      "geometry": null,
      "validationWarnings": [
        "string"
      ],
      "producerName": null,
      "isActive": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/plots?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/plots`

Create plot

Creates an EUDR supplier plot for the scoped organization.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "supplierEntityId": "00000000-0000-4000-8000-000000000000",
  "supplierSnapshot": null,
  "name": "string",
  "externalId": null,
  "description": null,
  "areaHa": null,
  "producerName": null
}
```

### Responses

**201** – Plot created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/plots" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"supplierEntityId\": \"00000000-0000-4000-8000-000000000000\",
  \"supplierSnapshot\": null,
  \"name\": \"string\",
  \"externalId\": null,
  \"description\": null,
  \"areaHa\": null,
  \"producerName\": null
}"
```

## PUT `/eudr/plots`

Update plot

Updates an EUDR supplier plot.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "supplierSnapshot": null,
  "externalId": null,
  "description": null,
  "areaHa": null,
  "producerName": null
}
```

### Responses

**200** – Plot updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/eudr/plots" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"supplierSnapshot\": null,
  \"externalId\": null,
  \"description\": null,
  \"areaHa\": null,
  \"producerName\": null
}"
```

## POST `/eudr/plots/import`

Import plots

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "supplierEntityId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Import result

Content-Type: `application/json`

```json
{
  "created": 1,
  "failed": [
    {
      "index": 1,
      "name": "string",
      "errorKey": "string"
    }
  ]
}
```

**400** – Invalid import payload

Content-Type: `application/json`

```json
{}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Plot import failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/plots/import" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"supplierEntityId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/eudr/product-mappings`

Delete product mapping

Deletes an EUDR product commodity mapping by id. Request body or query may provide the identifier.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Product mapping deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/eudr/product-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/eudr/product-mappings`

List product mappings

Returns a paginated collection of product mappings scoped to the authenticated organization.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| commodity | query | any | Optional |
| productId | query | any | Optional |
| isInScope | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated product mappings

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "productId": null,
      "productSnapshot": null,
      "commodity": null,
      "hsCode": null,
      "speciesScientificName": null,
      "speciesCommonName": null,
      "isInScope": null,
      "notes": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/product-mappings?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/product-mappings`

Create product mapping

Creates an EUDR product commodity mapping for the scoped organization.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "productId": "00000000-0000-4000-8000-000000000000",
  "productSnapshot": null,
  "commodity": "cattle",
  "hsCode": null,
  "speciesScientificName": null,
  "speciesCommonName": null,
  "notes": null
}
```

### Responses

**201** – Product mapping created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/product-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"productId\": \"00000000-0000-4000-8000-000000000000\",
  \"productSnapshot\": null,
  \"commodity\": \"cattle\",
  \"hsCode\": null,
  \"speciesScientificName\": null,
  \"speciesCommonName\": null,
  \"notes\": null
}"
```

## PUT `/eudr/product-mappings`

Update product mapping

Updates an EUDR product commodity mapping.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "productSnapshot": null,
  "hsCode": null,
  "speciesScientificName": null,
  "speciesCommonName": null,
  "notes": null
}
```

### Responses

**200** – Product mapping updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/eudr/product-mappings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"productSnapshot\": null,
  \"hsCode\": null,
  \"speciesScientificName\": null,
  \"speciesCommonName\": null,
  \"notes\": null
}"
```

## GET `/eudr/product-mappings/suggestions`

Product mapping suggestions

**Tags:** EUDR

**Requires authentication.**

### Responses

**200** – Suggested product mappings

Content-Type: `application/json`

```json
{
  "items": [
    {
      "productId": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "sku": null,
      "hsCode": "string",
      "suggestedCommodity": "cattle"
    }
  ]
}
```

**400** – Invalid organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Product mapping suggestions loading failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/product-mappings/suggestions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/product-mappings/suggestions/apply`

Apply mapping suggestions

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Apply result

Content-Type: `application/json`

```json
{
  "created": 1,
  "failed": [
    {
      "productId": "00000000-0000-4000-8000-000000000000",
      "errorKey": "string"
    }
  ]
}
```

**400** – Invalid apply payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Mapping suggestion apply failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/product-mappings/suggestions/apply" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/eudr/reports/annual`

Generate an annual EUDR due diligence report

Returns aggregate-only annual statement metrics. Country, risk, and mitigation blocks are omitted unless the caller holds their corresponding view features. Use format=csv for a statement-derived commodity export.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| year | query | any | Required |
| format | query | any | Optional |

### Responses

**200** – Annual EUDR due diligence report (JSON by default; with format=csv the same endpoint streams a statement-derived commodity table as text/csv)

Content-Type: `application/json`

```json
{
  "year": 1,
  "generatedAt": "string",
  "statements": {
    "total": 1,
    "byStatus": {
      "key": 1
    },
    "byCommodity": [
      {
        "commodity": "string",
        "count": 1,
        "quantityKg": "string",
        "supplementaryQuantities": [
          {
            "unit": "string",
            "quantity": "string"
          }
        ]
      }
    ]
  }
}
```

**400** – Invalid report query

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Annual report generation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/reports/annual?year=1&format=json" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/eudr/risk-assessments`

Delete risk assessment

Deletes an EUDR risk assessment by id. Request body or query may provide the identifier.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Risk assessment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/eudr/risk-assessments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/eudr/risk-assessments`

List risk assessments

Returns a paginated collection of risk assessments scoped to the authenticated organization.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| statementId | query | any | Optional |
| conclusion | query | any | Optional |
| overallTier | query | any | Optional |
| reviewDueBefore | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated risk assessments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "statementId": null,
      "statementTitle": null,
      "countryRisks": [
        {
          "country": "string",
          "tier": "string"
        }
      ],
      "overallTier": null,
      "criteria": {},
      "conclusion": null,
      "isSimplified": true,
      "assessedAt": null,
      "assessedByName": null,
      "reviewDueAt": null,
      "notes": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/risk-assessments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/risk-assessments`

Create risk assessment

Creates an EUDR risk assessment for the scoped organization.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "statementId": "00000000-0000-4000-8000-000000000000",
  "criteria": {
    "key": {
      "answer": "no_concern",
      "note": null
    }
  },
  "conclusion": "negligible",
  "reviewDueAt": null,
  "notes": null
}
```

### Responses

**201** – Risk assessment created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/risk-assessments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"statementId\": \"00000000-0000-4000-8000-000000000000\",
  \"criteria\": {
    \"key\": {
      \"answer\": \"no_concern\",
      \"note\": null
    }
  },
  \"conclusion\": \"negligible\",
  \"reviewDueAt\": null,
  \"notes\": null
}"
```

## PUT `/eudr/risk-assessments`

Update risk assessment

Updates an EUDR risk assessment.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "reviewDueAt": null,
  "notes": null
}
```

### Responses

**200** – Risk assessment updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/eudr/risk-assessments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"reviewDueAt\": null,
  \"notes\": null
}"
```

## DELETE `/eudr/statements`

Delete due diligence statement

Deletes an EUDR due diligence statement by id. Request body or query may provide the identifier.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Due diligence statement deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/eudr/statements" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/eudr/statements`

List due diligence statements

Returns a paginated collection of due diligence statements scoped to the authenticated organization.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| commodity | query | any | Optional |
| status | query | any | Optional |
| orderId | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated due diligence statements

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "title": null,
      "commodity": null,
      "referenceNumber": null,
      "verificationNumber": null,
      "status": null,
      "activityType": null,
      "actorRole": null,
      "quantityKg": null,
      "supplementaryUnit": null,
      "supplementaryQuantity": null,
      "orderId": null,
      "submittedAt": null,
      "referenceIssuedAt": null,
      "orderSnapshot": null,
      "notes": null,
      "latestRisk": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/statements?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/eudr/statements`

Create due diligence statement

Creates an EUDR due diligence statement for the scoped organization.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "title": "string",
  "commodity": "cattle",
  "referenceNumber": null,
  "verificationNumber": null,
  "activityType": null,
  "actorRole": null,
  "quantityKg": null,
  "supplementaryUnit": null,
  "supplementaryQuantity": null,
  "orderId": null,
  "orderSnapshot": null,
  "notes": null
}
```

### Responses

**201** – Due diligence statement created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/eudr/statements" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"title\": \"string\",
  \"commodity\": \"cattle\",
  \"referenceNumber\": null,
  \"verificationNumber\": null,
  \"activityType\": null,
  \"actorRole\": null,
  \"quantityKg\": null,
  \"supplementaryUnit\": null,
  \"supplementaryQuantity\": null,
  \"orderId\": null,
  \"orderSnapshot\": null,
  \"notes\": null
}"
```

## PUT `/eudr/statements`

Update due diligence statement

Updates an EUDR due diligence statement.

**Tags:** EUDR

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "referenceNumber": null,
  "verificationNumber": null,
  "activityType": null,
  "actorRole": null,
  "quantityKg": null,
  "supplementaryUnit": null,
  "supplementaryQuantity": null,
  "orderId": null,
  "referenceIssuedAt": null,
  "orderSnapshot": null,
  "notes": null
}
```

### Responses

**200** – Due diligence statement updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/eudr/statements" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"referenceNumber\": null,
  \"verificationNumber\": null,
  \"activityType\": null,
  \"actorRole\": null,
  \"quantityKg\": null,
  \"supplementaryUnit\": null,
  \"supplementaryQuantity\": null,
  \"orderId\": null,
  \"referenceIssuedAt\": null,
  \"orderSnapshot\": null,
  \"notes\": null
}"
```

## GET `/eudr/statements/{id}/export`

Export due diligence statement evidence packet

Returns a due diligence statement with decrypted evidence submissions, product mappings, readiness details, lifecycle fields, latest risk assessment, mitigation actions, and referenced plots. Use `format=geojson` to export referenced plot and legacy submission geolocations.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| format | query | any | Optional |

### Responses

**200** – GeoJSON plot and legacy submission geolocation export

Content-Type: `application/geo+json`

```json
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {}
    }
  ]
}
```

**404** – Statement not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/statements/:id/export" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/eudr/statements/{id}/readiness`

Evaluate the submit gate for a due diligence statement

Runs the draft→submitted gate evaluation without transitioning the statement, returning the unmet requirements as machine-readable i18n keys (eudr.gate.*). Lets the UI show a live readiness checklist before the operator attempts Submit.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Gate evaluation result

Content-Type: `application/json`

```json
{
  "status": "draft",
  "allowed": true,
  "reasons": [
    "string"
  ]
}
```

**404** – Statement not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/statements/:id/readiness" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/eudr/suppliers/compliance`

Get supplier compliance readiness

Returns organization-scoped EUDR submission and permitted plot aggregates for a supplier.

**Tags:** EUDR

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| supplierEntityId | query | any | Required |

### Responses

**200** – Supplier compliance readiness

Content-Type: `application/json`

```json
{
  "submissions": {
    "total": 1,
    "byStatus": {
      "key": 1
    },
    "avgCompleteness": null
  },
  "lastSubmissionAt": null
}
```

**400** – Invalid query or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to load supplier compliance readiness

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/eudr/suppliers/compliance?supplierEntityId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/events`

List declared events

Returns every declared event, including its declared payloadSchema when the module (or the generated CRUD default) provides one. Filters: category, module, excludeTriggerExcluded (default true).

**Tags:** Events

**Requires authentication.**

### Responses

**200** – Declared events

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "string",
      "label": "string"
    }
  ],
  "total": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/events/stream`

GET /events/stream

**Tags:** Events

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/events/stream" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/example-customers-sync/mappings`

List Example customer sync mappings

**Tags:** Example

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| interactionId | query | any | Optional |
| todoId | query | any | Optional |
| limit | query | any | Optional |
| cursor | query | any | Optional |

### Responses

**200** – Sync mappings

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "interactionId": "00000000-0000-4000-8000-000000000000",
      "todoId": "00000000-0000-4000-8000-000000000000",
      "syncStatus": "string",
      "lastSyncedAt": null,
      "lastError": null,
      "sourceUpdatedAt": null,
      "createdAt": "string",
      "updatedAt": "string",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "exampleHref": "string",
      "interaction": null
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example-customers-sync/mappings?limit=50" \
  -H "Accept: application/json"
```

## POST `/example-customers-sync/reconcile`

Backfill or reconcile Example todo mappings to canonical customer interactions

**Tags:** Example

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**202** – Reconcile job accepted

Content-Type: `application/json`

```json
{
  "queued": 1
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example-customers-sync/reconcile" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/example/assignees`

List example assignees

Returns mock assignee options filtered by the optional `q` query parameter.

**Tags:** Example

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| q | query | any | Optional |

### Responses

**200** – Assignable users.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/assignees" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/example/assignees`

Emit SSE probe event for integration tests

Emits a clientBroadcast example todo event with optional recipient filters (user/role/org).

**Tags:** Example

**Requires authentication.**

### Responses

**200** – Event emitted

Content-Type: `application/json`

```json
{
  "ok": true,
  "eventId": "string",
  "payload": {}
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Targeting outside the authenticated scope is forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example/assignees" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/example/blog/{id}`

Fetch demo blog payload

Returns a placeholder blog record containing the provided identifier.

**Tags:** Example

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Placeholder blog payload.

Content-Type: `application/json`

```json
{
  "id": "string",
  "method": "GET"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/blog/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/example/blog/{id}`

Create demo blog payload

Echoes the provided identifier as a placeholder write endpoint.

**Tags:** Example

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Placeholder confirmation.

Content-Type: `application/json`

```json
{
  "id": "string",
  "method": "POST"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example/blog/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/example/customer-priorities`

Delete customer priority

Soft-deletes a customer priority record.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Customer Priority deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/example/customer-priorities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/example/customer-priorities`

List customer priorities

Returns a paginated collection of customer priorities in the current tenant scope.

**Tags:** Example

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| customerId | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated customer priorities

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "customer_id": "00000000-0000-4000-8000-000000000000",
      "priority": "low",
      "tenant_id": null,
      "organization_id": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/customer-priorities?page=1&pageSize=50&sortField=created_at&sortDir=desc" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/example/customer-priorities`

Create customer priority

Creates or stores customer priority records for injected CRUD fields.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "customerId": "00000000-0000-4000-8000-000000000000",
  "priority": "normal"
}
```

### Responses

**201** – Customer Priority created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example/customer-priorities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"customerId\": \"00000000-0000-4000-8000-000000000000\",
  \"priority\": \"normal\"
}"
```

## PUT `/example/customer-priorities`

Update customer priority

Updates customer priority values.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Customer Priority updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/example/customer-priorities" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/example/notifications`

Emit example actionable notification

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

No example available for this content type.

### Responses

**201** – Notification emitted

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example/notifications" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/example/organizations`

Resolve organization labels

Fetches organization names for the provided identifiers within the current tenant scope.

**Tags:** Example

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| ids | query | any | Optional |

### Responses

**200** – Resolved organizations.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/organizations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/example/override-probe`

Example override probe

Returns a small payload used by integration tests to verify modules.ts API route overrides.

**Tags:** Example

### Responses

**200** – Probe payload

Content-Type: `application/json`

```json
{
  "ok": true,
  "source": "string",
  "route": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/override-probe" \
  -H "Accept: application/json"
```

## DELETE `/example/qa-events`

Clear QA-captured server events for the current tenant scope

**Tags:** Example

**Requires authentication.**

### Responses

**200** – Captured events cleared

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/example/qa-events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/example/qa-events`

List QA-captured server events for the current tenant scope

**Tags:** Example

**Requires authentication.**

### Responses

**200** – Captured events

Content-Type: `application/json`

```json
{
  "items": [
    {
      "event": "string",
      "payload": {},
      "capturedAt": "string"
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/qa-events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/example/tags`

List example tags

Returns tag options collected from custom field values and dictionary configuration.

**Tags:** Example

**Requires authentication.**

### Responses

**200** – Available tag options.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
```

**500** – Failed to resolve tags

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/example/todos`

Delete todo

Deletes a todo by id. Provide the identifier in the request body.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Todo deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/example/todos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/example/todos`

List todos

Returns a paginated collection of todos in the current tenant scope.

**Tags:** Example

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| title | query | any | Optional |
| notes | query | any | Optional |
| isDone | query | any | Optional |
| withDeleted | query | any | Optional |
| organizationId | query | any | Optional |
| createdFrom | query | any | Optional |
| createdTo | query | any | Optional |
| format | query | any | Optional |

### Responses

**200** – Paginated todos

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "notes": null,
      "tenant_id": null,
      "organization_id": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/todos?page=1&pageSize=50&sortField=id&sortDir=asc&withDeleted=false" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/example/todos`

Create todo

Creates a todo record. Supports additional custom field keys prefixed with `cf_`.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**201** – Todo created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example/todos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## PUT `/example/todos`

Update todo

Updates an existing todo record by id. Accepts base fields and optional `cf_` custom fields.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Todo updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/example/todos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/example/todos/bulk-complete`

Start marking selected todos done

Creates (or reuses, by idempotency key) a durable bulk operation plus a progress job, then publishes it to the execution queue. Returns the `progressJobId` the DataTable bulk-action contract hands to the top progress bar.

**Tags:** Example

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "ids": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "idempotencyKey": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**202** – Operation accepted.

Content-Type: `application/json`

```json
{
  "ok": true,
  "progressJobId": null,
  "message": "string"
}
```

**400** – Invalid payload or missing organization scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – One or more todos are not in the caller scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/example/todos/bulk-complete" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"ids\": [
    \"00000000-0000-4000-8000-000000000000\"
  ],
  \"idempotencyKey\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/example/todos/summary`

Todo count summary for the current scope

Cache-aside aggregate of todo counts for the session tenant and organization. `cacheHit` reports whether the response was served from the module cache.

**Tags:** Example

**Requires authentication.**

### Responses

**200** – Scoped todo counts.

Content-Type: `application/json`

```json
{
  "total": 1,
  "done": 1,
  "open": 1,
  "cacheHit": true
}
```

**400** – Organization scope required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Unexpected server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/example/todos/summary" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/check/boolean`

Check if feature is enabled

Checks if a feature toggle is enabled for the current context.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| identifier | query | any | Required. Feature toggle identifier |

### Responses

**200** – Feature status

Content-Type: `application/json`

```json
{
  "enabled": true,
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
```

**400** – Bad Request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Tenant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/check/boolean?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/check/json`

Get json config

Gets the json configuration for a feature toggle.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| identifier | query | any | Required. Feature toggle identifier |

### Responses

**200** – Json config

Content-Type: `application/json`

```json
{
  "valueType": "json",
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
```

**400** – Bad Request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Tenant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/check/json?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/check/number`

Get number config

Gets the number configuration for a feature toggle.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| identifier | query | any | Required. Feature toggle identifier |

### Responses

**200** – Number config

Content-Type: `application/json`

```json
{
  "valueType": "number",
  "value": 1,
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
```

**400** – Bad Request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Tenant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/check/number?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/check/string`

Get string config

Gets the string configuration for a feature toggle.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| identifier | query | any | Required. Feature toggle identifier |

### Responses

**200** – String config

Content-Type: `application/json`

```json
{
  "valueType": "string",
  "value": "string",
  "source": "override",
  "toggleId": "string",
  "identifier": "string",
  "tenantId": "string"
}
```

**400** – Bad Request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Tenant not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/check/string?identifier=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/feature_toggles/global`

Delete global feature toggle

Soft deletes a global feature toggle by ID. Requires superadmin role.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. Feature toggle identifier |

### Responses

**200** – Feature toggle deleted

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - superadmin role required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Feature toggle not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/feature_toggles/global?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/global`

List global feature toggles

Returns all global feature toggles with filtering and pagination. Requires superadmin role.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional. Page number for pagination |
| pageSize | query | any | Optional. Number of items per page (max 200) |
| search | query | any | Optional. Case-insensitive search across identifier, name, description, and category |
| type | query | any | Optional. Filter by toggle type (boolean, string, number, json) |
| category | query | any | Optional. Filter by category (case-insensitive partial match) |
| name | query | any | Optional. Filter by name (case-insensitive partial match) |
| identifier | query | any | Optional. Filter by identifier (case-insensitive partial match) |
| sortField | query | any | Optional. Field to sort by |
| sortDir | query | any | Optional. Sort direction (ascending or descending) |

### Responses

**200** – Feature toggles collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "identifier": "string",
      "name": "string",
      "description": null,
      "category": null,
      "type": "boolean",
      "defaultValue": null,
      "createdAt": null,
      "updatedAt": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - superadmin role required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/global?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/feature_toggles/global`

Create global feature toggle

Creates a new global feature toggle. Requires superadmin role.

**Tags:** Feature Toggles

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "identifier": "string",
  "name": "string",
  "description": null,
  "category": null,
  "type": "boolean",
  "defaultValue": null
}
```

### Responses

**201** – Feature toggle created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - superadmin role required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/feature_toggles/global" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"identifier\": \"string\",
  \"name\": \"string\",
  \"description\": null,
  \"category\": null,
  \"type\": \"boolean\",
  \"defaultValue\": null
}"
```

## PUT `/feature_toggles/global`

Update global feature toggle

Updates an existing global feature toggle. Requires superadmin role.

**Tags:** Feature Toggles

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "category": null,
  "defaultValue": null
}
```

### Responses

**200** – Feature toggle updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - superadmin role required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Feature toggle not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/feature_toggles/global" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"category\": null,
  \"defaultValue\": null
}"
```

## GET `/feature_toggles/global/{id}`

Fetch feature toggle by ID

Returns complete details of a feature toggle.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Feature toggle detail

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "identifier": "string",
  "name": "string",
  "description": null,
  "category": null,
  "type": "boolean",
  "defaultValue": null,
  "createdAt": null,
  "updatedAt": null
}
```

**400** – Invalid identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Feature toggle not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/global/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/global/{id}/override`

Fetch feature toggle override

Returns feature toggle override.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Feature toggle overrides

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "tenantName": "string",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "toggleType": "boolean",
  "updatedAt": null
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Feature toggle not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/global/:id/override" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/feature_toggles/overrides`

List overrides

Returns list of feature toggle overrides.

**Tags:** Feature Toggles

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| category | query | any | Optional |
| name | query | any | Optional |
| identifier | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – List of overrides

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "toggleId": "00000000-0000-4000-8000-000000000000",
      "tenantName": "string",
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "identifier": "string",
      "name": "string",
      "category": "string",
      "isOverride": true
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1,
  "isSuperAdmin": true
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/feature_toggles/overrides?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/feature_toggles/overrides`

Change override state

Enable, disable or inherit a feature toggle for a specific tenant.

**Tags:** Feature Toggles

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "toggleId": "00000000-0000-4000-8000-000000000000",
  "isOverride": true
}
```

### Responses

**200** – Override updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "overrideToggleId": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/feature_toggles/overrides" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"toggleId\": \"00000000-0000-4000-8000-000000000000\",
  \"isOverride\": true
}"
```

## GET `/inbox_ops/emails`

List received emails

Processing log of all received emails

**Tags:** InboxOps

**Requires authentication.**

### Responses

**200** – Paginated list of emails

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/inbox_ops/emails" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/inbox_ops/emails/{id}`

Soft-delete an inbox email

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Email deleted

Content-Type: `application/json`

**404** – Email not found

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/inbox_ops/emails/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/inbox_ops/emails/{id}`

Get email detail with parsed thread

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Email detail

Content-Type: `application/json`

**404** – Email not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/inbox_ops/emails/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/emails/{id}/reprocess`

Re-trigger LLM extraction on a failed or low-confidence email

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Email queued for reprocessing

Content-Type: `application/json`

**404** – Email not found

Content-Type: `application/json`

**409** – Email is already processing or proposal cannot be superseded safely

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/emails/:id/reprocess" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/extract`

Submit raw text for LLM extraction

Creates an InboxEmail record from raw text and triggers the extraction pipeline. The extraction runs asynchronously.

**Tags:** InboxOps

**Requires authentication.**

### Responses

**200** – Extraction queued successfully

Content-Type: `application/json`

**400** – Invalid request body

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/extract" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/inbox_ops/proposals`

List proposals

List inbox proposals with optional status filter and pagination

**Tags:** InboxOps

**Requires authentication.**

### Responses

**200** – Paginated list of proposals

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/inbox_ops/proposals" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/inbox_ops/proposals/{id}`

Get proposal detail

Returns proposal with actions, discrepancies, and source email

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Full proposal detail

Content-Type: `application/json`

**404** – Proposal not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/accept-all`

Accept and execute all pending actions in a proposal

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – All actions processed

Content-Type: `application/json`

**404** – Proposal not found

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/accept-all" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/inbox_ops/proposals/{id}/actions/{actionId}`

Edit action payload before accepting

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| actionId | path | any | Required |

### Responses

**200** – Action updated

Content-Type: `application/json`

**404** – Action not found

Content-Type: `application/json`

**409** – Action already processed or stale (optimistic-lock conflict)

Content-Type: `application/json`

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/actions/:actionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/actions/{actionId}/accept`

Accept and execute a proposal action

Executes the action and creates the entity in the target module. Returns 409 if already processed.

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| actionId | path | any | Required |

### Responses

**200** – Action executed successfully

Content-Type: `application/json`

**403** – Insufficient permissions in target module

Content-Type: `application/json`

**404** – Action not found

Content-Type: `application/json`

**409** – Action already processed

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/actions/:actionId/accept" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/inbox_ops/proposals/{id}/actions/{actionId}/complete`

Mark an action as completed with an externally-created entity

Used when an action is fulfilled through the normal sales form instead of the execution engine. Updates the action status without running the execution engine.

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| actionId | path | any | Required |

### Responses

**200** – Action marked as completed

Content-Type: `application/json`

**400** – Invalid body

Content-Type: `application/json`

**404** – Action not found

Content-Type: `application/json`

**409** – Action already processed

Content-Type: `application/json`

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/actions/:actionId/complete" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/actions/{actionId}/reject`

Reject a proposal action

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| actionId | path | any | Required |

### Responses

**200** – Action rejected

Content-Type: `application/json`

**404** – Action not found

Content-Type: `application/json`

**409** – Action already processed

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/actions/:actionId/reject" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/categorize`

Set or change the category of a proposal

Assigns a category to a proposal. Returns the new and previous category for undo support.

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Category updated

Content-Type: `application/json`

**400** – Invalid category value

Content-Type: `application/json`

**404** – Proposal not found

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/categorize" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/reject`

Reject entire proposal (all pending actions)

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Proposal rejected

Content-Type: `application/json`

**404** – Proposal not found

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/reject" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/replies/{replyId}/send`

Send a draft reply email and register it in messages when available

Sends the draft_reply action payload via the configured email provider. When the messages module is available, also records the sent reply as an internal message record. Sets In-Reply-To and References headers for threading.

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| replyId | path | any | Required |

### Responses

**200** – Reply sent successfully

Content-Type: `application/json`

**400** – Missing required payload fields

Content-Type: `application/json`

**404** – Reply action not found

Content-Type: `application/json`

**409** – Action in invalid state for sending, or a send is already in progress / completed for this reply

Content-Type: `application/json`

**502** – Email delivery failed

Content-Type: `application/json`

**503** – Email service not configured or disabled

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/replies/:replyId/send" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/proposals/{id}/translate`

Translate proposal content

Translates the proposal summary and action descriptions to the target locale. Results are cached.

**Tags:** InboxOps

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Translation result

Content-Type: `application/json`

**400** – Invalid target locale or same language

Content-Type: `application/json`

**404** – Proposal not found

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/proposals/:id/translate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/inbox_ops/proposals/counts`

Get proposal status and category counts

Returns counts by status and by category for tab badges and filter dropdowns

**Tags:** InboxOps

**Requires authentication.**

### Responses

**200** – Status and category counts object

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/inbox_ops/proposals/counts" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/inbox_ops/settings`

Get tenant inbox configuration

Returns the forwarding address and configuration for this tenant

**Tags:** InboxOps

**Requires authentication.**

### Responses

**200** – Inbox settings

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/inbox_ops/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/inbox_ops/settings`

Update tenant inbox configuration

Updates working language and/or active status

**Tags:** InboxOps

**Requires authentication.**

### Responses

**200** – Updated settings

Content-Type: `application/json`

**404** – Settings not found

Content-Type: `application/json`

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/inbox_ops/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/inbox_ops/webhook/inbound`

Receive forwarded email from provider webhook

Public endpoint — validated by provider HMAC signature or Resend/Svix signature. Rate limited per tenant.

**Tags:** InboxOps

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Email received and queued for processing

Content-Type: `application/json`

**400** – Invalid payload or signature

Content-Type: `application/json`

**413** – Payload too large

Content-Type: `application/json`

**429** – Rate limit exceeded

Content-Type: `application/json`

**503** – Webhook secret not configured

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/inbox_ops/webhook/inbound" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/integrations`

List integrations

Returns a paginated collection of integrations.

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| q | query | any | Optional |
| category | query | any | Optional |
| bundleId | query | any | Optional |
| isEnabled | query | any | Optional |
| healthStatus | query | any | Optional |
| sort | query | any | Optional |
| order | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated integrations

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "description": null,
      "category": null,
      "tags": [
        "string"
      ],
      "hub": null,
      "providerKey": null,
      "bundleId": null,
      "author": null,
      "company": null,
      "version": null,
      "hasCredentials": true,
      "isEnabled": true,
      "apiVersion": null,
      "healthStatus": "healthy",
      "lastHealthCheckedAt": null,
      "lastHealthLatencyMs": null,
      "enabledAt": null,
      "analytics": {
        "lastActivityAt": null,
        "totalCount": 1,
        "errorCount": 1,
        "errorRate": 1,
        "dailyCounts": [
          1
        ]
      }
    }
  ],
  "total": 1,
  "totalPages": 1,
  "bundles": [
    {
      "id": "string",
      "title": "string",
      "description": "string",
      "icon": null,
      "integrationCount": 1,
      "enabledCount": 1
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/integrations?order=asc&page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/integrations/{id}`

Get integration detail

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/integrations/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/integrations/{id}/credentials`

Get or save integration credentials

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/integrations/:id/credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/integrations/{id}/credentials`

Get or save integration credentials

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/integrations/:id/credentials" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/integrations/{id}/health`

Run health check for an integration

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/integrations/:id/health" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/integrations/{id}/state`

Update integration state

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/integrations/:id/state" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/integrations/{id}/version`

Change integration API version

**Tags:** Integrations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/integrations/:id/version" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/integrations/logs`

List integration logs

**Tags:** Integrations

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/integrations/logs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/messages`

List messages

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| folder | query | any | Optional |
| status | query | any | Optional |
| type | query | any | Optional |
| visibility | query | any | Optional |
| sourceEntityType | query | any | Optional |
| sourceEntityId | query | any | Optional |
| externalEmail | query | any | Optional |
| hasObjects | query | any | Optional |
| hasAttachments | query | any | Optional |
| hasActions | query | any | Optional |
| senderId | query | any | Optional |
| search | query | any | Optional |
| since | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |

### Responses

**200** – Message list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "type": "string",
      "visibility": null,
      "sourceEntityType": null,
      "sourceEntityId": null,
      "externalEmail": null,
      "externalName": null,
      "subject": "string",
      "bodyPreview": "string",
      "senderUserId": "00000000-0000-4000-8000-000000000000",
      "senderName": null,
      "senderEmail": null,
      "priority": "string",
      "status": "string",
      "hasObjects": true,
      "objectCount": 1,
      "hasAttachments": true,
      "attachmentCount": 1,
      "recipientCount": 1,
      "hasActions": true,
      "actionTaken": null,
      "sentAt": null,
      "readAt": null,
      "threadId": null
    }
  ],
  "page": 1,
  "pageSize": 1,
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages?folder=inbox&page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/messages`

Compose a message

**Tags:** Messages

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "type": "default",
  "visibility": null,
  "recipients": [],
  "subject": "",
  "body": "",
  "bodyFormat": "text",
  "priority": "normal",
  "sendViaEmail": false,
  "isDraft": false
}
```

### Responses

**201** – Message created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "threadId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/messages" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"type\": \"default\",
  \"visibility\": null,
  \"recipients\": [],
  \"subject\": \"\",
  \"body\": \"\",
  \"bodyFormat\": \"text\",
  \"priority\": \"normal\",
  \"sendViaEmail\": false,
  \"isDraft\": false
}"
```

## DELETE `/messages/{id}`

Delete message for current sender/recipient context

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Message deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Message was modified concurrently (optimistic lock conflict)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/messages/{id}`

Get message detail

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Message detail with actor-visible thread items only

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "updatedAt": null,
  "type": "string",
  "isDraft": true,
  "canEditDraft": true,
  "canArchive": true,
  "isArchived": true,
  "visibility": null,
  "sourceEntityType": null,
  "sourceEntityId": null,
  "externalEmail": null,
  "externalName": null,
  "typeDefinition": {
    "labelKey": "string",
    "icon": "string",
    "color": null,
    "allowReply": true,
    "allowForward": true,
    "ui": null
  },
  "threadId": null,
  "parentMessageId": null,
  "senderUserId": "00000000-0000-4000-8000-000000000000",
  "senderName": null,
  "senderEmail": null,
  "subject": "string",
  "body": "string",
  "bodyFormat": "text",
  "priority": "string",
  "sentAt": null,
  "actionData": null,
  "actionTaken": null,
  "actionTakenAt": null,
  "actionTakenByUserId": null,
  "recipients": [
    {
      "userId": "00000000-0000-4000-8000-000000000000",
      "type": "to",
      "status": "string",
      "readAt": null
    }
  ],
  "objects": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityModule": "string",
      "entityType": "string",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "actionRequired": true,
      "actionType": null,
      "actionLabel": null,
      "snapshot": null,
      "preview": null
    }
  ],
  "thread": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "senderUserId": "00000000-0000-4000-8000-000000000000",
      "senderName": null,
      "senderEmail": null,
      "externalName": null,
      "externalEmail": null,
      "sourceEntityType": null,
      "body": "string",
      "sentAt": null
    }
  ],
  "isRead": true,
  "conversationArchived": true,
  "conversationAllUnread": true,
  "_channel": null,
  "_channelPayload": null,
  "_channelContact": null
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/messages/{id}`

Update draft message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "visibility": null
}
```

### Responses

**200** – Draft updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Only drafts can be edited, or the draft was modified concurrently (optimistic lock conflict)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/messages/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"visibility\": null
}"
```

## POST `/messages/{id}/actions/{actionId}`

Execute message action

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| actionId | path | any | Required |

### Request Body

Content-Type: `application/json`

No example available for this content type.

### Responses

**200** – Action executed

Content-Type: `application/json`

```json
{
  "ok": true,
  "actionId": "string"
}
```

**403** – Access denied

Content-Type: `application/json`

**404** – Action not found

Content-Type: `application/json`

**409** – Action already taken, or the message was modified concurrently (optimistic lock conflict)

Content-Type: `application/json`

**410** – Action expired

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/messages/:id/actions/:actionId" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/messages/{id}/archive`

Unarchive message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Message unarchived

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied or sender-only message cannot be unarchived

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/messages/{id}/archive`

Archive message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Message archived

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied or sender-only message cannot be archived

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/messages/:id/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/messages/{id}/attachments`

Unlink attachments from draft message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Attachments unlinked

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Only draft messages can be edited

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/messages/{id}/attachments`

List message attachments

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Attachments

Content-Type: `application/json`

```json
{
  "attachments": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "fileName": "string",
      "fileSize": 1,
      "mimeType": "string",
      "url": "string"
    }
  ]
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/:id/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/messages/{id}/attachments`

Link attachments to draft message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "attachmentIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

### Responses

**200** – Attachments linked

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Only draft messages can be edited

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/messages/:id/attachments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"attachmentIds\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
```

## GET `/messages/{id}/confirmation`

Read message confirmation status

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Confirmation status

Content-Type: `application/json`

```json
{
  "messageId": "00000000-0000-4000-8000-000000000000",
  "confirmed": true,
  "confirmedAt": null,
  "confirmedByUserId": null
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/:id/confirmation" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/messages/{id}/conversation`

Delete conversation for current actor

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Conversation deleted

Content-Type: `application/json`

```json
{
  "ok": true,
  "affectedCount": 1
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id/conversation" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/messages/{id}/conversation/archive`

Unarchive conversation for current actor

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Conversation unarchived

Content-Type: `application/json`

```json
{
  "ok": true,
  "affectedCount": 1
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id/conversation/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/messages/{id}/conversation/archive`

Archive conversation for current actor

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Conversation archived

Content-Type: `application/json`

```json
{
  "ok": true,
  "affectedCount": 1
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/messages/:id/conversation/archive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/messages/{id}/conversation/read`

Mark entire conversation as unread for current actor

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Conversation marked unread

Content-Type: `application/json`

```json
{
  "ok": true,
  "affectedCount": 1
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id/conversation/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/messages/{id}/conversation/read`

Mark entire conversation as read for current actor

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Conversation marked read

Content-Type: `application/json`

```json
{
  "ok": true,
  "affectedCount": 1
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/messages/:id/conversation/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/messages/{id}/forward`

Forward a message and optionally include attachments from the forwarded conversation slice

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "recipients": [
    {
      "userId": "00000000-0000-4000-8000-000000000000",
      "type": "to"
    }
  ],
  "includeAttachments": true,
  "sendViaEmail": false
}
```

### Responses

**201** – Message forwarded

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**403** – Access denied

Content-Type: `application/json`

**404** – Message not found

Content-Type: `application/json`

**409** – Forward not allowed for message type

Content-Type: `application/json`

**413** – Forward body exceeds maximum length

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/messages/:id/forward" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"recipients\": [
    {
      \"userId\": \"00000000-0000-4000-8000-000000000000\",
      \"type\": \"to\"
    }
  ],
  \"includeAttachments\": true,
  \"sendViaEmail\": false
}"
```

## GET `/messages/{id}/forward-preview`

Get forward preview for a message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Forward preview generated

Content-Type: `application/json`

```json
{
  "subject": "string",
  "body": "string"
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Forward body exceeds maximum length

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/:id/forward-preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/messages/{id}/read`

Mark message as unread

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Message marked unread

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/messages/:id/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/messages/{id}/read`

Mark message as read

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Message marked read

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/messages/:id/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/messages/{id}/reply`

Reply to message

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "body": "string",
  "bodyFormat": "text",
  "replyAll": false,
  "sendViaEmail": false
}
```

### Responses

**201** – Reply created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Message not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – No recipients available for reply

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/messages/:id/reply" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"body\": \"string\",
  \"bodyFormat\": \"text\",
  \"replyAll\": false,
  \"sendViaEmail\": false
}"
```

## GET `/messages/object-types`

List registered message object types for a message type

**Tags:** Messages

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| messageType | query | any | Required |

### Responses

**200** – Message object types

Content-Type: `application/json`

```json
{
  "items": [
    {
      "module": "string",
      "entityType": "string",
      "labelKey": "string",
      "icon": "string",
      "actions": [
        {
          "id": "string",
          "labelKey": "string"
        }
      ]
    }
  ]
}
```

**400** – Invalid query

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/object-types?messageType=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/messages/token/{token}`

Access message via token

**Tags:** Messages

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| token | path | any | Required |

### Responses

**200** – Message detail via token

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "type": "string",
  "subject": "string",
  "body": "string",
  "bodyFormat": "text",
  "priority": "low",
  "senderUserId": "00000000-0000-4000-8000-000000000000",
  "sentAt": null,
  "actionData": null,
  "actionTaken": null,
  "actionTakenAt": null,
  "actionTakenByUserId": null,
  "objects": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "entityModule": "string",
      "entityType": "string",
      "entityId": "00000000-0000-4000-8000-000000000000",
      "actionRequired": true,
      "actionType": null,
      "actionLabel": null,
      "snapshot": null
    }
  ],
  "requiresAuth": true,
  "recipientUserId": "00000000-0000-4000-8000-000000000000"
}
```

**404** – Invalid or expired link

Content-Type: `application/json`

**409** – Token usage exceeded

Content-Type: `application/json`

**410** – Token expired

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/token/:token" \
  -H "Accept: application/json"
```

## GET `/messages/types`

List registered message types

**Tags:** Messages

**Requires authentication.**

### Responses

**200** – Message types

Content-Type: `application/json`

```json
{
  "items": [
    {
      "type": "string",
      "module": "string",
      "labelKey": "string",
      "icon": "string",
      "color": null,
      "allowReply": true,
      "allowForward": true,
      "actionsExpireAfterHours": null,
      "ui": null
    }
  ]
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/messages/unread-count`

Get unread message count

**Tags:** Messages

**Requires authentication.**

### Responses

**200** – Unread count

Content-Type: `application/json`

```json
{
  "unreadCount": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/messages/unread-count" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications`

List notifications

Returns a paginated collection of notifications.

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| status | query | any | Optional |
| type | query | any | Optional |
| severity | query | any | Optional |
| sourceEntityType | query | any | Optional |
| sourceEntityId | query | any | Optional |
| since | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated notifications

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "type": "string",
      "title": "string",
      "body": null,
      "titleKey": null,
      "bodyKey": null,
      "titleVariables": null,
      "bodyVariables": null,
      "icon": null,
      "severity": "string",
      "status": "string",
      "actions": [
        {
          "id": "string",
          "label": "string"
        }
      ],
      "sourceModule": null,
      "sourceEntityType": null,
      "sourceEntityId": null,
      "linkHref": null,
      "createdAt": "string",
      "readAt": null,
      "actionTaken": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**403** – Request could not be resolved to a tenant scope (code: tenant_scope_required)

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications?page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/notifications`

Create notification

Creates a notification for a user.

**Tags:** Notifications

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "type": "string",
  "severity": "info",
  "recipientUserId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Notification created

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/notifications" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"type\": \"string\",
  \"severity\": \"info\",
  \"recipientUserId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/notifications/{id}/action`

POST /notifications/{id}/action

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/notifications/:id/action" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/{id}/dismiss`

PUT /notifications/{id}/dismiss

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/:id/dismiss" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/{id}/read`

PUT /notifications/{id}/read

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/:id/read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/{id}/restore`

PUT /notifications/{id}/restore

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/:id/restore" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications/admin/preferences`

GET /notifications/admin/preferences

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications/admin/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/admin/preferences`

PUT /notifications/admin/preferences

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/admin/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/notifications/batch`

POST /notifications/batch

**Tags:** Notifications

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/notifications/batch" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications/channels`

GET /notifications/channels

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/notifications/feature`

POST /notifications/feature

**Tags:** Notifications

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/notifications/feature" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/mark-all-read`

PUT /notifications/mark-all-read

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/mark-all-read" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications/preferences`

GET /notifications/preferences

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/preferences`

PUT /notifications/preferences

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/preferences" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/notifications/role`

POST /notifications/role

**Tags:** Notifications

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/notifications/role" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications/settings`

GET /notifications/settings

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/notifications/settings`

POST /notifications/settings

**Tags:** Notifications

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/notifications/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications/types`

GET /notifications/types

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications/types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/notifications/types`

PATCH /notifications/types

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/notifications/types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/notifications/types/{id}/channels/{channel}`

DELETE /notifications/types/{id}/channels/{channel}

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| channel | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/notifications/types/:id/channels/:channel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/notifications/types/{id}/channels/{channel}`

PUT /notifications/types/{id}/channels/{channel}

**Tags:** Notifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| channel | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/notifications/types/:id/channels/:channel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/notifications/unread-count`

GET /notifications/unread-count

**Tags:** Notifications

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/notifications/unread-count" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/onboarding/demo-feedback`

Submit demo feedback

Sends a feedback/contact request from the demo environment to the configured admin.

**Tags:** Demo

### Request Body

Content-Type: `application/json`

```json
{
  "email": "user@example.com",
  "message": "",
  "termsAccepted": true,
  "marketingConsent": false
}
```

### Responses

**200** – Feedback sent successfully.

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/onboarding/demo-feedback" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"email\": \"user@example.com\",
  \"message\": \"\",
  \"termsAccepted\": true,
  \"marketingConsent\": false
}"
```

## POST `/onboarding/onboarding`

Self-service onboarding submission

**Tags:** Onboarding

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/onboarding/onboarding" \
  -H "Accept: application/json"
```

## GET `/onboarding/onboarding/status`

Onboarding preparation status

**Tags:** Onboarding

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/onboarding/onboarding/status" \
  -H "Accept: application/json"
```

## GET `/onboarding/onboarding/verify`

Onboarding verification redirect

**Tags:** Onboarding

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/onboarding/onboarding/verify" \
  -H "Accept: application/json"
```

## POST `/payment_gateways/cancel`

Cancel payment

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – Payment cancelled

Content-Type: `application/json`

**409** – Invalid payment status transition

Content-Type: `application/json`

**422** – Invalid payload

Content-Type: `application/json`

**502** – Gateway provider error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/payment_gateways/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/payment_gateways/capture`

Capture payment

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – Payment captured

Content-Type: `application/json`

**409** – Invalid payment status transition, cumulative capture ceiling exceeded, or conflicting capture operation

Content-Type: `application/json`

**422** – Invalid payload

Content-Type: `application/json`

**502** – Gateway provider error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/payment_gateways/capture" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/payment_gateways/providers`

List payment gateway descriptors

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – List of safe payment gateway descriptors

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/payment_gateways/providers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/payment_gateways/providers/{providerKey}`

Get payment gateway descriptor

**Tags:** PaymentGateways

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| providerKey | path | any | Required |

### Responses

**200** – Provider descriptor

Content-Type: `application/json`

**404** – Provider descriptor not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/payment_gateways/providers/:providerKey" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/payment_gateways/refund`

Refund payment

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – Payment refunded

Content-Type: `application/json`

**409** – Invalid payment status transition

Content-Type: `application/json`

**422** – Invalid payload

Content-Type: `application/json`

**502** – Gateway provider error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/payment_gateways/refund" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/payment_gateways/sessions`

Create payment session

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**201** – Payment session created

Content-Type: `application/json`

**409** – Amount or currency does not match the referenced order

Content-Type: `application/json`

**422** – Invalid payload or unknown provider

Content-Type: `application/json`

**502** – Gateway provider error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/payment_gateways/sessions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/payment_gateways/status`

Get stored transaction status

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – Stored transaction status

Content-Type: `application/json`

**400** – Missing or malformed transactionId

Content-Type: `application/json`

**404** – Transaction not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/payment_gateways/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/payment_gateways/status`

Refresh transaction status from the provider

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – Refreshed transaction status

Content-Type: `application/json`

**401** – Unauthorized

Content-Type: `application/json`

**404** – Transaction not found

Content-Type: `application/json`

**422** – Missing or malformed payload

Content-Type: `application/json`

**502** – Gateway provider error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/payment_gateways/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/payment_gateways/transactions`

List payment transactions

**Tags:** PaymentGateways

**Requires authentication.**

### Responses

**200** – Payment transaction list

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/payment_gateways/transactions" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/payment_gateways/transactions/{id}`

Get payment transaction details

**Tags:** PaymentGateways

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Payment transaction details

Content-Type: `application/json`

**404** – Transaction not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/payment_gateways/transactions/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/payment_gateways/webhook/{provider}`

Process inbound webhook from payment provider

**Tags:** PaymentGateways

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| provider | path | any | Required |

### Responses

**202** – Webhook accepted for async processing

Content-Type: `application/json`

**401** – Signature verification failed

Content-Type: `application/json`

**404** – Unknown provider

Content-Type: `application/json`

**413** – Webhook payload too large

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/payment_gateways/webhook/:provider" \
  -H "Accept: application/json"
```

## GET `/perspectives/{tableId}`

Load perspectives for a table

Returns personal perspectives and available role defaults for the requested table identifier.

**Tags:** Perspectives

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| tableId | path | any | Required |

### Responses

**200** – Current perspectives and defaults.

Content-Type: `application/json`

```json
{
  "tableId": "string",
  "perspectives": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "tableId": "string",
      "settings": {},
      "isDefault": true,
      "createdAt": "string",
      "updatedAt": null
    }
  ],
  "defaultPerspectiveId": null,
  "rolePerspectives": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "tableId": "string",
      "settings": {},
      "isDefault": true,
      "createdAt": "string",
      "updatedAt": null,
      "roleId": "00000000-0000-4000-8000-000000000000",
      "tenantId": null,
      "organizationId": null,
      "roleName": null
    }
  ],
  "manageableRolePerspectives": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "tableId": "string",
      "settings": {},
      "isDefault": true,
      "createdAt": "string",
      "updatedAt": null,
      "roleId": "00000000-0000-4000-8000-000000000000",
      "tenantId": null,
      "organizationId": null,
      "roleName": null
    }
  ],
  "roles": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "hasPerspective": true,
      "hasDefault": true
    }
  ],
  "canApplyToRoles": true
}
```

**400** – Invalid table identifier

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/perspectives/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/perspectives/{tableId}`

Create or update a perspective

Saves a personal perspective and optionally applies the same configuration to selected roles.

**Tags:** Perspectives

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| tableId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "settings": {}
}
```

### Responses

**200** – Perspective saved successfully.

Content-Type: `application/json`

```json
{
  "perspective": {
    "id": "00000000-0000-4000-8000-000000000000",
    "name": "string",
    "tableId": "string",
    "settings": {},
    "isDefault": true,
    "createdAt": "string",
    "updatedAt": null
  },
  "rolePerspectives": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "tableId": "string",
      "settings": {},
      "isDefault": true,
      "createdAt": "string",
      "updatedAt": null,
      "roleId": "00000000-0000-4000-8000-000000000000",
      "tenantId": null,
      "organizationId": null,
      "roleName": null
    }
  ],
  "clearedRoleIds": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

**400** – Validation failed or invalid roles provided

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing perspectives.role_defaults feature for role updates

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict or perspective name already exists

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/perspectives/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"settings\": {}
}"
```

## DELETE `/perspectives/{tableId}/{perspectiveId}`

Delete a personal perspective

Removes a perspective owned by the current user for the given table.

**Tags:** Perspectives

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| tableId | path | any | Required |
| perspectiveId | path | any | Required |

### Responses

**200** – Perspective removed.

Content-Type: `application/json`

```json
{
  "success": true
}
```

**400** – Invalid identifiers supplied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Perspective not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/perspectives/string/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/perspectives/{tableId}/roles/{roleId}`

Clear role perspectives for a table

Removes all role-level perspectives associated with the provided role identifier for the table.

**Tags:** Perspectives

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| tableId | path | any | Required |
| roleId | path | any | Required |

### Request Body

Content-Type: `application/json`

No example available for this content type.

### Responses

**200** – Role perspectives cleared.

Content-Type: `application/json`

```json
{
  "success": true
}
```

**400** – Invalid identifiers supplied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing perspectives.role_defaults feature

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Role not found in scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/perspectives/string/roles/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/phone_calls/calls`

List phonecalls

Returns a paginated collection of phonecalls scoped to the authenticated organization.

**Tags:** PhoneCalls

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| q | query | any | Optional |
| providerKey | query | any | Optional |
| status | query | any | Optional |
| direction | query | any | Optional |
| startedFrom | query | any | Optional |
| startedTo | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated phonecalls

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "organization_id": null,
      "tenant_id": null,
      "provider_key": null,
      "integration_id": null,
      "external_call_id": null,
      "external_conversation_id": null,
      "direction": null,
      "status": null,
      "started_at": null,
      "answered_at": null,
      "ended_at": null,
      "duration_seconds": null,
      "recording_url": null,
      "ingest_status": null,
      "last_ingested_at": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/phone_calls/calls?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/planner/availability`

Delete availability rule

Deletes an availability rule by id.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Availability rule deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/planner/availability" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/planner/availability`

List availability rules

Returns a paginated collection of availability rules scoped to the authenticated organization.

**Tags:** Planner

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| subjectType | query | any | Optional |
| subjectIds | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated availability rules

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "subject_type": null,
      "subject_id": null,
      "timezone": null,
      "rrule": null,
      "exdates": null,
      "kind": null,
      "note": null,
      "unavailability_reason_entry_id": null,
      "unavailability_reason_value": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/planner/availability?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/planner/availability`

Create availability rule

Creates an availability rule for the selected subject.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "subjectType": "member",
  "subjectId": "00000000-0000-4000-8000-000000000000",
  "timezone": "string",
  "rrule": "string",
  "exdates": [],
  "kind": "availability",
  "note": null,
  "unavailabilityReasonEntryId": null,
  "unavailabilityReasonValue": null
}
```

### Responses

**201** – Availability rule created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/planner/availability" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"subjectType\": \"member\",
  \"subjectId\": \"00000000-0000-4000-8000-000000000000\",
  \"timezone\": \"string\",
  \"rrule\": \"string\",
  \"exdates\": [],
  \"kind\": \"availability\",
  \"note\": null,
  \"unavailabilityReasonEntryId\": null,
  \"unavailabilityReasonValue\": null
}"
```

## PUT `/planner/availability`

Update availability rule

Updates an availability rule by id.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "note": null,
  "unavailabilityReasonEntryId": null,
  "unavailabilityReasonValue": null
}
```

### Responses

**200** – Availability rule updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/planner/availability" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"note\": null,
  \"unavailabilityReasonEntryId\": null,
  \"unavailabilityReasonValue\": null
}"
```

## POST `/planner/availability-date-specific`

Replace date-specific availability

Replaces date-specific availability rules for the subject in a single request.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "subjectType": "member",
  "subjectId": "00000000-0000-4000-8000-000000000000",
  "timezone": "string",
  "windows": [],
  "isAvailable": true,
  "note": null,
  "unavailabilityReasonEntryId": null,
  "unavailabilityReasonValue": null
}
```

### Responses

**200** – Date-specific availability updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Conflict — the subject/date availability was modified by another edit

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/planner/availability-date-specific" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"subjectType\": \"member\",
  \"subjectId\": \"00000000-0000-4000-8000-000000000000\",
  \"timezone\": \"string\",
  \"windows\": [],
  \"isAvailable\": true,
  \"note\": null,
  \"unavailabilityReasonEntryId\": null,
  \"unavailabilityReasonValue\": null
}"
```

## DELETE `/planner/availability-rule-sets`

Delete availability rule set

Deletes an availability rule set by id.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Availability rule set deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/planner/availability-rule-sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/planner/availability-rule-sets`

List availability rule sets

Returns a paginated collection of availability rule sets scoped to the authenticated organization.

**Tags:** Planner

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated availability rule sets

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "name": null,
      "description": null,
      "timezone": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/planner/availability-rule-sets?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/planner/availability-rule-sets`

Create availability rule set

Creates a reusable availability rule set.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "description": null,
  "timezone": "string"
}
```

### Responses

**201** – Availability rule set created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/planner/availability-rule-sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"description\": null,
  \"timezone\": \"string\"
}"
```

## PUT `/planner/availability-rule-sets`

Update availability rule set

Updates an availability rule set by id.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null
}
```

### Responses

**200** – Availability rule set updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/planner/availability-rule-sets" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null
}"
```

## POST `/planner/availability-weekly`

Replace weekly availability

Replaces weekly availability rules for the subject in a single request.

**Tags:** Planner

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "subjectType": "member",
  "subjectId": "00000000-0000-4000-8000-000000000000",
  "timezone": "string",
  "windows": []
}
```

### Responses

**200** – Weekly availability updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Optimistic lock conflict

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "optimistic_lock_conflict",
  "currentUpdatedAt": "string",
  "expectedUpdatedAt": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/planner/availability-weekly" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"subjectType\": \"member\",
  \"subjectId\": \"00000000-0000-4000-8000-000000000000\",
  \"timezone\": \"string\",
  \"windows\": []
}"
```

## GET `/progress/active`

GET /progress/active

**Tags:** Progress

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/progress/active" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/progress/jobs`

List progressjobs

Returns a paginated collection of progressjobs scoped to the authenticated tenant.

**Tags:** Progress

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| status | query | any | Optional |
| jobType | query | any | Optional |
| parentJobId | query | any | Optional |
| includeCompleted | query | any | Optional |
| completedSince | query | any | Optional |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated progressjobs

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "jobType": "string",
      "name": "string",
      "description": null,
      "status": "string",
      "progressPercent": 1,
      "processedCount": 1,
      "totalCount": null,
      "etaSeconds": null,
      "cancellable": true,
      "startedAt": null,
      "finishedAt": null,
      "errorMessage": null,
      "createdAt": null,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/progress/jobs?page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/progress/jobs`

Create progressjob

Creates a new progress job for tracking a long-running operation.

**Tags:** Progress

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "jobType": "string",
  "name": "string",
  "cancellable": false
}
```

### Responses

**201** – ProgressJob created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/progress/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"jobType\": \"string\",
  \"name\": \"string\",
  \"cancellable\": false
}"
```

## DELETE `/progress/jobs/{id}`

DELETE /progress/jobs/{id}

**Tags:** Progress

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/progress/jobs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/progress/jobs/{id}`

GET /progress/jobs/{id}

**Tags:** Progress

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/progress/jobs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/progress/jobs/{id}`

PUT /progress/jobs/{id}

**Tags:** Progress

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/progress/jobs/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/push_notifications/custom-send`

POST /push_notifications/custom-send

**Tags:** Push Notifications

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/push_notifications/custom-send" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/push_notifications/deliveries`

List push deliveries

Returns the tenant's push push deliveries (admin observability).

**Tags:** PushNotifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| status | query | any | Optional |
| userId | query | any | Optional |
| from | query | any | Optional |
| to | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated push deliveries

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "tenant_id": "00000000-0000-4000-8000-000000000000",
      "organization_id": null,
      "notification_id": null,
      "notification_type_id": "string",
      "user_device_id": "00000000-0000-4000-8000-000000000000",
      "user_id": "00000000-0000-4000-8000-000000000000",
      "provider": "string",
      "token_snapshot": "string",
      "status": "pending",
      "attempts": 1,
      "last_error": null,
      "created_at": null,
      "sent_at": null,
      "next_retry_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/push_notifications/deliveries?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/push_notifications/deliveries/{id}`

Get a push delivery

Admin: fetch a single push delivery row (payload + provider response; no full push token).

**Tags:** PushNotifications

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Push delivery

Content-Type: `application/json`

```json
{
  "item": {
    "id": "00000000-0000-4000-8000-000000000000",
    "tenant_id": "00000000-0000-4000-8000-000000000000",
    "organization_id": null,
    "notification_id": null,
    "notification_type_id": "string",
    "user_device_id": "00000000-0000-4000-8000-000000000000",
    "user_id": "00000000-0000-4000-8000-000000000000",
    "provider": "string",
    "token_snapshot": "string",
    "status": "pending",
    "attempts": 1,
    "last_error": null,
    "created_at": null,
    "sent_at": null,
    "next_retry_at": null,
    "updated_at": null,
    "payload": null,
    "provider_response": null
  }
}
```

**400** – Invalid id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing push_notifications.view_deliveries

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Delivery not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/push_notifications/deliveries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/query_index/purge`

Purge query index records

Queues a purge job to remove indexed records for an entity type within the active scope.

**Tags:** Query Index

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityType": "string"
}
```

### Responses

**200** – Purge job accepted.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing entity type

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/query_index/purge" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\"
}"
```

## POST `/query_index/reindex`

Trigger query index rebuild

Queues a reindex job for the specified entity type within the current tenant scope.

**Tags:** Query Index

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "entityType": "string"
}
```

### Responses

**200** – Reindex job accepted.

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing entity type

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/query_index/reindex" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"entityType\": \"string\"
}"
```

## GET `/query_index/status`

Inspect query index coverage

Returns entity counts comparing base tables with the query index along with the latest job status.

**Tags:** Query Index

**Requires authentication.**

### Responses

**200** – Current query index status.

Content-Type: `application/json`

```json
{
  "items": [
    {
      "entityId": "string",
      "label": "string",
      "baseCount": null,
      "indexCount": null,
      "vectorCount": null,
      "fulltextCount": null,
      "ok": true,
      "job": {
        "status": "idle",
        "startedAt": null,
        "finishedAt": null,
        "heartbeatAt": null,
        "processedCount": null,
        "totalCount": null,
        "scope": null
      },
      "refreshedAt": null
    }
  ],
  "errors": [
    {
      "id": "string",
      "source": "string",
      "handler": "string",
      "entityType": null,
      "recordId": null,
      "tenantId": null,
      "organizationId": null,
      "message": "string",
      "stack": null,
      "payload": null,
      "occurredAt": "string"
    }
  ],
  "logs": [
    {
      "id": "string",
      "source": "string",
      "handler": "string",
      "level": "info",
      "entityType": null,
      "recordId": null,
      "tenantId": null,
      "organizationId": null,
      "message": "string",
      "details": null,
      "occurredAt": "string"
    }
  ]
}
```

**400** – Tenant or organization context required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/query_index/status" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/ratelimit_probe/ping`

Test-only endpoint with per-route metadata.rateLimit — used to prove rate-limit leakage under OM_INTEGRATION_TEST

**Tags:** RateLimitProbe

### Responses

**200** – Always OK when under the points budget

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**429** – Rate limit exceeded (3 points / 60 s per client IP)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/ratelimit_probe/ping" \
  -H "Accept: application/json"
```

## POST `/record_locks/acquire`

Acquire lock for editing

**Tags:** Record Locks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "resourceKind": "string",
  "resourceId": "string"
}
```

### Responses

**200** – Lock acquisition result

Content-Type: `application/json`

```json
{
  "ok": true,
  "enabled": true,
  "resourceEnabled": true,
  "strategy": "optimistic",
  "allowForceUnlock": true,
  "heartbeatSeconds": 1,
  "acquired": true,
  "latestActionLogId": null,
  "lock": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**423** – Record locked by another user

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**429** – Per-user active lock quota exceeded

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/record_locks/acquire" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"resourceKind\": \"string\",
  \"resourceId\": \"string\"
}"
```

## POST `/record_locks/force-release`

Force release lock owned by another user

**Tags:** Record Locks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "resourceKind": "string",
  "resourceId": "string"
}
```

### Responses

**200** – Force release result

Content-Type: `application/json`

```json
{
  "ok": true,
  "released": true,
  "lock": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**403** – Missing permission

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**409** – No releasable lock

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/record_locks/force-release" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"resourceKind\": \"string\",
  \"resourceId\": \"string\"
}"
```

## POST `/record_locks/heartbeat`

Heartbeat active lock

**Tags:** Record Locks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "resourceKind": "string",
  "resourceId": "string",
  "token": "string"
}
```

### Responses

**200** – Heartbeat accepted

Content-Type: `application/json`

```json
{
  "ok": true,
  "expiresAt": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/record_locks/heartbeat" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"resourceKind\": \"string\",
  \"resourceId\": \"string\",
  \"token\": \"string\"
}"
```

## POST `/record_locks/release`

Release active lock owned by the caller

**Tags:** Record Locks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "resourceKind": "string",
  "resourceId": "string"
}
```

### Responses

**200** – Release result

Content-Type: `application/json`

```json
{
  "ok": true,
  "released": true,
  "conflictResolved": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/record_locks/release" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"resourceKind\": \"string\",
  \"resourceId\": \"string\"
}"
```

## GET `/record_locks/settings`

Get record locking settings

**Tags:** Record Locks

**Requires authentication.**

### Responses

**200** – Current record locking settings

Content-Type: `application/json`

```json
{
  "settings": {
    "enabled": true,
    "strategy": "optimistic",
    "timeoutSeconds": 300,
    "heartbeatSeconds": 30,
    "maxActiveLocksPerUser": 50,
    "enabledResources": [],
    "allowForceUnlock": true,
    "allowIncomingOverride": true,
    "notifyOnConflict": true
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/record_locks/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/record_locks/settings`

Update record locking settings

**Tags:** Record Locks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "enabled": true,
  "strategy": "optimistic",
  "timeoutSeconds": 300,
  "heartbeatSeconds": 30,
  "maxActiveLocksPerUser": 50,
  "enabledResources": [],
  "allowForceUnlock": true,
  "allowIncomingOverride": true,
  "notifyOnConflict": true
}
```

### Responses

**200** – Updated settings

Content-Type: `application/json`

```json
{
  "settings": {
    "enabled": true,
    "strategy": "optimistic",
    "timeoutSeconds": 300,
    "heartbeatSeconds": 30,
    "maxActiveLocksPerUser": 50,
    "enabledResources": [],
    "allowForceUnlock": true,
    "allowIncomingOverride": true,
    "notifyOnConflict": true
  }
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/record_locks/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"enabled\": true,
  \"strategy\": \"optimistic\",
  \"timeoutSeconds\": 300,
  \"heartbeatSeconds\": 30,
  \"maxActiveLocksPerUser\": 50,
  \"enabledResources\": [],
  \"allowForceUnlock\": true,
  \"allowIncomingOverride\": true,
  \"notifyOnConflict\": true
}"
```

## POST `/record_locks/validate`

Preflight lock validation for save/delete

**Tags:** Record Locks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "resourceKind": "string",
  "resourceId": "string",
  "method": "PUT",
  "resolution": "normal",
  "mutationPayload": null
}
```

### Responses

**200** – Validation result

Content-Type: `application/json`

```json
{
  "ok": true,
  "enabled": true,
  "resourceEnabled": true,
  "strategy": "optimistic",
  "shouldReleaseOnSuccess": true,
  "lock": null,
  "latestActionLogId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/record_locks/validate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"resourceKind\": \"string\",
  \"resourceId\": \"string\",
  \"method\": \"PUT\",
  \"resolution\": \"normal\",
  \"mutationPayload\": null
}"
```

## DELETE `/resources/activities`

Delete resourceactivity

Deletes a resource activity.

**Tags:** Resources

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – ResourceActivity deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/resources/activities" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/resources/activities`

List resourceactivitys

Returns a paginated collection of resourceactivitys scoped to the authenticated organization.

**Tags:** Resources

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| entityId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated resourceactivitys

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "resource_id": null,
      "activity_type": null,
      "subject": null,
      "body": null,
      "occurred_at": null,
      "author_user_id": null,
      "appearance_icon": null,
      "appearance_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/resources/activities?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/resources/activities`

Create resourceactivity

Adds an activity to a resource timeline.

**Tags:** Resources

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "activityType": "string",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**201** – ResourceActivity created

Content-Type: `application/json`

```json
{
  "id": null,
  "authorUserId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/activities" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"activityType\": \"string\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## PUT `/resources/activities`

Update resourceactivity

Updates a resource activity.

**Tags:** Resources

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**200** – ResourceActivity updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/resources/activities" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## DELETE `/resources/comments`

Delete resourcecomment

Deletes a resource note.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – ResourceComment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/resources/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/resources/comments`

List resourcecomments

Returns a paginated collection of resourcecomments scoped to the authenticated organization.

**Tags:** Resources

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| entityId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated resourcecomments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "resource_id": null,
      "body": null,
      "author_user_id": null,
      "appearance_icon": null,
      "appearance_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/resources/comments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/resources/comments`

Create resourcecomment

Adds a note to a resource timeline.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "entityId": "00000000-0000-4000-8000-000000000000",
  "body": "string",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**201** – ResourceComment created

Content-Type: `application/json`

```json
{
  "id": null,
  "authorUserId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"entityId\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## PUT `/resources/comments`

Update resourcecomment

Updates a resource note.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**200** – ResourceComment updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/resources/comments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## DELETE `/resources/resource-types`

Delete resource type

Deletes a resource type by id.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Resource type deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/resources/resource-types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/resources/resource-types`

List resource types

Returns a paginated collection of resource types scoped to the authenticated organization.

**Tags:** Resources

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withResourceCounts | query | any | Optional |

### Responses

**200** – Paginated resource types

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "name": null,
      "description": null,
      "appearance_icon": null,
      "appearance_color": null,
      "created_at": null,
      "updated_at": null,
      "resourceCount": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/resources/resource-types?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/resources/resource-types`

Create resource type

Creates a resource type for resources resources.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "description": null,
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**201** – Resource type created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/resource-types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"description\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## PUT `/resources/resource-types`

Update resource type

Updates a resource type by id.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**200** – Resource type updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/resources/resource-types" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## DELETE `/resources/resources`

Delete resource

Deletes a resource by id.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Resource deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/resources/resources" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/resources/resources`

List resources

Returns a paginated collection of resources scoped to the authenticated organization.

**Tags:** Resources

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| resourceTypeId | query | any | Optional |
| isActive | query | any | Optional |
| tagIds | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated resources

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "name": null,
      "description": null,
      "resource_type_id": null,
      "capacity": null,
      "capacity_unit_value": null,
      "capacity_unit_name": null,
      "capacity_unit_color": null,
      "capacity_unit_icon": null,
      "appearance_icon": null,
      "appearance_color": null,
      "is_active": null,
      "availability_rule_set_id": null,
      "custom_fieldset_code": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/resources/resources?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/resources/resources`

Create resource

Creates a resource scoped to the selected organization.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "description": null,
  "resourceTypeId": null,
  "capacity": null,
  "capacityUnitValue": null,
  "appearanceIcon": null,
  "appearanceColor": null,
  "availabilityRuleSetId": null,
  "customFieldsetCode": null
}
```

### Responses

**201** – Resource created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/resources" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"description\": null,
  \"resourceTypeId\": null,
  \"capacity\": null,
  \"capacityUnitValue\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null,
  \"availabilityRuleSetId\": null,
  \"customFieldsetCode\": null
}"
```

## PUT `/resources/resources`

Update resource

Updates a resource by id.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "description": null,
  "resourceTypeId": null,
  "capacity": null,
  "capacityUnitValue": null,
  "appearanceIcon": null,
  "appearanceColor": null,
  "availabilityRuleSetId": null,
  "customFieldsetCode": null
}
```

### Responses

**200** – Resource updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/resources/resources" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"description\": null,
  \"resourceTypeId\": null,
  \"capacity\": null,
  \"capacityUnitValue\": null,
  \"appearanceIcon\": null,
  \"appearanceColor\": null,
  \"availabilityRuleSetId\": null,
  \"customFieldsetCode\": null
}"
```

## POST `/resources/resources/tags/assign`

Assign resource tag

Assigns a tag to a resources resource.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tagId": "00000000-0000-4000-8000-000000000000",
  "resourceId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Tag assignment created

Content-Type: `application/json`

```json
{
  "id": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/resources/tags/assign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tagId\": \"00000000-0000-4000-8000-000000000000\",
  \"resourceId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/resources/resources/tags/unassign`

Unassign resource tag

Removes a tag from a resources resource.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tagId": "00000000-0000-4000-8000-000000000000",
  "resourceId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Tag assignment removed

Content-Type: `application/json`

```json
{
  "id": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/resources/tags/unassign" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tagId\": \"00000000-0000-4000-8000-000000000000\",
  \"resourceId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/resources/tags`

Delete resource tag

Deletes a resource tag by id.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Resource tag deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/resources/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/resources/tags`

List resource tags

Returns a paginated collection of resource tags scoped to the authenticated organization.

**Tags:** Resources

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated resource tags

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "slug": null,
      "label": null,
      "color": null,
      "description": null,
      "organization_id": null,
      "tenant_id": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/resources/tags?page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/resources/tags`

Create resource tag

Creates a tag for resources resources and services.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "label": "string",
  "color": null,
  "description": null
}
```

### Responses

**201** – Resource tag created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/resources/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"label\": \"string\",
  \"color\": null,
  \"description\": null
}"
```

## PUT `/resources/tags`

Update resource tag

Updates a resource tag by id.

**Tags:** Resources

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "color": null,
  "description": null
}
```

### Responses

**200** – Resource tag updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/resources/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"color\": null,
  \"description\": null
}"
```

## DELETE `/sales/adjustment-kinds`

Delete sales adjustment kind

Deletes an adjustment kind.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Sales adjustment kind deleted

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/adjustment-kinds" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/sales/adjustment-kinds`

List sales adjustment kinds

Returns a paginated collection of sales adjustment kinds that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated sales adjustment kinds

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null,
      "color": null,
      "icon": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/adjustment-kinds?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/adjustment-kinds`

Create sales adjustment kind

Creates an adjustment kind.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**201** – Sales adjustment kind created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/adjustment-kinds" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## PUT `/sales/adjustment-kinds`

Update sales adjustment kind

Updates an adjustment kind.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Sales adjustment kind updated

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/adjustment-kinds" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## DELETE `/sales/channels`

Delete sales channel

Deletes a sales channel identified by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Sales channel deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/channels`

List sales channels

Manage sales channels to segment orders and pricing across marketplaces or stores.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| id | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |

### Responses

**200** – Paginated sales channels

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "code": null,
      "description": null,
      "statusEntryId": null,
      "isActive": true,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/channels?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/channels`

Create sales channel

Creates a new sales channel.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "code": "string"
}
```

### Responses

**201** – Sales channel created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"code\": \"string\"
}"
```

## PUT `/sales/channels`

Update sales channel

Updates an existing sales channel by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "code": "string"
}
```

### Responses

**200** – Sales channel updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/channels" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"code\": \"string\"
}"
```

## DELETE `/sales/credit-memos`

Delete creditmemo

Delete a credit memo

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – CreditMemo deleted

Content-Type: `application/json`

```json
{
  "creditMemoId": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/credit-memos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/credit-memos`

List creditmemos

Returns a paginated collection of creditmemos that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| id | query | any | Optional |
| orderId | query | any | Optional |
| invoiceId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated creditmemos

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "creditMemoNumber": "string",
      "status": null,
      "reason": null,
      "issueDate": null,
      "currencyCode": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/credit-memos?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/credit-memos`

Create creditmemo

Create a new credit memo

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string"
}
```

### Responses

**201** – CreditMemo created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/credit-memos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\"
}"
```

## PUT `/sales/credit-memos`

Update creditmemo

Update a credit memo

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – CreditMemo updated

Content-Type: `application/json`

```json
{
  "creditMemoId": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/credit-memos" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/dashboard/widgets/new-orders`

Fetch recently created sales orders

Fetches recently created sales orders for the dashboard widget with a configurable date period.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| datePeriod | query | any | Optional |
| customFrom | query | any | Optional |
| customTo | query | any | Optional |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |

### Responses

**200** – List of recent orders

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "orderNumber": "string",
      "status": null,
      "fulfillmentStatus": null,
      "paymentStatus": null,
      "customerName": null,
      "customerEntityId": null,
      "netAmount": "string",
      "grossAmount": "string",
      "currency": null,
      "createdAt": "string"
    }
  ],
  "total": 1,
  "dateRange": {
    "from": "string",
    "to": "string"
  }
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Widget failed to load

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/dashboard/widgets/new-orders?limit=5&datePeriod=last24h" \
  -H "Accept: application/json"
```

## GET `/sales/dashboard/widgets/new-quotes`

Fetch recently created sales quotes

Fetches recently created sales quotes for the dashboard widget with a configurable date period.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| limit | query | any | Optional |
| datePeriod | query | any | Optional |
| customFrom | query | any | Optional |
| customTo | query | any | Optional |
| tenantId | query | any | Optional |
| organizationId | query | any | Optional |

### Responses

**200** – List of recent quotes

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "quoteNumber": "string",
      "status": null,
      "customerName": null,
      "customerEntityId": null,
      "validFrom": null,
      "validUntil": null,
      "netAmount": "string",
      "grossAmount": "string",
      "currency": null,
      "createdAt": "string",
      "convertedOrderId": null
    }
  ],
  "total": 1,
  "dateRange": {
    "from": "string",
    "to": "string"
  }
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Widget failed to load

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/dashboard/widgets/new-quotes?limit=5&datePeriod=last24h" \
  -H "Accept: application/json"
```

## DELETE `/sales/delivery-windows`

Delete delivery window

Deletes a delivery window identified by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Delivery window deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/delivery-windows" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/delivery-windows`

List delivery windows

Define delivery windows to communicate lead times and cut-off rules for sales orders.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated delivery windows

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "code": null,
      "description": null,
      "leadTimeDays": null,
      "cutoffTime": null,
      "timezone": null,
      "isActive": true,
      "metadata": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/delivery-windows?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/delivery-windows`

Create delivery window

Creates a new delivery window.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "code": "string"
}
```

### Responses

**201** – Delivery window created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/delivery-windows" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"code\": \"string\"
}"
```

## PUT `/sales/delivery-windows`

Update delivery window

Updates an existing delivery window by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Delivery window updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/delivery-windows" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/document-addresses`

Delete document address

Deletes a sales document address.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "documentId": "00000000-0000-4000-8000-000000000000",
  "documentKind": "order"
}
```

### Responses

**200** – Document address deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/document-addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"documentId\": \"00000000-0000-4000-8000-000000000000\",
  \"documentKind\": \"order\"
}"
```

## GET `/sales/document-addresses`

List document addresss

Returns a paginated collection of document addresss that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| documentId | query | any | Required |
| documentKind | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated document addresss

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "document_id": "00000000-0000-4000-8000-000000000000",
      "document_kind": "order",
      "customer_address_id": null,
      "name": null,
      "purpose": null,
      "company_name": null,
      "address_line1": "string",
      "address_line2": null,
      "building_number": null,
      "flat_number": null,
      "city": null,
      "region": null,
      "postal_code": null,
      "country": null,
      "latitude": null,
      "longitude": null,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/document-addresses?page=1&pageSize=50&documentId=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/document-addresses`

Create document address

Creates a sales document address linked to an order or quote.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "documentId": "00000000-0000-4000-8000-000000000000",
  "documentKind": "order",
  "name": null,
  "purpose": null,
  "companyName": null,
  "addressLine1": "string",
  "addressLine2": null,
  "city": null,
  "region": null,
  "postalCode": null,
  "country": null,
  "buildingNumber": null,
  "flatNumber": null,
  "latitude": null,
  "longitude": null
}
```

### Responses

**201** – Document address created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/document-addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"documentId\": \"00000000-0000-4000-8000-000000000000\",
  \"documentKind\": \"order\",
  \"name\": null,
  \"purpose\": null,
  \"companyName\": null,
  \"addressLine1\": \"string\",
  \"addressLine2\": null,
  \"city\": null,
  \"region\": null,
  \"postalCode\": null,
  \"country\": null,
  \"buildingNumber\": null,
  \"flatNumber\": null,
  \"latitude\": null,
  \"longitude\": null
}"
```

## PUT `/sales/document-addresses`

Update document address

Updates a sales document address.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "id": "00000000-0000-4000-8000-000000000000",
  "documentId": "00000000-0000-4000-8000-000000000000",
  "documentKind": "order",
  "name": null,
  "purpose": null,
  "companyName": null,
  "addressLine1": "string",
  "addressLine2": null,
  "city": null,
  "region": null,
  "postalCode": null,
  "country": null,
  "buildingNumber": null,
  "flatNumber": null,
  "latitude": null,
  "longitude": null
}
```

### Responses

**200** – Document address updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/document-addresses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"documentId\": \"00000000-0000-4000-8000-000000000000\",
  \"documentKind\": \"order\",
  \"name\": null,
  \"purpose\": null,
  \"companyName\": null,
  \"addressLine1\": \"string\",
  \"addressLine2\": null,
  \"city\": null,
  \"region\": null,
  \"postalCode\": null,
  \"country\": null,
  \"buildingNumber\": null,
  \"flatNumber\": null,
  \"latitude\": null,
  \"longitude\": null
}"
```

## GET `/sales/document-history`

List history entries for an order or quote

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| kind | query | any | Required |
| id | query | any | Required |
| limit | query | any | Optional |
| before | query | any | Optional |
| after | query | any | Optional |
| types | query | any | Optional |

### Responses

**200** – History entries

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "occurredAt": "string",
      "kind": "status",
      "action": "string",
      "actor": {
        "id": null,
        "label": "string"
      },
      "source": "action_log"
    }
  ]
}
```

**400** – Invalid query

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Document not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/document-history?kind=order&id=00000000-0000-4000-8000-000000000000&limit=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/document-numbers`

Generate next number

Generates the next sales order or quote number using configured formatting rules.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "kind": "order"
}
```

### Responses

**200** – Generated number

Content-Type: `application/json`

```json
{
  "number": "string",
  "format": "string",
  "sequence": 1
}
```

**400** – Invalid input or scope missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/document-numbers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"kind\": \"order\"
}"
```

## DELETE `/sales/invoices`

Delete invoice

Delete an invoice

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Invoice deleted

Content-Type: `application/json`

```json
{
  "invoiceId": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/invoices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/invoices`

List invoices

Returns a paginated collection of invoices that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| id | query | any | Optional |
| orderId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated invoices

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "invoiceNumber": "string",
      "status": null,
      "issueDate": null,
      "dueDate": null,
      "currencyCode": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/invoices?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/invoices`

Create invoice

Create a new invoice

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string"
}
```

### Responses

**201** – Invoice created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/invoices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\"
}"
```

## PUT `/sales/invoices`

Update invoice

Update an invoice

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Invoice updated

Content-Type: `application/json`

```json
{
  "invoiceId": "00000000-0000-4000-8000-000000000000"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/invoices" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/notes`

Delete sales note

Deletes a sales note.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Sales note deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/notes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/notes`

List sales notes

Returns a paginated collection of sales notes that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| contextType | query | any | Optional |
| contextId | query | any | Optional |
| orderId | query | any | Optional |
| quoteId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated sales notes

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "context_type": "order",
      "context_id": "00000000-0000-4000-8000-000000000000",
      "order_id": null,
      "quote_id": null,
      "body": null,
      "author_user_id": null,
      "appearance_icon": null,
      "appearance_color": null,
      "organization_id": null,
      "tenant_id": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/notes?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/notes`

Create sales note

Creates a note attached to a sales document.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "contextType": "order",
  "contextId": "00000000-0000-4000-8000-000000000000",
  "body": "string",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**201** – Sales note created

Content-Type: `application/json`

```json
{
  "id": null,
  "authorUserId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/notes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"contextType\": \"order\",
  \"contextId\": \"00000000-0000-4000-8000-000000000000\",
  \"body\": \"string\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## PUT `/sales/notes`

Update sales note

Updates a sales note.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "appearanceIcon": null,
  "appearanceColor": null
}
```

### Responses

**200** – Sales note updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/notes" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"appearanceIcon\": null,
  \"appearanceColor\": null
}"
```

## DELETE `/sales/order-adjustments`

Delete order adjustment

Deletes an order adjustment and recalculates totals.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order adjustment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/order-adjustments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/order-adjustments`

List order adjustments

Returns a paginated collection of order adjustments that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| orderId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated order adjustments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "order_id": "00000000-0000-4000-8000-000000000000",
      "order_line_id": null,
      "scope": "string",
      "kind": "string",
      "code": null,
      "label": null,
      "calculator_key": null,
      "promotion_id": null,
      "rate": 1,
      "amount_net": 1,
      "amount_gross": 1,
      "currency_code": null,
      "metadata": null,
      "position": 1,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/order-adjustments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/order-adjustments`

Create order adjustment

Creates an order adjustment and recalculates totals.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Order adjustment created

Content-Type: `application/json`

```json
{
  "id": null,
  "orderId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/order-adjustments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/sales/order-adjustments`

Update order adjustment

Updates an order adjustment and recalculates totals.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order adjustment updated

Content-Type: `application/json`

```json
{
  "id": null,
  "orderId": null
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/order-adjustments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/order-line-statuses`

Delete order line status

Deletes a order line status identified by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order line status deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/order-line-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/order-line-statuses`

List order line statuses

Manage custom order line statuses available for sales documents.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated order line statuses

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null,
      "color": null,
      "icon": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/order-line-statuses?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/order-line-statuses`

Create order line status

Creates a new order line status.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "color": null,
  "icon": null
}
```

### Responses

**201** – Order line status created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/order-line-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"value\": \"string\",
  \"color\": null,
  \"icon\": null
}"
```

## PUT `/sales/order-line-statuses`

Update order line status

Updates an existing order line status by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "color": null,
  "icon": null,
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order line status updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/order-line-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"color\": null,
  \"icon\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/order-lines`

Delete order line

Deletes an order line and recalculates totals.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order line deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/order-lines" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/order-lines`

List order lines

Returns a paginated collection of order lines that belong to the current organization.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| orderId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated order lines

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "order_id": "00000000-0000-4000-8000-000000000000",
      "line_number": 1,
      "kind": "string",
      "status_entry_id": null,
      "status": null,
      "product_id": null,
      "product_variant_id": null,
      "catalog_snapshot": null,
      "name": null,
      "description": null,
      "comment": null,
      "quantity": 1,
      "quantity_unit": null,
      "normalized_quantity": 1,
      "normalized_unit": null,
      "uom_snapshot": null,
      "currency_code": "string",
      "unit_price_net": 1,
      "unit_price_gross": 1,
      "discount_amount": 1,
      "discount_percent": 1,
      "tax_rate": 1,
      "tax_amount": 1,
      "total_net_amount": 1,
      "total_gross_amount": 1,
      "configuration": null,
      "promotion_code": null,
      "promotion_snapshot": null,
      "metadata": null,
      "custom_field_set_id": null,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/order-lines?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/order-lines`

Create order line

Creates an order line and recalculates totals.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string",
  "uomSnapshot": null,
  "quantity": 1,
  "normalizedUnit": null
}
```

### Responses

**201** – Order line created

Content-Type: `application/json`

```json
{
  "id": null,
  "orderId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/order-lines" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\",
  \"uomSnapshot\": null,
  \"quantity\": 1,
  \"normalizedUnit\": null
}"
```

## PUT `/sales/order-lines`

Update order line

Updates an order line and recalculates totals.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string",
  "uomSnapshot": null,
  "quantity": 1,
  "normalizedUnit": null
}
```

### Responses

**200** – Order line updated

Content-Type: `application/json`

```json
{
  "id": null,
  "orderId": null
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/order-lines" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\",
  \"uomSnapshot\": null,
  \"quantity\": 1,
  \"normalizedUnit\": null
}"
```

## DELETE `/sales/order-statuses`

Delete order status

Deletes a order status identified by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order status deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/order-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/order-statuses`

List order statuses

Manage the lifecycle states available for sales orders.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated order statuses

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null,
      "color": null,
      "icon": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/order-statuses?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/order-statuses`

Create order status

Creates a new order status.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "color": null,
  "icon": null
}
```

### Responses

**201** – Order status created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/order-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"value\": \"string\",
  \"color\": null,
  \"icon\": null
}"
```

## PUT `/sales/order-statuses`

Update order status

Updates an existing order status by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "color": null,
  "icon": null,
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order status updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/order-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"color\": null,
  \"icon\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/orders`

Delete order

Deletes a sales order.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Order deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/orders" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/orders`

List orders

Returns a paginated collection of orders that belong to the current organization.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| id | query | any | Optional |
| customerId | query | any | Optional |
| channelId | query | any | Optional |
| channelIds | query | any | Optional. Comma-separated sales channel uuids; matches documents on any of them. Capped at 200 ids, malformed entries are dropped. Ignored when channelId is supplied; combines with channelIdsEmpty. |
| channelIdsEmpty | query | any | Optional. Boolean token; matches documents with no sales channel. Ignored when channelId is supplied; combines with channelIds. |
| lineItemCountMin | query | any | Optional |
| lineItemCountMax | query | any | Optional |
| totalNetMin | query | any | Optional |
| totalNetMax | query | any | Optional |
| totalGrossMin | query | any | Optional |
| totalGrossMax | query | any | Optional |
| dateFrom | query | any | Optional |
| dateTo | query | any | Optional |
| tagIds | query | any | Optional |
| tagIdsEmpty | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated orders

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "orderNumber": null,
      "status": null,
      "statusEntryId": null,
      "customerEntityId": null,
      "customerContactId": null,
      "billingAddressId": null,
      "shippingAddressId": null,
      "customerReference": null,
      "externalReference": null,
      "comment": null,
      "placedAt": null,
      "expectedDeliveryAt": null,
      "customerSnapshot": null,
      "billingAddressSnapshot": null,
      "shippingAddressSnapshot": null,
      "shippingMethodId": null,
      "shippingMethodCode": null,
      "shippingMethodSnapshot": null,
      "paymentMethodId": null,
      "paymentMethodCode": null,
      "paymentMethodSnapshot": null,
      "currencyCode": null,
      "channelId": null,
      "channelName": null,
      "channelCode": null,
      "organizationId": null,
      "tenantId": null,
      "validFrom": null,
      "validUntil": null,
      "lineItemCount": null,
      "subtotalNetAmount": null,
      "subtotalGrossAmount": null,
      "discountTotalAmount": null,
      "taxTotalAmount": null,
      "shippingNetAmount": null,
      "shippingGrossAmount": null,
      "surchargeTotalAmount": null,
      "grandTotalNetAmount": null,
      "grandTotalGrossAmount": null,
      "paidTotalAmount": null,
      "refundedTotalAmount": null,
      "outstandingAmount": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/orders?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/orders`

Create order

Creates a new sales order. paidTotalAmount, refundedTotalAmount, and outstandingAmount are deprecated compatibility inputs: supplied values are ignored and reported in warnings. Record payments through sales.payments.create or POST /api/sales/payments.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string",
  "lines": [
    {
      "currencyCode": "string",
      "uomSnapshot": null,
      "quantity": 1,
      "normalizedUnit": null
    }
  ]
}
```

### Responses

**201** – Order created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/orders" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\",
  \"lines\": [
    {
      \"currencyCode\": \"string\",
      \"uomSnapshot\": null,
      \"quantity\": 1,
      \"normalizedUnit\": null
    }
  ]
}"
```

## PUT `/sales/orders`

Order management

**Tags:** Sales

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/orders" \
  -H "Accept: application/json"
```

## DELETE `/sales/payment-methods`

Delete payment method

Deletes a payment method identified by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Payment method deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/payment-methods" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/payment-methods`

List payment methods

Configure payment options that can be assigned to sales orders and invoices.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated payment methods

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "code": "string",
      "description": null,
      "providerKey": null,
      "terms": null,
      "isActive": true,
      "metadata": null,
      "providerSettings": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/payment-methods?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/payment-methods`

Create payment method

Creates a new payment method.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "code": "string"
}
```

### Responses

**201** – Payment method created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/payment-methods" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"code\": \"string\"
}"
```

## PUT `/sales/payment-methods`

Update payment method

Updates an existing payment method by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Payment method updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/payment-methods" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/payment-statuses`

Delete payment status

Deletes a payment status identified by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Payment status deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/payment-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/payment-statuses`

List payment statuses

Manage the lifecycle states available for payments.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated payment statuses

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null,
      "color": null,
      "icon": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/payment-statuses?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/payment-statuses`

Create payment status

Creates a new payment status.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "color": null,
  "icon": null
}
```

### Responses

**201** – Payment status created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/payment-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"value\": \"string\",
  \"color\": null,
  \"icon\": null
}"
```

## PUT `/sales/payment-statuses`

Update payment status

Updates an existing payment status by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "color": null,
  "icon": null,
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Payment status updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/payment-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"color\": null,
  \"icon\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/payments`

Delete payment

Deletes a payment.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Payment deleted

Content-Type: `application/json`

```json
{
  "id": null,
  "orderTotals": null
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/payments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/payments`

List payments

Returns a paginated collection of payments that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| orderId | query | any | Optional |
| paymentMethodId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated payments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "order_id": null,
      "payment_method_id": null,
      "payment_method_name": null,
      "payment_method_code": null,
      "payment_reference": null,
      "status_entry_id": null,
      "status": null,
      "status_label": null,
      "amount": 1,
      "currency_code": "string",
      "captured_amount": null,
      "refunded_amount": null,
      "received_at": null,
      "captured_at": null,
      "custom_field_set_id": null,
      "customFieldSetId": null,
      "custom_values": null,
      "customValues": null,
      "custom_fields": null,
      "customFields": null,
      "metadata": null,
      "created_at": "string",
      "updated_at": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/payments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/payments`

Create payment

Creates a payment for a sales order.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "amount": 1,
  "currencyCode": "string"
}
```

### Responses

**201** – Payment created

Content-Type: `application/json`

```json
{
  "id": null,
  "orderTotals": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/payments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"amount\": 1,
  \"currencyCode\": \"string\"
}"
```

## PUT `/sales/payments`

Update payment

Updates a payment.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Payment updated

Content-Type: `application/json`

```json
{
  "id": null,
  "orderTotals": null
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/payments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/price-kinds`

List price kinds

Lists available price kinds that can be used when pricing sales channels and offers.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated price kinds

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "code": "string",
      "title": "string",
      "currency_code": null,
      "display_mode": "string",
      "is_active": true
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/price-kinds?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/sales/quote-adjustments`

Delete quote adjustment

Deletes a quote adjustment and recalculates totals.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "quoteId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Quote adjustment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/quote-adjustments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/quote-adjustments`

List quote adjustments

Returns a paginated collection of quote adjustments that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| quoteId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated quote adjustments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "quote_id": "00000000-0000-4000-8000-000000000000",
      "quote_line_id": null,
      "scope": "string",
      "kind": "string",
      "code": null,
      "label": null,
      "calculator_key": null,
      "promotion_id": null,
      "rate": 1,
      "amount_net": 1,
      "amount_gross": 1,
      "currency_code": null,
      "metadata": null,
      "position": 1,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/quote-adjustments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/quote-adjustments`

Create quote adjustment

Creates a quote adjustment and recalculates totals.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "quoteId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Quote adjustment created

Content-Type: `application/json`

```json
{
  "id": null,
  "quoteId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/quote-adjustments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/sales/quote-adjustments`

Update quote adjustment

Updates a quote adjustment and recalculates totals.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "quoteId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Quote adjustment updated

Content-Type: `application/json`

```json
{
  "id": null,
  "quoteId": null
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/quote-adjustments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/quote-lines`

Delete quote line

Deletes a quote line and recalculates totals.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "quoteId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Quote line deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/quote-lines" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/quote-lines`

List quote lines

Returns a paginated collection of quote lines that belong to the current organization.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| quoteId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated quote lines

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "quote_id": "00000000-0000-4000-8000-000000000000",
      "line_number": 1,
      "kind": "string",
      "status_entry_id": null,
      "status": null,
      "product_id": null,
      "product_variant_id": null,
      "catalog_snapshot": null,
      "name": null,
      "description": null,
      "comment": null,
      "quantity": 1,
      "quantity_unit": null,
      "normalized_quantity": 1,
      "normalized_unit": null,
      "uom_snapshot": null,
      "currency_code": "string",
      "unit_price_net": 1,
      "unit_price_gross": 1,
      "discount_amount": 1,
      "discount_percent": 1,
      "tax_rate": 1,
      "tax_amount": 1,
      "total_net_amount": 1,
      "total_gross_amount": 1,
      "configuration": null,
      "promotion_code": null,
      "promotion_snapshot": null,
      "metadata": null,
      "custom_field_set_id": null,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/quote-lines?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/quote-lines`

Create quote line

Creates a quote line and recalculates totals.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "quoteId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string",
  "uomSnapshot": null,
  "quantity": 1,
  "normalizedUnit": null
}
```

### Responses

**201** – Quote line created

Content-Type: `application/json`

```json
{
  "id": null,
  "quoteId": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/quote-lines" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\",
  \"uomSnapshot\": null,
  \"quantity\": 1,
  \"normalizedUnit\": null
}"
```

## PUT `/sales/quote-lines`

Update quote line

Updates a quote line and recalculates totals.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "quoteId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string",
  "uomSnapshot": null,
  "quantity": 1,
  "normalizedUnit": null
}
```

### Responses

**200** – Quote line updated

Content-Type: `application/json`

```json
{
  "id": null,
  "quoteId": null
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/quote-lines" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\",
  \"uomSnapshot\": null,
  \"quantity\": 1,
  \"normalizedUnit\": null
}"
```

## DELETE `/sales/quotes`

Delete quote

Deletes a sales quote.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Quote deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/quotes" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/quotes`

List quotes

Returns a paginated collection of quotes that belong to the current organization.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| id | query | any | Optional |
| customerId | query | any | Optional |
| channelId | query | any | Optional |
| channelIds | query | any | Optional. Comma-separated sales channel uuids; matches documents on any of them. Capped at 200 ids, malformed entries are dropped. Ignored when channelId is supplied; combines with channelIdsEmpty. |
| channelIdsEmpty | query | any | Optional. Boolean token; matches documents with no sales channel. Ignored when channelId is supplied; combines with channelIds. |
| lineItemCountMin | query | any | Optional |
| lineItemCountMax | query | any | Optional |
| totalNetMin | query | any | Optional |
| totalNetMax | query | any | Optional |
| totalGrossMin | query | any | Optional |
| totalGrossMax | query | any | Optional |
| dateFrom | query | any | Optional |
| dateTo | query | any | Optional |
| tagIds | query | any | Optional |
| tagIdsEmpty | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated quotes

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "quoteNumber": null,
      "status": null,
      "statusEntryId": null,
      "customerEntityId": null,
      "customerContactId": null,
      "billingAddressId": null,
      "shippingAddressId": null,
      "customerReference": null,
      "externalReference": null,
      "comment": null,
      "placedAt": null,
      "expectedDeliveryAt": null,
      "customerSnapshot": null,
      "billingAddressSnapshot": null,
      "shippingAddressSnapshot": null,
      "shippingMethodId": null,
      "shippingMethodCode": null,
      "shippingMethodSnapshot": null,
      "paymentMethodId": null,
      "paymentMethodCode": null,
      "paymentMethodSnapshot": null,
      "currencyCode": null,
      "channelId": null,
      "channelName": null,
      "channelCode": null,
      "organizationId": null,
      "tenantId": null,
      "validFrom": null,
      "validUntil": null,
      "lineItemCount": null,
      "subtotalNetAmount": null,
      "subtotalGrossAmount": null,
      "discountTotalAmount": null,
      "taxTotalAmount": null,
      "shippingNetAmount": null,
      "shippingGrossAmount": null,
      "surchargeTotalAmount": null,
      "grandTotalNetAmount": null,
      "grandTotalGrossAmount": null,
      "paidTotalAmount": null,
      "refundedTotalAmount": null,
      "outstandingAmount": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/quotes?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/quotes`

Create quote

Creates a new sales quote.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "currencyCode": "string"
}
```

### Responses

**201** – Quote created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/quotes" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"currencyCode\": \"string\"
}"
```

## PUT `/sales/quotes`

Quote management

**Tags:** Sales

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/quotes" \
  -H "Accept: application/json"
```

## POST `/sales/quotes/accept`

Accept quote and convert to order

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "token": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Quote accepted and order created

Content-Type: `application/json`

```json
{
  "orderId": "00000000-0000-4000-8000-000000000000",
  "orderNumber": "string"
}
```

**400** – Invalid or expired quote

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Cross-site request rejected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Quote not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Too many requests

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/quotes/accept" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"token\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/sales/quotes/convert`

Convert quote

Creates a sales order from a quote and removes the original quote record.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "quoteId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Conversion succeeded

Content-Type: `application/json`

```json
{
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Conflict detected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**423** – Record locked

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/quotes/convert" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/quotes/public/{token}`

Get quote details by acceptance token

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| token | path | any | Required |

### Responses

**200** – Quote details

Content-Type: `application/json`

```json
{
  "quote": {
    "quoteNumber": "string",
    "currencyCode": "string",
    "validFrom": null,
    "validUntil": null,
    "status": null,
    "subtotalNetAmount": "string",
    "subtotalGrossAmount": "string",
    "discountTotalAmount": "string",
    "taxTotalAmount": "string",
    "grandTotalNetAmount": "string",
    "grandTotalGrossAmount": "string"
  },
  "lines": [
    {
      "lineNumber": null,
      "kind": "string",
      "name": null,
      "description": null,
      "quantity": "string",
      "quantityUnit": null,
      "normalizedQuantity": "string",
      "normalizedUnit": null,
      "uomSnapshot": null,
      "currencyCode": "string",
      "unitPriceNet": "string",
      "unitPriceGross": "string",
      "discountAmount": "string",
      "discountPercent": "string",
      "taxRate": "string",
      "taxAmount": "string",
      "totalNetAmount": "string",
      "totalGrossAmount": "string",
      "unitPriceReference": null
    }
  ],
  "adjustments": [
    {
      "scope": null,
      "kind": null,
      "label": null,
      "rate": null,
      "amountNet": null,
      "amountGross": null,
      "currencyCode": null,
      "position": null,
      "quoteLineId": null
    }
  ],
  "isExpired": true
}
```

**404** – Quote not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/quotes/public/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## POST `/sales/quotes/send`

Send quote

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "quoteId": "00000000-0000-4000-8000-000000000000",
  "validForDays": 14
}
```

### Responses

**200** – Email queued

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Conflict detected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**423** – Record locked

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/quotes/send" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"quoteId\": \"00000000-0000-4000-8000-000000000000\",
  \"validForDays\": 14
}"
```

## DELETE `/sales/returns`

Delete return

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "id": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Return deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/returns" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/returns`

List returns

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| orderId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Returns list

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "order_id": "00000000-0000-4000-8000-000000000000",
      "return_number": "string",
      "status_entry_id": null,
      "status": null,
      "reason": null,
      "notes": null,
      "returned_at": null,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/returns?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/returns`

Create return

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000",
  "lines": [
    {
      "orderLineId": "00000000-0000-4000-8000-000000000000",
      "quantity": 1
    }
  ]
}
```

### Responses

**201** – Return created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/returns" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\",
  \"lines\": [
    {
      \"orderLineId\": \"00000000-0000-4000-8000-000000000000\",
      \"quantity\": 1
    }
  ]
}"
```

## PUT `/sales/returns`

Update return

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "id": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Return updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/returns" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/returns/{id}`

Get return details

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Return details

Content-Type: `application/json`

```json
{
  "return": {
    "id": "00000000-0000-4000-8000-000000000000",
    "orderId": "00000000-0000-4000-8000-000000000000",
    "returnNumber": "string",
    "statusEntryId": null,
    "status": null,
    "reason": null,
    "notes": null,
    "returnedAt": null,
    "createdAt": null,
    "updatedAt": null,
    "totalNetAmount": 1,
    "totalGrossAmount": 1
  },
  "lines": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "orderLineId": null,
      "quantityReturned": "string",
      "unitPriceNet": "string",
      "unitPriceGross": "string",
      "totalNetAmount": "string",
      "totalGrossAmount": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/returns/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/sales/settings/document-numbers`

Get document numbering settings

**Tags:** Sales

**Requires authentication.**

### Responses

**200** – Current numbering formats and counters

Content-Type: `application/json`

```json
{
  "orderNumberFormat": "string",
  "quoteNumberFormat": "string",
  "nextOrderNumber": 1,
  "nextQuoteNumber": 1
}
```

**400** – Missing scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/settings/document-numbers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/sales/settings/document-numbers`

Update document numbering settings

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderNumberFormat": "string",
  "quoteNumberFormat": "string",
  "orderCustomerEditableStatuses": null,
  "orderAddressEditableStatuses": null
}
```

### Responses

**200** – Updated numbering formats and counters

Content-Type: `application/json`

```json
{
  "orderNumberFormat": "string",
  "quoteNumberFormat": "string",
  "nextOrderNumber": 1,
  "nextQuoteNumber": 1
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/settings/document-numbers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderNumberFormat\": \"string\",
  \"quoteNumberFormat\": \"string\",
  \"orderCustomerEditableStatuses\": null,
  \"orderAddressEditableStatuses\": null
}"
```

## GET `/sales/settings/order-editing`

Get order editing guards

**Tags:** Sales

**Requires authentication.**

### Responses

**200** – Current order editing guards

Content-Type: `application/json`

```json
{
  "orderCustomerEditableStatuses": null,
  "orderAddressEditableStatuses": null,
  "orderStatuses": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": "string"
    }
  ]
}
```

**400** – Missing scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/settings/order-editing" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/sales/settings/order-editing`

Update order editing guards

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderCustomerEditableStatuses": null,
  "orderAddressEditableStatuses": null
}
```

### Responses

**200** – Updated order editing guards

Content-Type: `application/json`

```json
{
  "orderCustomerEditableStatuses": null,
  "orderAddressEditableStatuses": null,
  "orderStatuses": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": "string"
    }
  ]
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/settings/order-editing" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderCustomerEditableStatuses\": null,
  \"orderAddressEditableStatuses\": null
}"
```

## DELETE `/sales/shipment-statuses`

Delete shipment status

Deletes a shipment status identified by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Shipment status deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/shipment-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/shipment-statuses`

List shipment statuses

Manage the lifecycle states available for shipments.

**Tags:** Sales

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated shipment statuses

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "value": "string",
      "label": null,
      "color": null,
      "icon": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/shipment-statuses?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## POST `/sales/shipment-statuses`

Create shipment status

Creates a new shipment status.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "value": "string",
  "color": null,
  "icon": null
}
```

### Responses

**201** – Shipment status created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/shipment-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"value\": \"string\",
  \"color\": null,
  \"icon\": null
}"
```

## PUT `/sales/shipment-statuses`

Update shipment status

Updates an existing shipment status by id.

**Tags:** Sales

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "color": null,
  "icon": null,
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Shipment status updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/shipment-statuses" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"color\": null,
  \"icon\": null,
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/shipments`

Delete shipment

Deletes a shipment.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Shipment deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/shipments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/shipments`

List shipments

Returns a paginated collection of shipments that belong to the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| orderId | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated shipments

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "order_id": "00000000-0000-4000-8000-000000000000",
      "shipment_number": null,
      "shipping_method_id": null,
      "shipping_method_code": null,
      "shipping_method_name": null,
      "status_entry_id": null,
      "status": null,
      "status_label": null,
      "carrier_name": null,
      "tracking_numbers": null,
      "shipped_at": null,
      "delivered_at": null,
      "weight_value": null,
      "weight_unit": null,
      "declared_value_net": null,
      "declared_value_gross": null,
      "currency_code": null,
      "notes": null,
      "metadata": null,
      "custom_values": null,
      "customValues": null,
      "custom_fields": null,
      "customFields": null,
      "items_snapshot": null,
      "itemsSnapshot": null,
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/shipments?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/shipments`

Create shipment

Creates a shipment for an order.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "orderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**201** – Shipment created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/shipments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"orderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/sales/shipments`

Update shipment

Updates a shipment.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Shipment updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/shipments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/shipping-methods`

Delete shipping method

Deletes a shipping method identified by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Shipping method deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/shipping-methods" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/shipping-methods`

List shipping methods

Maintain shipping services, carrier mappings, and pricing defaults for order fulfillment.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| currency | query | any | Optional |
| id | query | any | Optional |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated shipping methods

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "code": "string",
      "description": null,
      "carrierCode": null,
      "providerKey": null,
      "serviceLevel": null,
      "estimatedTransitDays": null,
      "baseRateNet": "string",
      "baseRateGross": "string",
      "currencyCode": null,
      "isActive": true,
      "metadata": null,
      "providerSettings": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/shipping-methods?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/shipping-methods`

Create shipping method

Creates a new shipping method.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "code": "string"
}
```

### Responses

**201** – Shipping method created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/shipping-methods" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"code\": \"string\"
}"
```

## PUT `/sales/shipping-methods`

Update shipping method

Updates an existing shipping method by id.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Shipping method updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/shipping-methods" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/tags`

Delete sales tag

Deletes a sales tag.

**Tags:** Sales

**Requires authentication.**

### Responses

**200** – Sales tag deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/sales/tags`

List sales tags

Manage reusable tags to categorize sales orders and quotes.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated sales tags

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "slug": "string",
      "label": null,
      "color": null,
      "description": null,
      "organization_id": null,
      "tenant_id": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/tags?page=1&pageSize=100" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/tags`

Create sales tag

Creates a sales document tag.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "slug": "string",
  "label": "string"
}
```

### Responses

**201** – Sales tag created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"slug\": \"string\",
  \"label\": \"string\"
}"
```

## PUT `/sales/tags`

Update sales tag

Updates an existing sales tag.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Sales tag updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/tags" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/sales/tax-rates`

Delete tax rate

Deletes a tax rate identified by `id`.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Deletion acknowledgement

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/sales/tax-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/sales/tax-rates`

List tax rates

Returns a paginated list of sales tax rates for the current organization.

**Tags:** Sales

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| country | query | any | Optional |
| region | query | any | Optional |
| channelId | query | any | Optional |
| id | query | any | Optional |
| isCompound | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |
| withDeleted | query | any | Optional |

### Responses

**200** – Paginated list of tax rates

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "code": null,
      "rate": 1,
      "countryCode": null,
      "regionCode": null,
      "postalCode": null,
      "city": null,
      "customerGroupId": null,
      "productCategoryId": null,
      "channelId": null,
      "priority": null,
      "isCompound": true,
      "isDefault": true,
      "metadata": null,
      "startsAt": null,
      "endsAt": null,
      "organizationId": null,
      "tenantId": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sales/tax-rates?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sales/tax-rates`

Create tax rate

Creates a new tax rate record.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "code": "string",
  "rate": 1
}
```

### Responses

**201** – Identifier of the created tax rate

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sales/tax-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"code\": \"string\",
  \"rate\": 1
}"
```

## PUT `/sales/tax-rates`

Update tax rate

Updates an existing tax rate by identifier.

**Tags:** Sales

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Update acknowledgement

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/sales/tax-rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/scheduler/jobs`

Delete scheduledjob

Deletes a scheduled job by ID.

**Tags:** Scheduler

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "string"
}
```

### Responses

**200** – ScheduledJob deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/scheduler/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\"
}"
```

## GET `/scheduler/jobs`

List scheduledjobs

Returns a paginated collection of scheduledjobs scoped to the authenticated organization.

**Tags:** Scheduler

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| id | query | any | Optional |
| search | query | any | Optional |
| scopeType | query | any | Optional |
| isEnabled | query | any | Required |
| sourceType | query | any | Optional |
| sourceModule | query | any | Optional |
| sort | query | any | Optional |
| order | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |

### Responses

**200** – Paginated scheduledjobs

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "string",
      "description": null,
      "scopeType": "system",
      "organizationId": null,
      "tenantId": null,
      "scheduleType": "cron",
      "scheduleValue": "string",
      "timezone": "string",
      "targetType": "queue",
      "targetQueue": null,
      "targetCommand": null,
      "targetPayload": null,
      "requireFeature": null,
      "isEnabled": true,
      "lastRunAt": null,
      "nextRunAt": null,
      "sourceType": "user",
      "sourceModule": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/scheduler/jobs?page=1&pageSize=20" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/scheduler/jobs`

Create scheduledjob

Creates a new scheduled job with cron or interval-based scheduling.

**Tags:** Scheduler

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "description": null,
  "scopeType": "system",
  "organizationId": null,
  "tenantId": null,
  "scheduleType": "cron",
  "scheduleValue": "string",
  "timezone": "UTC",
  "targetType": "queue",
  "targetQueue": null,
  "targetCommand": null,
  "targetPayload": null,
  "requireFeature": null,
  "isEnabled": true
}
```

### Responses

**201** – ScheduledJob created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/scheduler/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"scopeType\": \"system\",
  \"organizationId\": null,
  \"tenantId\": null,
  \"scheduleType\": \"cron\",
  \"scheduleValue\": \"string\",
  \"timezone\": \"UTC\",
  \"targetType\": \"queue\",
  \"targetQueue\": null,
  \"targetCommand\": null,
  \"targetPayload\": null,
  \"requireFeature\": null,
  \"isEnabled\": true
}"
```

## PUT `/scheduler/jobs`

Update scheduledjob

Updates an existing scheduled job by ID.

**Tags:** Scheduler

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "string",
  "description": null,
  "targetQueue": null,
  "targetCommand": null,
  "targetPayload": null,
  "requireFeature": null
}
```

### Responses

**200** – ScheduledJob updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/scheduler/jobs" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\",
  \"description\": null,
  \"targetQueue\": null,
  \"targetCommand\": null,
  \"targetPayload\": null,
  \"requireFeature\": null
}"
```

## GET `/scheduler/jobs/{id}/executions`

Get execution history for a schedule

Fetch recent executions from BullMQ for a scheduled job. Requires QUEUE_STRATEGY=async.

**Tags:** Scheduler

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| pageSize | query | any | Optional |

### Responses

**200** – Execution history

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "scheduleId": "00000000-0000-4000-8000-000000000000",
      "startedAt": "string",
      "finishedAt": null,
      "status": "running",
      "triggerType": "scheduled",
      "triggeredByUserId": null,
      "errorMessage": null,
      "errorStack": null,
      "durationMs": null,
      "queueJobId": "string",
      "queueName": "string",
      "attemptsMade": 1,
      "result": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1
}
```

**400** – Local strategy not supported

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Schedule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/scheduler/jobs/:id/executions?pageSize=20" \
  -H "Accept: application/json"
```

## GET `/scheduler/queue-jobs/{jobId}`

Get BullMQ job details and logs

Fetch detailed information and logs for a queue job. Requires QUEUE_STRATEGY=async.

**Tags:** Scheduler

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| jobId | path | any | Required |
| queue | query | any | Required |

### Responses

**200** – Job details and logs

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "state": "waiting",
  "progress": null,
  "returnvalue": null,
  "failedReason": null,
  "stacktrace": null,
  "attemptsMade": 1,
  "processedOn": null,
  "finishedOn": null,
  "logs": [
    "string"
  ]
}
```

**400** – Invalid request or local strategy not supported

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Job not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/scheduler/queue-jobs/:jobId?queue=string" \
  -H "Accept: application/json"
```

## GET `/scheduler/targets`

List available queues and commands

Returns available queue names and scheduler-safe command IDs for schedule target selection.

**Tags:** Scheduler

### Responses

**200** – Available targets

Content-Type: `application/json`

```json
{
  "queues": [
    {
      "value": "string",
      "label": "string"
    }
  ],
  "commands": [
    {
      "value": "string",
      "label": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/scheduler/targets" \
  -H "Accept: application/json"
```

## POST `/scheduler/trigger`

Manually trigger a schedule

Executes a scheduled job immediately, bypassing the scheduled time. Only works with async queue strategy. The attempt is audited against the calling user whether it succeeds, is refused, or fails, except when a before command interceptor blocks it before the command runs.

**Tags:** Scheduler

### Request Body

Content-Type: `application/json`

```json
{
  "id": "string"
}
```

### Responses

**200** – Schedule triggered successfully

Content-Type: `application/json`

```json
{
  "ok": true,
  "jobId": "string",
  "message": "string"
}
```

**400** – Invalid request or local strategy not supported

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Access denied

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Schedule not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Trigger deliberately blocked by a before command interceptor. The interceptor chooses the status (any 4xx/5xx) and may replace the body.

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/scheduler/trigger" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"string\"
}"
```

## GET `/search/embeddings`

Get embeddings configuration

Returns current embedding provider and model configuration.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Embeddings settings

Content-Type: `application/json`

```json
{
  "settings": {
    "openaiConfigured": true,
    "autoIndexingEnabled": true,
    "autoIndexingLocked": true,
    "lockReason": null,
    "embeddingConfig": null,
    "configuredProviders": [
      "openai"
    ],
    "indexedDimension": null,
    "reindexRequired": true,
    "documentCount": null
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/embeddings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/search/embeddings`

Update embeddings configuration

Updates the embedding provider and model settings.

**Tags:** Search

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Updated settings

Content-Type: `application/json`

```json
{
  "settings": {
    "openaiConfigured": true,
    "autoIndexingEnabled": true,
    "autoIndexingLocked": true,
    "lockReason": null,
    "embeddingConfig": null,
    "configuredProviders": [
      "openai"
    ],
    "indexedDimension": null,
    "reindexRequired": true,
    "documentCount": null
  }
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Auto-indexing disabled via environment

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Update failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Configuration service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/search/embeddings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/search/embeddings/reindex`

Trigger vector reindex

Starts a vector embedding reindex operation.

**Tags:** Search

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Reindex result

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Reindex already in progress

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": {
    "type": "fulltext",
    "action": "string",
    "startedAt": "string",
    "elapsedMinutes": 1,
    "processedCount": null,
    "totalCount": null
  }
}
```

**500** – Reindex failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Search indexer unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/search/embeddings/reindex" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/search/embeddings/reindex/cancel`

Cancel vector reindex

Cancels an in-progress vector reindex operation.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Cancel result

Content-Type: `application/json`

```json
{
  "ok": true,
  "jobsRemoved": 1
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/search/embeddings/reindex/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/search/index`

Purge vector index

Purges entries from the vector search index. Requires confirmAll=true when purging all entities.

**Tags:** Search

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Optional. Specific entity ID to purge (e.g., "customers:customer_person_profile", "catalog:catalog_product") |
| confirmAll | query | any | Optional. Required when purging all entities |

### Responses

**200** – Purge result

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Missing confirmAll parameter

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Purge failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Search indexer unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/search/index" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/search/index`

List vector index entries

Returns paginated list of entries in the vector search index.

**Tags:** Search

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityId | query | any | Optional. Filter by entity ID (e.g., "customers:customer_person_profile", "catalog:catalog_product") |
| limit | query | any | Optional. Maximum entries to return (default: 50, max: 200) |
| offset | query | any | Optional. Offset for pagination (default: 0) |

### Responses

**200** – Index entries

Content-Type: `application/json`

```json
{
  "entries": [
    {
      "id": "string",
      "entityId": "string",
      "recordId": "string",
      "tenantId": "string",
      "organizationId": null
    }
  ],
  "limit": 1,
  "offset": 1
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Failed to fetch index

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Vector strategy unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/index" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/search/reindex`

Trigger fulltext reindex

Starts a fulltext (Meilisearch) reindex operation. Can clear, recreate, or fully reindex.

**Tags:** Search

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Reindex result

Content-Type: `application/json`

```json
{
  "ok": true,
  "action": "clear",
  "entityId": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Reindex already in progress

Content-Type: `application/json`

```json
{
  "error": "string",
  "lock": {
    "type": "fulltext",
    "action": "string",
    "startedAt": "string",
    "elapsedMinutes": 1,
    "processedCount": null,
    "totalCount": null
  }
}
```

**500** – Reindex failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Search service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/search/reindex" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/search/reindex/cancel`

Cancel fulltext reindex

Cancels an in-progress fulltext reindex operation.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Cancel result

Content-Type: `application/json`

```json
{
  "ok": true,
  "jobsRemoved": 1
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/search/reindex/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/search/search`

Search across all indexed entities

Performs a search using configured strategies (fulltext, vector, tokens). Use for search playground. Results are limited to the entity types the caller holds the declared view features for; superadmins are exempt.

**Tags:** Search

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| q | query | any | Required. Search query (required) |
| limit | query | any | Optional. Maximum results to return (default: 50, max: 100) |
| strategies | query | any | Optional. Comma-separated strategies to use: fulltext, vector, tokens (e.g., "fulltext,vector") |
| entityTypes | query | any | Optional. Comma-separated entity types to filter results (e.g., "customers:customer_person_profile,catalog:catalog_product,sales:sales_order") |

### Responses

**200** – Search results

Content-Type: `application/json`

```json
{
  "results": [
    {
      "entityId": "string",
      "recordId": "string",
      "score": 1,
      "source": "fulltext"
    }
  ],
  "strategiesUsed": [
    "fulltext"
  ],
  "timing": 1,
  "query": "string",
  "limit": 1
}
```

**400** – Missing query parameter

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Search failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Search service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/search?q=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/search/search/global`

Global search (Cmd+K)

Performs a global search using saved tenant strategies. Does NOT accept strategies from URL.

**Tags:** Search

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| q | query | any | Required. Search query (required) |
| limit | query | any | Optional. Maximum results to return (default: 50, max: 100) |
| entityTypes | query | any | Optional. Comma-separated entity types to filter results (e.g., "customers:customer_person_profile,catalog:catalog_product,sales:sales_order") |

### Responses

**200** – Search results

Content-Type: `application/json`

```json
{
  "results": [
    {
      "entityId": "string",
      "recordId": "string",
      "score": 1,
      "source": "fulltext"
    }
  ],
  "strategiesUsed": [
    "fulltext"
  ],
  "strategiesEnabled": [
    "fulltext"
  ],
  "timing": 1,
  "query": "string",
  "limit": 1
}
```

**400** – Missing query parameter

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Search failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Search service unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/search/global?q=string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/search/settings`

Get search settings and status

Returns search module configuration, available strategies, and reindex lock status.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Search settings

Content-Type: `application/json`

```json
{
  "settings": {
    "strategies": [
      {
        "id": "string",
        "name": "string",
        "priority": 1,
        "available": true
      }
    ],
    "fulltextConfigured": true,
    "fulltextStats": null,
    "vectorConfigured": true,
    "tokensEnabled": true,
    "defaultStrategies": [
      "string"
    ],
    "reindexLock": null,
    "fulltextReindexLock": null,
    "vectorReindexLock": null
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/search/settings/fulltext`

Get fulltext search configuration

Returns Meilisearch configuration status and index statistics.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Fulltext settings

Content-Type: `application/json`

```json
{
  "driver": null,
  "configured": true,
  "envVars": {
    "MEILISEARCH_HOST": {
      "set": true,
      "hint": "string"
    },
    "MEILISEARCH_API_KEY": {
      "set": true,
      "hint": "string"
    }
  },
  "optionalEnvVars": {
    "MEILISEARCH_INDEX_PREFIX": {
      "set": true,
      "hint": "string"
    },
    "SEARCH_EXCLUDE_ENCRYPTED_FIELDS": {
      "set": true,
      "hint": "string"
    }
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/settings/fulltext" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/search/settings/global-search`

Get global search strategies

Returns the enabled strategies for Cmd+K global search.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Global search settings

Content-Type: `application/json`

```json
{
  "enabledStrategies": [
    "fulltext"
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/settings/global-search" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/search/settings/global-search`

Update global search strategies

Sets which strategies are enabled for Cmd+K global search.

**Tags:** Search

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "enabledStrategies": [
    "fulltext"
  ]
}
```

### Responses

**200** – Updated settings

Content-Type: `application/json`

```json
{
  "ok": true,
  "enabledStrategies": [
    "fulltext"
  ]
}
```

**400** – Invalid request

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/search/settings/global-search" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"enabledStrategies\": [
    \"fulltext\"
  ]
}"
```

## GET `/search/settings/vector-store`

Get vector store configuration

Returns vector store configuration status.

**Tags:** Search

**Requires authentication.**

### Responses

**200** – Vector store settings

Content-Type: `application/json`

```json
{
  "currentDriver": "pgvector",
  "configured": true,
  "drivers": [
    {
      "id": "pgvector",
      "name": "string",
      "configured": true,
      "implemented": true,
      "available": null,
      "unavailableReason": null,
      "envVars": [
        {
          "name": "string",
          "set": true,
          "hint": "string"
        }
      ]
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/search/settings/vector-store" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/shipping-carriers/cancel`

Cancel shipment

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**200** – Shipment cancelled

Content-Type: `application/json`

**422** – Validation failed or shipment cannot be cancelled in its current status

Content-Type: `application/json`

**502** – Provider upstream error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/shipping-carriers/cancel" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/shipping-carriers/points`

Search carrier drop-off points (lockers, POP points)

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**200** – Points returned

Content-Type: `application/json`

**422** – Validation failed

Content-Type: `application/json`

**502** – Provider upstream error or unsupported

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/shipping-carriers/points" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/shipping-carriers/providers`

List registered shipping providers

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**200** – List of registered provider keys

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/shipping-carriers/providers" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/shipping-carriers/rates`

Calculate shipping rates

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**200** – Rates calculated

Content-Type: `application/json`

**422** – Validation failed

Content-Type: `application/json`

**502** – Provider upstream error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/shipping-carriers/rates" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/shipping-carriers/shipments`

Create shipment

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**201** – Shipment created

Content-Type: `application/json`

**409** – Idempotency conflict: the idempotency key was reused with a different payload

Content-Type: `application/json`

**422** – Validation failed

Content-Type: `application/json`

**502** – Provider upstream error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/shipping-carriers/shipments" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/shipping-carriers/tracking`

Get tracking

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**200** – Tracking returned

Content-Type: `application/json`

**404** – Shipment not found

Content-Type: `application/json`

**422** – Validation failed

Content-Type: `application/json`

**502** – Provider upstream error

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/shipping-carriers/tracking" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/shipping-carriers/tracking/refresh`

Refresh tracking and persist the latest shipment status

**Tags:** ShippingCarriers

**Requires authentication.**

### Responses

**200** – Tracking refreshed and shipment status persisted

Content-Type: `application/json`

**422** – Validation failed

Content-Type: `application/json`

**502** – Provider upstream error

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/shipping-carriers/tracking/refresh" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/shipping-carriers/webhook/{provider}`

Process inbound carrier webhook

**Tags:** ShippingCarriers

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| provider | path | any | Required |

### Responses

**202** – Webhook accepted for async processing

Content-Type: `application/json`

**401** – Signature verification failed

Content-Type: `application/json`

**404** – Unknown provider

Content-Type: `application/json`

**413** – Webhook payload too large

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/shipping-carriers/webhook/:provider" \
  -H "Accept: application/json"
```

## GET `/sync_akeneo/custom-fields`

Inspect and create Akeneo-backed custom fields

**Tags:** Akeneo Product Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sync_akeneo/custom-fields" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sync_akeneo/custom-fields`

Inspect and create Akeneo-backed custom fields

**Tags:** Akeneo Product Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sync_akeneo/custom-fields" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sync_akeneo/delete-products`

Start deleting all Akeneo-imported products for the current organization

**Tags:** Akeneo Product Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sync_akeneo/delete-products" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/sync_akeneo/discovery`

Load Akeneo discovery metadata for field mapping

**Tags:** Akeneo Product Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sync_akeneo/discovery" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/sync_akeneo/first-import`

GET /sync_akeneo/first-import

**Tags:** Akeneo Product Sync

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sync_akeneo/first-import" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sync_akeneo/first-import`

POST /sync_akeneo/first-import

**Tags:** Akeneo Product Sync

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sync_akeneo/first-import" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sync_excel/import`

Start CSV import

**Tags:** Excel / CSV Import

**Requires authentication.**

### Responses

**201** – Import run started

Content-Type: `application/json`

```json
{
  "runId": "00000000-0000-4000-8000-000000000000",
  "progressJobId": null,
  "status": "pending"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Upload not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Import overlap detected

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid import payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sync_excel/import" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/sync_excel/preview`

Fetch upload preview

**Tags:** Excel / CSV Import

**Requires authentication.**

### Responses

**200** – Stored upload preview

Content-Type: `application/json`

```json
{
  "uploadId": "00000000-0000-4000-8000-000000000000",
  "filename": "string",
  "mimeType": "string",
  "fileSize": 1,
  "entityType": "customers.person",
  "headers": [
    "string"
  ],
  "sampleRows": [
    {
      "key": null
    }
  ],
  "totalRows": 1,
  "suggestedMapping": {
    "entityType": "customers.person",
    "matchStrategy": "externalId",
    "fields": [
      {
        "externalField": "string",
        "localField": "string"
      }
    ],
    "unmappedColumns": [
      "string"
    ]
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Upload preview not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid query

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/sync_excel/preview" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/sync_excel/upload`

Upload CSV file

**Tags:** Excel / CSV Import

**Requires authentication.**

### Request Body

Content-Type: `multipart/form-data`

No example available for this content type.

### Responses

**200** – CSV uploaded and preview parsed

Content-Type: `application/json`

```json
{
  "uploadId": "00000000-0000-4000-8000-000000000000",
  "filename": "string",
  "mimeType": "string",
  "fileSize": 1,
  "entityType": "customers.person",
  "headers": [
    "string"
  ],
  "sampleRows": [
    {
      "key": null
    }
  ],
  "totalRows": 1,
  "suggestedMapping": {
    "entityType": "customers.person",
    "matchStrategy": "externalId",
    "fields": [
      {
        "externalField": "string",
        "localField": "string"
      }
    ],
    "unmappedColumns": [
      "string"
    ]
  }
}
```

**400** – Invalid multipart payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – CSV upload exceeds the maximum upload size

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Unsupported entity type or file type

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/sync_excel/upload" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/tillio/operators`

List and attach Tillio operators

**Tags:** Tillio Telephony

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/tillio/operators" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/tillio/operators`

List and attach Tillio operators

**Tags:** Tillio Telephony

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/tillio/operators" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/tillio/operators/{id}`

Detach a Tillio operator

**Tags:** Tillio Telephony

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**204** – Success

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/tillio/operators/:id" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/tillio/pull`

GET /tillio/pull

**Tags:** Tillio Telephony

**Requires authentication.**

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/tillio/pull" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/tillio/pull`

POST /tillio/pull

**Tags:** Tillio Telephony

**Requires authentication.**

### Responses

**201** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/tillio/pull" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/translations/{entityType}/{entityId}`

Delete entity translations

Removes all translations for an entity.

**Tags:** Translations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityType | path | any | Required |
| entityId | path | any | Required |

### Responses

**204** – Translations deleted.

**401** – Authentication required

Content-Type: `application/json`

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/translations/string/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/translations/{entityType}/{entityId}`

Get entity translations

Returns the full translation record for a single entity.

**Tags:** Translations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityType | path | any | Required |
| entityId | path | any | Required |

### Responses

**200** – Translation record found.

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

**404** – No translations found for this entity

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/translations/string/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/translations/{entityType}/{entityId}`

Create or update entity translations

Full replacement of translations JSONB for an entity.

**Tags:** Translations

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| entityType | path | any | Required |
| entityId | path | any | Required |

### Responses

**200** – Translations saved.

Content-Type: `application/json`

**400** – Validation failed

Content-Type: `application/json`

**401** – Authentication required

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/translations/string/string" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/translations/locales`

List supported translation locales

**Tags:** Entity Translations

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/translations/locales" \
  -H "Accept: application/json"
```

## PUT `/translations/locales`

Update supported translation locales

**Tags:** Entity Translations

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/translations/locales" \
  -H "Accept: application/json"
```

## GET `/version`

Deployed Open Mercato version

**Tags:** API Documentation

### Responses

**200** – Success response

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/version" \
  -H "Accept: application/json"
```

## GET `/webhooks`

List webhooks

Returns paginated webhooks for the current tenant and organization.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |

### Responses

**200** – Webhook collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "description": null,
      "url": "string",
      "subscribedEvents": [
        "string"
      ],
      "httpMethod": "string",
      "isActive": true,
      "deliveryStrategy": "string",
      "maxRetries": 1,
      "consecutiveFailures": 1,
      "lastSuccessAt": null,
      "lastFailureAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Tenant context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/webhooks`

Create webhook

Creates a new webhook endpoint. A signing secret (whsec_ prefixed) is auto-generated and returned once.

**Tags:** Webhooks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "description": null,
  "url": "https://example.com/resource",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}
```

### Responses

**201** – Webhook created

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "url": "string",
  "secret": "string",
  "subscribedEvents": [
    "string"
  ],
  "isActive": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"url\": \"https://example.com/resource\",
  \"subscribedEvents\": [
    \"string\"
  ],
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
```

## DELETE `/webhooks/{id}`

Delete webhook

Soft-deletes a webhook endpoint.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Webhook deleted

Content-Type: `application/json`

```json
{
  "success": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## GET `/webhooks/{id}`

Get webhook

Returns webhook configuration, masked secret metadata, and delivery settings.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Webhook detail

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## PUT `/webhooks/{id}`

Update webhook

Updates a single webhook configuration.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "description": null,
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}
```

### Responses

**200** – Webhook updated

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
```

## POST `/webhooks/{id}/rotate-secret`

Rotate secret

Returns the new secret once. Store it immediately; future reads only expose a masked value.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Secret rotated

Content-Type: `application/json`

```json
{
  "success": true,
  "secret": "string",
  "previousSecretSetAt": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/00000000-0000-4000-8000-000000000000/rotate-secret" \
  -H "Accept: application/json"
```

## POST `/webhooks/{id}/test`

Test webhook

Creates a synthetic event payload and delivers it immediately without using the queue.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Test delivery result

Content-Type: `application/json`

```json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
```

**400** – Invalid request payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Webhook integration disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/00000000-0000-4000-8000-000000000000/test" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/webhooks/deliveries`

List delivery logs

Returns paginated webhook delivery attempts with filtering by webhook, event type, and status.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| webhookId | query | any | Optional |
| eventType | query | any | Optional |
| status | query | any | Optional |

### Responses

**200** – Delivery log collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "webhookId": "string",
      "webhookName": null,
      "eventType": "string",
      "messageId": "string",
      "status": "string",
      "responseStatus": null,
      "errorMessage": null,
      "attemptNumber": 1,
      "maxAttempts": 1,
      "targetUrl": "string",
      "durationMs": null,
      "enqueuedAt": "string",
      "lastAttemptAt": null,
      "deliveredAt": null,
      "createdAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Tenant context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/deliveries?page=1&pageSize=50" \
  -H "Accept: application/json"
```

## GET `/webhooks/deliveries/{id}`

Get delivery

Returns a single delivery attempt by ID.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Delivery detail

Content-Type: `application/json`

```json
{
  "id": "string",
  "webhookId": "string",
  "eventType": "string",
  "messageId": "string",
  "status": "string",
  "responseStatus": null,
  "errorMessage": null,
  "attemptNumber": 1,
  "maxAttempts": 1,
  "targetUrl": "string",
  "durationMs": null,
  "enqueuedAt": "string",
  "lastAttemptAt": null,
  "deliveredAt": null,
  "createdAt": "string",
  "payload": {},
  "responseBody": null,
  "responseHeaders": null,
  "nextRetryAt": null,
  "updatedAt": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Delivery not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/deliveries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## POST `/webhooks/deliveries/{id}/retry`

Retry delivery

Resets retry scheduling fields and enqueues the delivery again.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Delivery re-enqueued

Content-Type: `application/json`

```json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Delivery not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Webhook integration disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/deliveries/00000000-0000-4000-8000-000000000000/retry" \
  -H "Accept: application/json"
```

## GET `/webhooks/events`

List webhook events

Returns all declared non-webhook events, sorted by event id.

**Tags:** Webhooks

**Requires authentication.**

### Responses

**200** – Available events

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "string",
      "label": "string"
    }
  ],
  "total": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/events" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/webhooks/inbound/{endpointId}`

Receive inbound webhook

The endpoint id resolves to a registered webhook source first (module-level handler dispatch), otherwise to a legacy adapter provider key.

**Tags:** Webhooks

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| endpointId | path | any | Required |

### Responses

**200** – Inbound webhook accepted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Verification failed or stale webhook timestamp

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Signature verification failed (source flow)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Endpoint not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**413** – Webhook payload too large

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**429** – Rate limit exceeded

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Webhook integration disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/inbound/string" \
  -H "Accept: application/json"
```

## GET `/webhooks/webhook-deliveries`

List delivery logs

Returns paginated webhook delivery attempts with filtering by webhook, event type, and status.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| webhookId | query | any | Optional |
| eventType | query | any | Optional |
| status | query | any | Optional |

### Responses

**200** – Delivery log collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "webhookId": "string",
      "webhookName": null,
      "eventType": "string",
      "messageId": "string",
      "status": "string",
      "responseStatus": null,
      "errorMessage": null,
      "attemptNumber": 1,
      "maxAttempts": 1,
      "targetUrl": "string",
      "durationMs": null,
      "enqueuedAt": "string",
      "lastAttemptAt": null,
      "deliveredAt": null,
      "createdAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Tenant context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/webhook-deliveries?page=1&pageSize=50" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/webhooks/webhook-deliveries/{id}`

Get delivery

Returns a single delivery attempt by ID.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Delivery detail

Content-Type: `application/json`

```json
{
  "id": "string",
  "webhookId": "string",
  "eventType": "string",
  "messageId": "string",
  "status": "string",
  "responseStatus": null,
  "errorMessage": null,
  "attemptNumber": 1,
  "maxAttempts": 1,
  "targetUrl": "string",
  "durationMs": null,
  "enqueuedAt": "string",
  "lastAttemptAt": null,
  "deliveredAt": null,
  "createdAt": "string",
  "payload": {},
  "responseBody": null,
  "responseHeaders": null,
  "nextRetryAt": null,
  "updatedAt": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Delivery not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/webhook-deliveries/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/webhooks/webhook-deliveries/{id}/retry`

Retry delivery

Resets retry scheduling fields and enqueues the delivery again.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Delivery re-enqueued

Content-Type: `application/json`

```json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Delivery not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Webhook integration disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/webhook-deliveries/00000000-0000-4000-8000-000000000000/retry" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/webhooks/webhooks`

Delete webhook

Soft-deletes a webhook endpoint.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | query | any | Required. Webhook ID to delete |

### Responses

**200** – Deleted

Content-Type: `application/json`

```json
{
  "success": true
}
```

**403** – Forbidden

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/webhooks/webhooks?id=00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/webhooks/webhooks`

List webhooks

Returns paginated webhooks for the current tenant and organization.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| isActive | query | any | Optional |

### Responses

**200** – Webhook collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "description": null,
      "url": "string",
      "subscribedEvents": [
        "string"
      ],
      "httpMethod": "string",
      "isActive": true,
      "deliveryStrategy": "string",
      "maxRetries": 1,
      "consecutiveFailures": 1,
      "lastSuccessAt": null,
      "lastFailureAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**400** – Tenant context missing

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/webhooks/webhooks`

Create webhook

Creates a new webhook endpoint. A signing secret (whsec_ prefixed) is auto-generated and returned once.

**Tags:** Webhooks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "name": "string",
  "description": null,
  "url": "https://example.com/resource",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}
```

### Responses

**201** – Webhook created

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "url": "string",
  "secret": "string",
  "subscribedEvents": [
    "string"
  ],
  "isActive": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"name\": \"string\",
  \"description\": null,
  \"url\": \"https://example.com/resource\",
  \"subscribedEvents\": [
    \"string\"
  ],
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
```

## PUT `/webhooks/webhooks`

Update webhook

Updates an existing webhook configuration.

**Tags:** Webhooks

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "description": null,
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}
```

### Responses

**200** – Webhook updated

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/webhooks/webhooks" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
```

## DELETE `/webhooks/webhooks/{id}`

Delete webhook

Soft-deletes a webhook endpoint.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Webhook deleted

Content-Type: `application/json`

```json
{
  "success": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/webhooks/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/webhooks/webhooks/{id}`

Get webhook

Returns webhook configuration, masked secret metadata, and delivery settings.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Webhook detail

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/webhooks/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/webhooks/webhooks/{id}`

Update webhook

Updates a single webhook configuration.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "description": null,
  "httpMethod": "POST",
  "customHeaders": null,
  "deliveryStrategy": "http",
  "strategyConfig": null,
  "maxRetries": 10,
  "timeoutMs": 15000,
  "rateLimitPerMinute": 0,
  "autoDisableThreshold": 100,
  "integrationId": null
}
```

### Responses

**200** – Webhook updated

Content-Type: `application/json`

```json
{
  "id": "string",
  "name": "string",
  "description": null,
  "url": "string",
  "subscribedEvents": [
    "string"
  ],
  "httpMethod": "string",
  "isActive": true,
  "deliveryStrategy": "string",
  "maxRetries": 1,
  "consecutiveFailures": 1,
  "lastSuccessAt": null,
  "lastFailureAt": null,
  "createdAt": "string",
  "updatedAt": "string",
  "customHeaders": null,
  "strategyConfig": null,
  "timeoutMs": 1,
  "rateLimitPerMinute": 1,
  "autoDisableThreshold": 1,
  "integrationId": null,
  "maskedSecret": "string",
  "previousSecretSetAt": null
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/webhooks/webhooks/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"httpMethod\": \"POST\",
  \"customHeaders\": null,
  \"deliveryStrategy\": \"http\",
  \"strategyConfig\": null,
  \"maxRetries\": 10,
  \"timeoutMs\": 15000,
  \"rateLimitPerMinute\": 0,
  \"autoDisableThreshold\": 100,
  \"integrationId\": null
}"
```

## POST `/webhooks/webhooks/{id}/rotate-secret`

Rotate secret

Returns the new secret once. Store it immediately; future reads only expose a masked value.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Secret rotated

Content-Type: `application/json`

```json
{
  "success": true,
  "secret": "string",
  "previousSecretSetAt": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/webhooks/00000000-0000-4000-8000-000000000000/rotate-secret" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/webhooks/webhooks/{id}/test`

Test webhook

Creates a synthetic event payload and delivers it immediately without using the queue.

**Tags:** Webhooks

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Test delivery result

Content-Type: `application/json`

```json
{
  "success": true,
  "delivery": {
    "id": "string",
    "webhookId": "string",
    "eventType": "string",
    "messageId": "string",
    "status": "string",
    "responseStatus": null,
    "errorMessage": null,
    "attemptNumber": 1,
    "maxAttempts": 1,
    "targetUrl": "string",
    "durationMs": null,
    "enqueuedAt": "string",
    "lastAttemptAt": null,
    "deliveredAt": null,
    "createdAt": "string",
    "payload": {},
    "responseBody": null,
    "responseHeaders": null,
    "nextRetryAt": null,
    "updatedAt": "string"
  }
}
```

**400** – Invalid request payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Webhook not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Webhook integration disabled

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/webhooks/webhooks/00000000-0000-4000-8000-000000000000/test" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## GET `/wms/dashboard/operational`

Load operational dashboard data

Aggregated KPIs, expiry watch lot rows (`expiryLots`), monthly movement trends, and recent activity for the WMS operational dashboard.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| warehouseId | query | any | Optional |

### Responses

**200** – Dashboard payload

Content-Type: `application/json`

```json
{
  "lastUpdatedAt": "string",
  "warehouseId": null,
  "kpis": [
    {
      "id": "lowStock",
      "count": 1,
      "deltaSinceYesterday": null,
      "sparkline": [
        1
      ]
    }
  ],
  "expiryLots": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "lotNumber": "string",
      "sku": "string",
      "expiresAt": "string",
      "availableQuantity": 1,
      "category": "expiringSoon"
    }
  ],
  "monthlyTrends": [
    {
      "month": "string",
      "receive": 1,
      "allocate": 1
    }
  ],
  "recentActivity": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "movementType": "string",
      "quantity": 1,
      "variantSku": null,
      "variantId": "00000000-0000-4000-8000-000000000000",
      "referenceType": null,
      "referenceId": null,
      "reason": null,
      "locationLabel": "string",
      "performedAt": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

**404** – Warehouse not found

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/dashboard/operational" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/wms/inventory-profiles`

Delete inventory profile

Soft-deletes an inventory profile by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory profile deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/wms/inventory-profiles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/inventory-profiles`

List inventory profiles

Returns a paginated collection of inventory profiles scoped to the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| catalogProductId | query | any | Optional |
| catalogVariantId | query | any | Optional |
| defaultStrategy | query | any | Optional |
| trackLot | query | any | Optional |
| trackSerial | query | any | Optional |
| trackExpiration | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated inventory profiles

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "catalog_product_id": null,
      "catalog_variant_id": null,
      "product_title": null,
      "product_sku": null,
      "variant_name": null,
      "variant_sku": null,
      "default_uom": null,
      "track_lot": null,
      "track_serial": null,
      "track_expiration": null,
      "default_strategy": null,
      "reorder_point": null,
      "safety_stock": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/inventory-profiles?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/inventory-profiles`

Create inventory profile

Creates a product inventory profile.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "catalogProductId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": null,
  "defaultUom": "string",
  "defaultStrategy": "fifo"
}
```

### Responses

**201** – Inventory profile created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory-profiles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogProductId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": null,
  \"defaultUom\": \"string\",
  \"defaultStrategy\": \"fifo\"
}"
```

## PUT `/wms/inventory-profiles`

Update inventory profile

Updates an inventory profile by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": null
}
```

### Responses

**200** – Inventory profile updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/wms/inventory-profiles" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": null
}"
```

## POST `/wms/inventory/adjust`

Adjust inventory

Applies a manual inventory adjustment and appends a movement ledger row.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "locationId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": "00000000-0000-4000-8000-000000000000",
  "delta": 1,
  "reason": "string",
  "referenceType": "manual",
  "referenceId": "00000000-0000-4000-8000-000000000000",
  "performedBy": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory adjusted

Content-Type: `application/json`

```json
{
  "ok": true,
  "movementId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Insufficient stock

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid location

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/adjust" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"locationId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
  \"delta\": 1,
  \"reason\": \"string\",
  \"referenceType\": \"manual\",
  \"referenceId\": \"00000000-0000-4000-8000-000000000000\",
  \"performedBy\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/wms/inventory/allocate`

Allocate reservation

Converts a reservation from reserved quantity into allocated quantity on the selected stock buckets.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "reservationId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Reservation allocated

Content-Type: `application/json`

```json
{
  "ok": true,
  "allocationState": "allocated"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Reservation not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Invalid reservation state

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/allocate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"reservationId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/inventory/balances`

List inventory balances

Returns paginated inventory balance buckets for the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| warehouseId | query | any | Optional |
| locationId | query | any | Optional |
| catalogVariantId | query | any | Optional |
| lotId | query | any | Optional |
| serialNumber | query | any | Optional |
| lowStock | query | any | Optional |
| search | query | any | Optional |

### Responses

**200** – Inventory balances collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "warehouse_id": null,
      "warehouse_name": null,
      "warehouse_code": null,
      "location_id": null,
      "location_code": null,
      "location_type": null,
      "catalog_variant_id": null,
      "catalog_product_id": null,
      "variant_name": null,
      "variant_sku": null,
      "lot_id": null,
      "serial_number": null,
      "quantity_on_hand": null,
      "quantity_reserved": null,
      "quantity_allocated": null,
      "quantity_available": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/inventory/balances?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/inventory/cycle-count`

Cycle count reconcile

Reconciles a counted quantity against the current on-hand balance and appends a cycle-count movement when a delta exists.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "locationId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": "00000000-0000-4000-8000-000000000000",
  "countedQuantity": 1,
  "autoAdjust": true,
  "reason": "string",
  "referenceId": "00000000-0000-4000-8000-000000000000",
  "performedBy": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Cycle count reconciled

Content-Type: `application/json`

```json
{
  "ok": true,
  "adjustmentDelta": "string",
  "movementId": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid location

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/cycle-count" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"locationId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
  \"countedQuantity\": 1,
  \"autoAdjust\": true,
  \"reason\": \"string\",
  \"referenceId\": \"00000000-0000-4000-8000-000000000000\",
  \"performedBy\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/wms/inventory/import/apply`

Apply inventory CSV import

Applies validated inventory import rows via wms.inventory.adjust commands (idempotent skip when delta is zero).

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "importBatchId": "00000000-0000-4000-8000-000000000000",
  "reason": "CSV import inventory receipt",
  "mode": "additive",
  "rows": [
    {
      "rowNumber": 1,
      "warehouseId": "00000000-0000-4000-8000-000000000000",
      "locationId": "00000000-0000-4000-8000-000000000000",
      "catalogVariantId": "00000000-0000-4000-8000-000000000000",
      "quantity": 1,
      "delta": 1
    }
  ]
}
```

### Responses

**200** – Import applied

Content-Type: `application/json`

```json
{
  "ok": true,
  "importBatchId": "00000000-0000-4000-8000-000000000000",
  "summary": {
    "applied": 1,
    "skipped": 1,
    "failed": 1
  }
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Partial apply failure

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/import/apply" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"importBatchId\": \"00000000-0000-4000-8000-000000000000\",
  \"reason\": \"CSV import inventory receipt\",
  \"mode\": \"additive\",
  \"rows\": [
    {
      \"rowNumber\": 1,
      \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
      \"locationId\": \"00000000-0000-4000-8000-000000000000\",
      \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
      \"quantity\": 1,
      \"delta\": 1
    }
  ]
}"
```

## GET `/wms/inventory/import/template`

Download inventory import CSV template

Returns a CSV template for WMS inventory imports. By default the quantity column is added to existing on-hand stock; the "Reconcile to exact balance" import option treats it as the absolute target balance instead.

**Tags:** WMS

**Requires authentication.**

### Responses

**200** – CSV template file

Content-Type: `application/json`

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/inventory/import/template" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/inventory/import/validate`

Validate inventory CSV import

Dry-run validation for inventory import CSV rows. By default (mode "additive"), quantity is added to existing on-hand stock; opt into mode "reconcile" to instead treat quantity as the absolute target balance (overwrites existing stock, including reducing it). Accepts JSON rows, JSON csv text, or multipart file upload.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "mode": "additive",
  "rows": [
    {}
  ]
}
```

### Responses

**200** – Validation report

Content-Type: `application/json`

```json
{
  "ok": true,
  "importBatchId": "00000000-0000-4000-8000-000000000000",
  "summary": {
    "totalRows": 1,
    "validRows": 1,
    "errorRows": 1,
    "warningRows": 1,
    "skipRows": 1
  },
  "rows": [
    {
      "rowNumber": 1,
      "status": "valid",
      "errors": [
        "string"
      ],
      "warnings": [
        "string"
      ]
    }
  ]
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/import/validate" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"mode\": \"additive\",
  \"rows\": [
    {}
  ]
}"
```

## POST `/wms/inventory/move`

Move inventory

Moves stock from one location to another within a warehouse and appends a transfer movement.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "fromLocationId": "00000000-0000-4000-8000-000000000000",
  "toLocationId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": "00000000-0000-4000-8000-000000000000",
  "quantity": 1,
  "reason": "string",
  "referenceType": "manual",
  "referenceId": "00000000-0000-4000-8000-000000000000",
  "performedBy": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory moved

Content-Type: `application/json`

```json
{
  "ok": true,
  "movementId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Insufficient stock

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid location

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/move" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"fromLocationId\": \"00000000-0000-4000-8000-000000000000\",
  \"toLocationId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quantity\": 1,
  \"reason\": \"string\",
  \"referenceType\": \"manual\",
  \"referenceId\": \"00000000-0000-4000-8000-000000000000\",
  \"performedBy\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/inventory/movements`

List inventory movements

Returns paginated inventory ledger entries for the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| warehouseId | query | any | Optional |
| locationId | query | any | Optional |
| catalogVariantId | query | any | Optional |
| lotId | query | any | Optional |
| referenceType | query | any | Optional |
| referenceId | query | any | Optional |
| type | query | any | Optional |
| search | query | any | Optional |

### Responses

**200** – Inventory movements collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "warehouse_id": null,
      "warehouse_name": null,
      "warehouse_code": null,
      "location_from_id": null,
      "location_from_code": null,
      "location_from_type": null,
      "location_to_id": null,
      "location_to_code": null,
      "location_to_type": null,
      "catalog_variant_id": null,
      "catalog_product_id": null,
      "variant_name": null,
      "variant_sku": null,
      "lot_id": null,
      "serial_number": null,
      "quantity": null,
      "type": null,
      "reference_type": null,
      "reference_id": null,
      "performed_by": null,
      "performed_at": null,
      "received_at": null,
      "reason": null,
      "reason_code": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/inventory/movements?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/inventory/receive`

Receive inventory

Records inbound inventory receipt and appends a receipt movement ledger row.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "locationId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": "00000000-0000-4000-8000-000000000000",
  "quantity": 1,
  "referenceType": "po",
  "referenceId": "00000000-0000-4000-8000-000000000000",
  "performedBy": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory received

Content-Type: `application/json`

```json
{
  "ok": true,
  "movementId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid location

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/receive" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"locationId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quantity\": 1,
  \"referenceType\": \"po\",
  \"referenceId\": \"00000000-0000-4000-8000-000000000000\",
  \"performedBy\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/wms/inventory/release`

Release reservation

Releases a previously reserved or allocated inventory reservation.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "reservationId": "00000000-0000-4000-8000-000000000000",
  "reason": "string"
}
```

### Responses

**200** – Reservation released

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Reservation not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/release" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"reservationId\": \"00000000-0000-4000-8000-000000000000\",
  \"reason\": \"string\"
}"
```

## GET `/wms/inventory/reservations`

List inventory reservations

Returns paginated inventory reservations for the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| warehouseId | query | any | Optional |
| catalogVariantId | query | any | Optional |
| lotId | query | any | Optional |
| sourceType | query | any | Optional |
| sourceId | query | any | Optional |
| status | query | any | Optional |
| search | query | any | Optional |

### Responses

**200** – Inventory reservations collection

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "warehouse_id": null,
      "warehouse_name": null,
      "warehouse_code": null,
      "catalog_variant_id": null,
      "catalog_product_id": null,
      "variant_name": null,
      "variant_sku": null,
      "lot_id": null,
      "serial_number": null,
      "quantity": null,
      "source_type": null,
      "source_id": null,
      "source_label": null,
      "expires_at": null,
      "status": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/inventory/reservations?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/inventory/reserve`

Reserve inventory

Creates an inventory reservation and assigns available buckets using the configured stock strategy.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": "00000000-0000-4000-8000-000000000000",
  "quantity": 1,
  "sourceType": "order",
  "sourceId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory reserved

Content-Type: `application/json`

```json
{
  "ok": true,
  "reservationId": "00000000-0000-4000-8000-000000000000",
  "allocatedBuckets": [
    {
      "locationId": "00000000-0000-4000-8000-000000000000",
      "lotId": null,
      "quantity": "string"
    }
  ]
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Insufficient stock

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Invalid tracking state

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/inventory/reserve" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
  \"quantity\": 1,
  \"sourceType\": \"order\",
  \"sourceId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/wms/locations`

Delete warehouse location

Soft-deletes a warehouse location by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse location deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/wms/locations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/locations`

List warehouse locations

Returns a paginated collection of warehouse locations scoped to the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| warehouseId | query | any | Optional |
| parentId | query | any | Optional |
| type | query | any | Optional |
| isActive | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated warehouse locations

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "warehouse_id": null,
      "warehouse_name": null,
      "warehouse_code": null,
      "parent_id": null,
      "code": null,
      "type": null,
      "is_active": null,
      "capacity_units": null,
      "capacity_weight": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/locations?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/locations`

Create warehouse location

Creates a storage location within a warehouse hierarchy.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "code": "string",
  "type": "zone",
  "parentId": null
}
```

### Responses

**201** – Warehouse location created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/locations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"code\": \"string\",
  \"type\": \"zone\",
  \"parentId\": null
}"
```

## PUT `/wms/locations`

Update warehouse location

Updates a warehouse location by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000",
  "parentId": null
}
```

### Responses

**200** – Warehouse location updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/wms/locations" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\",
  \"parentId\": null
}"
```

## DELETE `/wms/lots`

Delete inventory lot

Soft-deletes an inventory lot by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory lot deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/wms/lots" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/lots`

List inventory lots

Returns a paginated collection of inventory lots scoped to the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| catalogVariantId | query | any | Optional |
| status | query | any | Optional |
| expiryWindow | query | any | Optional |
| warehouseId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated inventory lots

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "catalog_variant_id": null,
      "sku": null,
      "lot_number": null,
      "batch_number": null,
      "manufactured_at": null,
      "best_before_at": null,
      "expires_at": null,
      "status": null,
      "metadata": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/lots?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/lots`

Create inventory lot

Creates an inventory lot or batch record.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "catalogVariantId": "00000000-0000-4000-8000-000000000000",
  "sku": "string",
  "lotNumber": "string"
}
```

### Responses

**201** – Inventory lot created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/lots" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"catalogVariantId\": \"00000000-0000-4000-8000-000000000000\",
  \"sku\": \"string\",
  \"lotNumber\": \"string\"
}"
```

## PUT `/wms/lots`

Update inventory lot

Updates an inventory lot by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Inventory lot updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/wms/lots" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/wms/sales-orders/{salesOrderId}/re-run-reservation`

Re-run reservation for sales order

Triggers the automatic reservation logic for a sales order, attempting to fill any remaining shortfall.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| salesOrderId | path | any | Required |

### Responses

**200** – Reservation re-run attempted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Order not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/sales-orders/:salesOrderId/re-run-reservation" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## DELETE `/wms/sales-orders/{salesOrderId}/warehouse-assignment`

Remove warehouse assignment from sales order

Clears the explicit assignment so enricher and automation fall back again.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| salesOrderId | path | any | Required |

### Responses

**200** – Assignment removed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/wms/sales-orders/:salesOrderId/warehouse-assignment" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/wms/sales-orders/{salesOrderId}/warehouse-assignment`

Get warehouse assignment for sales order

Returns the explicit WMS warehouse assignment for a sales order, or null when none is set.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| salesOrderId | path | any | Required |

### Responses

**200** – Assignment state

Content-Type: `application/json`

```json
{
  "assignment": null
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/sales-orders/:salesOrderId/warehouse-assignment" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PATCH `/wms/sales-orders/{salesOrderId}/warehouse-assignment`

Patch warehouse assignment for sales order

Same as PUT — upserts the explicit warehouse assignment.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| salesOrderId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse assigned

Content-Type: `application/json`

```json
{
  "ok": true,
  "assignmentId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/wms/sales-orders/:salesOrderId/warehouse-assignment" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## PUT `/wms/sales-orders/{salesOrderId}/warehouse-assignment`

Assign warehouse to sales order

Creates or replaces the explicit warehouse assignment for a sales order.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| salesOrderId | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse assigned

Content-Type: `application/json`

```json
{
  "ok": true,
  "assignmentId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

**201** – Warehouse assigned

Content-Type: `application/json`

```json
{
  "ok": true,
  "assignmentId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Warehouse not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Warehouse is inactive

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/wms/sales-orders/:salesOrderId/warehouse-assignment" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/wms/sales-orders/assign-warehouse`

Assign warehouse to sales order

Explicitly assigns a warehouse to a sales order. When set, the enricher returns this warehouse and the reservation automation prefers it.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "salesOrderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse assignment updated

Content-Type: `application/json`

```json
{
  "ok": true,
  "assignmentId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

**201** – Warehouse assigned

Content-Type: `application/json`

```json
{
  "ok": true,
  "assignmentId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000"
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Warehouse not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**422** – Warehouse is inactive

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/sales-orders/assign-warehouse" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"salesOrderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## POST `/wms/sales-orders/unassign-warehouse`

Remove warehouse assignment from sales order

Removes an explicit warehouse assignment from a sales order. The enricher will fall back to deriving the warehouse from active reservations or the primary warehouse.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "salesOrderId": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Assignment removed

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Validation failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/sales-orders/unassign-warehouse" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"salesOrderId\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/wms/warehouses`

Delete warehouse

Soft-deletes a warehouse by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/wms/warehouses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/warehouses`

List warehouses

Returns a paginated collection of warehouses scoped to the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| isActive | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated warehouses

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "name": null,
      "code": null,
      "is_active": null,
      "is_primary": null,
      "address_line1": null,
      "city": null,
      "postal_code": null,
      "country": null,
      "timezone": null,
      "created_at": null,
      "updated_at": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/warehouses?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/warehouses`

Create warehouse

Creates a warehouse for inventory operations.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "name": "string",
  "code": "string"
}
```

### Responses

**201** – Warehouse created

Content-Type: `application/json`

```json
{
  "id": null,
  "updatedAt": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/warehouses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"name\": \"string\",
  \"code\": \"string\"
}"
```

## PUT `/wms/warehouses`

Update warehouse

Updates a warehouse by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/wms/warehouses" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## DELETE `/wms/zones`

Delete warehouse zone

Soft-deletes a warehouse zone by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse zone deleted

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/wms/zones" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/wms/zones`

List warehouse zones

Returns a paginated collection of warehouse zones scoped to the authenticated organization.

**Tags:** WMS

**Requires authentication.**

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| search | query | any | Optional |
| warehouseId | query | any | Optional |
| ids | query | any | Optional. Comma-separated list of record UUIDs to filter by (max 200). |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – Paginated warehouse zones

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": null,
      "organization_id": null,
      "tenant_id": null,
      "warehouse_id": null,
      "warehouse_name": null,
      "warehouse_code": null,
      "code": null,
      "name": null,
      "priority": null,
      "created_at": null,
      "updated_at": null,
      "customValues": null
    }
  ],
  "total": 1,
  "totalPages": 1
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/wms/zones?page=1&pageSize=25" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## POST `/wms/zones`

Create warehouse zone

Creates a zone within a warehouse.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "warehouseId": "00000000-0000-4000-8000-000000000000",
  "code": "string",
  "name": "string"
}
```

### Responses

**201** – Warehouse zone created

Content-Type: `application/json`

```json
{
  "id": null
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/wms/zones" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"organizationId\": \"00000000-0000-4000-8000-000000000000\",
  \"tenantId\": \"00000000-0000-4000-8000-000000000000\",
  \"warehouseId\": \"00000000-0000-4000-8000-000000000000\",
  \"code\": \"string\",
  \"name\": \"string\"
}"
```

## PUT `/wms/zones`

Update warehouse zone

Updates a warehouse zone by id.

**Tags:** WMS

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "id": "00000000-0000-4000-8000-000000000000"
}
```

### Responses

**200** – Warehouse zone updated

Content-Type: `application/json`

```json
{
  "ok": true
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/wms/zones" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"id\": \"00000000-0000-4000-8000-000000000000\"
}"
```

## GET `/workflows/command-settings`

List workflow-safe command candidates with tenant enablement

Returns every command declared through registerWorkflowSafeCommands together with whether this tenant has switched it on. `configured: false` means the tenant has never saved the setting and the answers come from the grandfathered defaults.

**Tags:** Workflows

**Requires authentication.**

### Responses

**200** – Catalogue with tenant enablement

Content-Type: `application/json`

```json
{
  "configured": true,
  "items": [
    {
      "commandId": "string",
      "requiredFeatures": [
        "string"
      ],
      "labelKey": null
    }
  ]
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/command-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/workflows/command-settings`

Set which workflow-safe commands are enabled for the tenant

Replaces the tenant's enabled set. Every submitted id must be present in the code-declared catalogue; an unknown id is rejected with 400 rather than stored. Stored ids whose declaring module is not loaded in this process are retained so a save can never silently untick them.

**Tags:** Workflows

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "enabledCommandIds": [
    "string"
  ]
}
```

### Responses

**200** – Updated enablement

Content-Type: `application/json`

```json
{
  "configured": true,
  "items": [
    {
      "commandId": "string",
      "requiredFeatures": [
        "string"
      ],
      "labelKey": null
    }
  ],
  "ok": true
}
```

**400** – Invalid payload or unknown command id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Settings storage unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/workflows/command-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"enabledCommandIds\": [
    \"string\"
  ]
}"
```

## GET `/workflows/commands`

List commands allowlisted for UPDATE_ENTITY activities

Returns the registered workflow-safe command catalogue consumed by the UPDATE_ENTITY command picker, each entry carrying whether the caller's tenant has enabled it. Entries with enabled:false, and commands outside the catalogue entirely, can still be authored but fail at runtime.

**Tags:** Workflows

### Responses

**200** – Allowlisted workflow-safe commands

Content-Type: `application/json`

```json
{
  "items": [
    {
      "commandId": "string",
      "requiredFeatures": [
        "string"
      ],
      "labelKey": null
    }
  ]
}
```

**400** – Missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/commands" \
  -H "Accept: application/json"
```

## GET `/workflows/definitions`

List workflow definitions

Get a list of workflow definitions with optional filters. Supports pagination and search.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| workflowId | query | any | Required |
| enabled | query | any | Optional |
| search | query | any | Optional |
| limit | query | any | Optional |
| offset | query | any | Optional |

### Responses

**200** – List of workflow definitions with pagination

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "workflowId": "checkout-flow",
      "workflowName": "Checkout Flow",
      "description": "Complete checkout workflow for processing orders",
      "version": 1,
      "definition": {
        "steps": [
          {
            "stepId": "start",
            "stepName": "Start",
            "stepType": "START"
          },
          {
            "stepId": "validate-cart",
            "stepName": "Validate Cart",
            "stepType": "AUTOMATED"
          },
          {
            "stepId": "end",
            "stepName": "End",
            "stepType": "END"
          }
        ],
        "transitions": [
          {
            "transitionId": "start-to-validate",
            "fromStepId": "start",
            "toStepId": "validate-cart",
            "trigger": "auto"
          },
          {
            "transitionId": "validate-to-end",
            "fromStepId": "validate-cart",
            "toStepId": "end",
            "trigger": "auto"
          }
        ]
      },
      "enabled": true,
      "tenantId": "123e4567-e89b-12d3-a456-426614174001",
      "organizationId": "123e4567-e89b-12d3-a456-426614174002",
      "createdAt": "2025-12-08T10:00:00.000Z",
      "updatedAt": "2025-12-08T10:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "offset": 0,
    "hasMore": false
  }
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/definitions?workflowId=string&limit=50&offset=0" \
  -H "Accept: application/json"
```

## POST `/workflows/definitions`

Create workflow definition

Create a new workflow definition. The definition must include at least START and END steps with at least one transition connecting them.

**Tags:** Workflows

### Request Body

Content-Type: `application/json`

```json
{
  "workflowId": "checkout-flow",
  "workflowName": "Checkout Flow",
  "description": "Complete checkout workflow for processing orders",
  "version": 1,
  "definition": {
    "steps": [
      {
        "stepId": "start",
        "stepName": "Start",
        "stepType": "START"
      },
      {
        "stepId": "validate-cart",
        "stepName": "Validate Cart",
        "stepType": "AUTOMATED",
        "description": "Validate cart items and check inventory"
      },
      {
        "stepId": "payment",
        "stepName": "Process Payment",
        "stepType": "AUTOMATED",
        "description": "Charge payment method",
        "retryPolicy": {
          "maxAttempts": 3,
          "backoffMs": 1000
        }
      },
      {
        "stepId": "end",
        "stepName": "End",
        "stepType": "END"
      }
    ],
    "transitions": [
      {
        "transitionId": "start-to-validate",
        "fromStepId": "start",
        "toStepId": "validate-cart",
        "trigger": "auto"
      },
      {
        "transitionId": "validate-to-payment",
        "fromStepId": "validate-cart",
        "toStepId": "payment",
        "trigger": "auto"
      },
      {
        "transitionId": "payment-to-end",
        "fromStepId": "payment",
        "toStepId": "end",
        "trigger": "auto",
        "activities": [
          {
            "activityName": "Send Order Confirmation",
            "activityType": "SEND_EMAIL",
            "config": {
              "to": "{{context.customerEmail}}",
              "subject": "Order Confirmation #{{context.orderId}}",
              "template": "order_confirmation"
            }
          }
        ]
      }
    ]
  },
  "enabled": true
}
```

### Responses

**201** – Workflow definition created successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Complete checkout workflow for processing orders",
    "version": 1,
    "definition": {
      "steps": [
        {
          "stepId": "start",
          "stepName": "Start",
          "stepType": "START"
        },
        {
          "stepId": "validate-cart",
          "stepName": "Validate Cart",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "payment",
          "stepName": "Process Payment",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "end",
          "stepName": "End",
          "stepType": "END"
        }
      ],
      "transitions": [
        {
          "transitionId": "start-to-validate",
          "fromStepId": "start",
          "toStepId": "validate-cart",
          "trigger": "auto"
        },
        {
          "transitionId": "validate-to-payment",
          "fromStepId": "validate-cart",
          "toStepId": "payment",
          "trigger": "auto"
        },
        {
          "transitionId": "payment-to-end",
          "fromStepId": "payment",
          "toStepId": "end",
          "trigger": "auto"
        }
      ]
    },
    "enabled": true,
    "tenantId": "123e4567-e89b-12d3-a456-426614174001",
    "organizationId": "123e4567-e89b-12d3-a456-426614174002",
    "createdAt": "2025-12-08T10:00:00.000Z",
    "updatedAt": "2025-12-08T10:00:00.000Z"
  },
  "message": "Workflow definition created successfully"
}
```

**400** – Validation error - invalid workflow structure

Content-Type: `application/json`

```json
{
  "error": "Validation failed",
  "details": [
    {
      "path": [
        "definition",
        "steps"
      ],
      "code": "custom",
      "message": "Workflow must have at least START and END steps"
    }
  ]
}
```

**409** – Conflict - workflow with same ID and version already exists

Content-Type: `application/json`

```json
{
  "error": "Workflow definition with ID \"checkout-flow\" and version 1 already exists"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/definitions" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"workflowId\": \"string\",
  \"workflowName\": \"string\",
  \"description\": null,
  \"version\": 1,
  \"definition\": {
    \"steps\": [
      {
        \"stepId\": \"string\",
        \"stepName\": \"string\",
        \"stepType\": \"START\"
      }
    ],
    \"transitions\": [
      {
        \"transitionId\": \"string\",
        \"fromStepId\": \"string\",
        \"toStepId\": \"string\",
        \"trigger\": \"auto\",
        \"condition\": null,
        \"continueOnActivityFailure\": false,
        \"priority\": 0
      }
    ]
  },
  \"metadata\": null,
  \"enabled\": true,
  \"grantedFeatures\": null
}"
```

## DELETE `/workflows/definitions/{id}`

Delete workflow definition

Soft delete a workflow definition. Cannot be deleted if there are active workflow instances (RUNNING or WAITING status) using this definition.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Workflow definition deleted successfully

Content-Type: `application/json`

```json
{
  "message": "Workflow definition deleted successfully"
}
```

**404** – Workflow definition not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

**409** – Cannot delete - active workflow instances exist

Content-Type: `application/json`

```json
{
  "error": "Cannot delete workflow definition with 3 active instance(s)"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/workflows/definitions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json"
```

## GET `/workflows/definitions/{id}`

Get workflow definition

Get a single workflow definition by ID. Returns the complete workflow structure including steps and transitions (with embedded activities).

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. UUID for DB definitions, or "code:<workflowId>" for code-based definitions |

### Responses

**200** – Workflow definition found

Content-Type: `application/json`

```json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Complete checkout workflow for processing orders",
    "version": 1,
    "definition": {
      "steps": [
        {
          "stepId": "start",
          "stepName": "Start",
          "stepType": "START"
        },
        {
          "stepId": "validate-cart",
          "stepName": "Validate Cart",
          "stepType": "AUTOMATED",
          "description": "Validate cart items and check inventory"
        },
        {
          "stepId": "payment",
          "stepName": "Process Payment",
          "stepType": "AUTOMATED",
          "description": "Charge payment method",
          "retryPolicy": {
            "maxAttempts": 3,
            "backoffMs": 1000
          }
        },
        {
          "stepId": "end",
          "stepName": "End",
          "stepType": "END"
        }
      ],
      "transitions": [
        {
          "transitionId": "start-to-validate",
          "fromStepId": "start",
          "toStepId": "validate-cart",
          "trigger": "auto"
        },
        {
          "transitionId": "validate-to-payment",
          "fromStepId": "validate-cart",
          "toStepId": "payment",
          "trigger": "auto"
        },
        {
          "transitionId": "payment-to-end",
          "fromStepId": "payment",
          "toStepId": "end",
          "trigger": "auto",
          "activities": [
            {
              "activityName": "Send Order Confirmation",
              "activityType": "SEND_EMAIL",
              "config": {
                "to": "{{context.customerEmail}}",
                "subject": "Order Confirmation #{{context.orderId}}",
                "template": "order_confirmation"
              }
            }
          ]
        }
      ]
    },
    "enabled": true,
    "tenantId": "123e4567-e89b-12d3-a456-426614174001",
    "organizationId": "123e4567-e89b-12d3-a456-426614174002",
    "createdAt": "2025-12-08T10:00:00.000Z",
    "updatedAt": "2025-12-08T10:00:00.000Z"
  }
}
```

**404** – Workflow definition not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/definitions/string" \
  -H "Accept: application/json"
```

## PUT `/workflows/definitions/{id}`

Update workflow definition

Update an existing workflow definition. Supports partial updates - only provided fields will be updated.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "definition": {
    "steps": [
      {
        "stepId": "start",
        "stepName": "Start",
        "stepType": "START"
      },
      {
        "stepId": "validate-cart",
        "stepName": "Validate Cart",
        "stepType": "AUTOMATED"
      },
      {
        "stepId": "payment",
        "stepName": "Process Payment",
        "stepType": "AUTOMATED"
      },
      {
        "stepId": "confirmation",
        "stepName": "Order Confirmation",
        "stepType": "AUTOMATED"
      },
      {
        "stepId": "end",
        "stepName": "End",
        "stepType": "END"
      }
    ],
    "transitions": [
      {
        "transitionId": "start-to-validate",
        "fromStepId": "start",
        "toStepId": "validate-cart",
        "trigger": "auto"
      },
      {
        "transitionId": "validate-to-payment",
        "fromStepId": "validate-cart",
        "toStepId": "payment",
        "trigger": "auto"
      },
      {
        "transitionId": "payment-to-confirmation",
        "fromStepId": "payment",
        "toStepId": "confirmation",
        "trigger": "auto"
      },
      {
        "transitionId": "confirmation-to-end",
        "fromStepId": "confirmation",
        "toStepId": "end",
        "trigger": "auto"
      }
    ]
  },
  "enabled": true
}
```

### Responses

**200** – Workflow definition updated successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Complete checkout workflow for processing orders",
    "version": 1,
    "definition": {
      "steps": [
        {
          "stepId": "start",
          "stepName": "Start",
          "stepType": "START"
        },
        {
          "stepId": "validate-cart",
          "stepName": "Validate Cart",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "payment",
          "stepName": "Process Payment",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "confirmation",
          "stepName": "Order Confirmation",
          "stepType": "AUTOMATED"
        },
        {
          "stepId": "end",
          "stepName": "End",
          "stepType": "END"
        }
      ],
      "transitions": [
        {
          "transitionId": "start-to-validate",
          "fromStepId": "start",
          "toStepId": "validate-cart",
          "trigger": "auto"
        },
        {
          "transitionId": "validate-to-payment",
          "fromStepId": "validate-cart",
          "toStepId": "payment",
          "trigger": "auto"
        },
        {
          "transitionId": "payment-to-confirmation",
          "fromStepId": "payment",
          "toStepId": "confirmation",
          "trigger": "auto"
        },
        {
          "transitionId": "confirmation-to-end",
          "fromStepId": "confirmation",
          "toStepId": "end",
          "trigger": "auto"
        }
      ]
    },
    "enabled": true,
    "tenantId": "123e4567-e89b-12d3-a456-426614174001",
    "organizationId": "123e4567-e89b-12d3-a456-426614174002",
    "createdAt": "2025-12-08T10:00:00.000Z",
    "updatedAt": "2025-12-08T11:30:00.000Z"
  },
  "message": "Workflow definition updated successfully"
}
```

**400** – Validation error

Content-Type: `application/json`

```json
{
  "error": "Validation failed",
  "details": [
    {
      "path": [
        "definition"
      ],
      "code": "invalid_type",
      "message": "Invalid input: expected object, received string",
      "expected": "object",
      "got": "string"
    }
  ]
}
```

**404** – Workflow definition not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

**409** – Structural change refused while instances are still running (or optimistic-lock conflict). Publish a new version and apply the change there.

Content-Type: `application/json`

```json
{
  "error": "Structural changes require a new version while instances are still running",
  "code": "WORKFLOW_STRUCTURAL_EDIT_REQUIRES_NEW_VERSION",
  "definitionId": "123e4567-e89b-12d3-a456-426614174000",
  "activeInstanceCount": 3,
  "activeStatuses": [
    "RUNNING",
    "PAUSED",
    "WAITING_FOR_ACTIVITIES",
    "FORKED",
    "COMPENSATING"
  ],
  "changes": [
    {
      "kind": "transitionRetargeted",
      "id": "t_lz3k9_ab12cd34e"
    }
  ],
  "remedy": {
    "action": "createVersion",
    "method": "POST",
    "endpoint": "/api/workflows/definitions/123e4567-e89b-12d3-a456-426614174000/publish"
  }
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/workflows/definitions/00000000-0000-4000-8000-000000000000" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"description\": null,
  \"metadata\": null,
  \"effectiveFrom\": null,
  \"effectiveTo\": null,
  \"grantedFeatures\": null
}"
```

## GET `/workflows/definitions/{id}/callers`

List sub-workflow callers and breaking mappings

Returns parent definitions that invoke this workflow as a sub-workflow and the mappings its current port contract would break.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. Workflow definition id |

### Responses

**200** – Callers

Content-Type: `application/json`

```json
{
  "callers": [
    {
      "workflowId": "order-flow",
      "version": 1,
      "stepId": "sub",
      "brokenMappings": [
        "input:orderId"
      ]
    }
  ]
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/definitions/string/callers" \
  -H "Accept: application/json"
```

## GET `/workflows/definitions/{id}/context-schema`

Get the per-step context ledger

Computes what context paths are available at each step of the workflow definition, with type, presence (always/maybe), and producer source. Presence degrades to "maybe" at joins unless the entry arrives on every incoming route. Use ?stepId=<id> to narrow the response to one step.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. UUID for DB definitions, or "code:<workflowId>" for code-based definitions |
| stepId | query | any | Optional. Narrow the response to this step (404 when the step does not exist) |

### Responses

**200** – Per-step context ledger

Content-Type: `application/json`

```json
{
  "steps": {
    "approve": {
      "entries": [
        {
          "path": "orderId",
          "type": "text",
          "presence": "always",
          "source": {
            "kind": "contextSchema",
            "label": "contextSchema.input"
          }
        },
        {
          "path": "discount",
          "type": "number",
          "presence": "maybe",
          "source": {
            "kind": "userTask",
            "stepId": "review",
            "label": "userTask:review"
          }
        }
      ]
    }
  }
}
```

**400** – Missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow definition or requested step not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/definitions/string/context-schema" \
  -H "Accept: application/json"
```

## POST `/workflows/definitions/{id}/customize`

Customize code-based workflow definition

Creates a DB override for a code-based workflow definition, seeded from the current code registry values. The id param must be of the form "code:<workflowId>".

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. Must be of the form "code:<workflowId>" |

### Responses

**200** – Workflow definition customized successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "workflowId": "workflows.simple-approval",
    "workflowName": "Simple Approval Workflow",
    "source": "code_override"
  },
  "message": "Workflow definition customized successfully"
}
```

**400** – Not a code-based id

Content-Type: `application/json`

```json
{
  "error": "Customize is only supported for code-based workflow definitions"
}
```

**404** – Code workflow not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/definitions/string/customize" \
  -H "Accept: application/json"
```

## DELETE `/workflows/definitions/{id}/draft`

Discard the current user's draft

Deletes the authenticated user's draft for the workflow definition. Idempotent: discarding a non-existent draft succeeds.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. Workflow definition UUID (server drafts exist only for saved definitions) |

### Responses

**200** – Draft discarded (or no draft existed)

Content-Type: `application/json`

```json
{
  "message": "string"
}
```

**400** – Invalid definition id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X DELETE "https://makeitflow.90210.pl/api/workflows/definitions/string/draft" \
  -H "Accept: application/json"
```

## GET `/workflows/definitions/{id}/draft`

Get the current user's draft

Returns the authenticated user's autosaved draft for the workflow definition. Drafts are private to the user who saved them.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. Workflow definition UUID (server drafts exist only for saved definitions) |

### Responses

**200** – Draft found

Content-Type: `application/json`

```json
{
  "data": {
    "id": "string",
    "definitionId": null,
    "definition": {
      "steps": [
        {}
      ],
      "transitions": [
        {}
      ]
    },
    "metadata": null,
    "baseUpdatedAt": null,
    "createdAt": null,
    "updatedAt": null
  }
}
```

**400** – Invalid definition id (only saved definitions have server drafts)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – No draft exists for this user and definition

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/definitions/string/draft" \
  -H "Accept: application/json"
```

## PUT `/workflows/definitions/{id}/draft`

Save the current user's draft

Creates or updates the authenticated user's draft for the workflow definition. The definition payload is validated shape-only (steps and transitions must be arrays of objects) so a mid-edit, structurally incomplete graph still saves; full validation runs when the draft is promoted via the definition PUT. Draft saves never participate in the definition's optimistic lock.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. Workflow definition UUID (server drafts exist only for saved definitions) |

### Request Body

Content-Type: `application/json`

```json
{
  "definition": {
    "steps": [
      {
        "stepId": "start",
        "stepName": "Start",
        "stepType": "START"
      }
    ],
    "transitions": []
  },
  "baseUpdatedAt": "2026-07-27T10:00:00.000Z"
}
```

### Responses

**200** – Draft saved

Content-Type: `application/json`

```json
{
  "data": {
    "id": "string",
    "definitionId": null,
    "definition": {
      "steps": [
        {}
      ],
      "transitions": [
        {}
      ]
    },
    "metadata": null,
    "baseUpdatedAt": null,
    "createdAt": null,
    "updatedAt": null
  },
  "message": "string"
}
```

**400** – Malformed draft payload or invalid definition id

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow definition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/workflows/definitions/string/draft" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"definition\": {
    \"steps\": [
      {}
    ],
    \"transitions\": [
      {}
    ]
  },
  \"metadata\": null,
  \"baseUpdatedAt\": null
}"
```

## POST `/workflows/definitions/{id}/publish`

Publish a new workflow definition version

Mints a frozen published version snapshotting the definition and its IO port contract. Returns affected sub-workflow callers; pass acknowledgeBreakingChanges=true to publish despite breaking changes.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. Workflow definition id |

### Request Body

Content-Type: `application/json`

No example available for this content type.

### Responses

**200** – Published

Content-Type: `application/json`

```json
{
  "data": {
    "id": "…",
    "workflowId": "verify-policy",
    "version": 2,
    "lifecycle": "published"
  },
  "breakingChanges": [],
  "message": "Workflow definition published successfully"
}
```

**404** – Not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

**409** – Breaking changes not acknowledged

Content-Type: `application/json`

```json
{
  "error": "Publishing would break existing sub-workflow mappings",
  "breakingChanges": [
    {
      "workflowId": "order-flow",
      "version": 1,
      "stepId": "sub",
      "brokenMappings": [
        "input:orderId"
      ]
    }
  ]
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/definitions/string/publish" \
  -H "Accept: application/json"
```

## POST `/workflows/definitions/{id}/reset-to-code`

Reset workflow definition to code version

Deletes the DB override for a code-based workflow definition, reverting it to the original code registry version. Cannot be reset if there are active instances.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Workflow definition reset to code version

Content-Type: `application/json`

```json
{
  "data": {
    "id": "code:checkout-flow",
    "workflowId": "checkout-flow",
    "workflowName": "Checkout Flow",
    "description": "Code-defined checkout workflow",
    "version": 1,
    "source": "code",
    "isCodeBased": true
  },
  "message": "Workflow definition reset to code version"
}
```

**400** – Definition is not a code-based override

Content-Type: `application/json`

```json
{
  "error": "This workflow definition is not a code-based override and cannot be reset"
}
```

**404** – Workflow definition not found

Content-Type: `application/json`

```json
{
  "error": "Workflow definition not found"
}
```

**409** – Cannot reset - active workflow instances exist

Content-Type: `application/json`

```json
{
  "error": "Cannot reset workflow definition with 3 active instance(s)"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/definitions/00000000-0000-4000-8000-000000000000/reset-to-code" \
  -H "Accept: application/json"
```

## POST `/workflows/definitions/{id}/test-step`

Dry-run one activity config with mock-first semantics

Interpolates the supplied activity config against the sample context (plus a synthetic workflow scope and the server env allowlist) and runs the activity type's would-do mock. Never executes the real activity. Activity types that declare no mock or opt out with "refuse" respond 200 with a structured refusal the editor renders.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required. UUID for DB definitions, or "code:<workflowId>" for code-based definitions |

### Request Body

Content-Type: `application/json`

```json
{
  "stepId": "notify",
  "activityType": "SEND_EMAIL",
  "config": {
    "to": "{{context.customerEmail}}",
    "subject": "Order {{context.orderId}} approved"
  },
  "context": {
    "customerEmail": "jane@example.com",
    "orderId": "ORD-42"
  }
}
```

### Responses

**200** – Simulated mock output, or a structured refusal when the type cannot be simulated

Content-Type: `application/json`

```json
{
  "simulated": true,
  "activityType": "SEND_EMAIL",
  "output": {
    "sent": false,
    "simulated": true,
    "wouldSendTo": "jane@example.com",
    "subject": "Order ORD-42 approved"
  },
  "interpolatedConfig": {
    "to": "jane@example.com",
    "subject": "Order ORD-42 approved"
  }
}
```

**400** – Missing tenant context or malformed payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow definition or activity type not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/definitions/string/test-step" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"activityType\": \"string\",
  \"config\": {}
}"
```

## POST `/workflows/definitions/generate`

Author a draft workflow definition from natural language

Runs the propose-only workflows.workflow_author agent against this installation's activity, command, function and event catalogs and returns a draft definition plus the Problems-panel evaluation for it. Persists nothing: the draft is returned to the Studio for a human to apply, save and enable. Refusals ("unavailable" when no AI provider or agent registry is present, "failed" when the model call errored, "malformedResponse"/"schemaError" when the output is not a workflow definition) respond 200 with a structured body.

**Tags:** Workflows

### Request Body

Content-Type: `application/json`

```json
{
  "prompt": "string"
}
```

### Responses

**200** – The generated draft with its Problems-panel evaluation, or a structured refusal

Content-Type: `application/json`

```json
{
  "ok": true
}
```

**400** – Invalid request body

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Generation failed unexpectedly

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/definitions/generate" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"prompt\": \"string\"
}"
```

## GET `/workflows/endpoints`

List endpoints available to CALL_API activities

Returns a trimmed projection of the OpenAPI surface (path, method, summary, tag, parameters, and declared request/response schemas) consumed by the CALL_API endpoint picker. Endpoints outside this catalog can still be authored as free text. Responses without a declared schema omit responseSchema so consumers degrade to unknown typing.

**Tags:** Workflows

### Responses

**200** – Endpoint catalog projected from the OpenAPI surface

Content-Type: `application/json`

```json
{
  "items": [
    {
      "path": "string",
      "method": "string",
      "summary": "string",
      "tag": "string",
      "params": [
        {
          "name": "string",
          "in": "path",
          "required": true,
          "type": "string"
        }
      ],
      "hasRequestSchema": true
    }
  ]
}
```

**400** – Missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/endpoints" \
  -H "Accept: application/json"
```

## GET `/workflows/events`

List all workflow events

Get a paginated list of all workflow events with filtering options

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| page | query | any | Optional |
| pageSize | query | any | Optional |
| eventType | query | any | Optional |
| workflowInstanceId | query | any | Optional |
| userId | query | any | Optional |
| occurredAtFrom | query | any | Optional |
| occurredAtTo | query | any | Optional |
| sortField | query | any | Optional |
| sortDir | query | any | Optional |

### Responses

**200** – List of workflow events

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
      "stepInstanceId": null,
      "eventType": "string",
      "occurredAt": "string",
      "userId": null,
      "workflowInstance": null
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 1,
  "totalPages": 1
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/events?page=1&pageSize=50&sortField=occurredAt&sortDir=desc" \
  -H "Accept: application/json"
```

## GET `/workflows/events/{id}`

Get workflow event by ID

Get detailed information about a specific workflow event

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Workflow event details

Content-Type: `application/json`

```json
{
  "id": "string",
  "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
  "stepInstanceId": null,
  "eventType": "string",
  "occurredAt": "string",
  "userId": null,
  "tenantId": "00000000-0000-4000-8000-000000000000",
  "organizationId": "00000000-0000-4000-8000-000000000000",
  "workflowInstance": null
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow event not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/events/:id" \
  -H "Accept: application/json"
```

## GET `/workflows/functions`

List registered workflow function descriptors for EXECUTE_FUNCTION activities

Returns the registered workflow function descriptors consumed by the EXECUTE_FUNCTION function picker. Functions outside this list can still be authored but fail at runtime when no matching workflowFunction:<name> DI registration exists.

**Tags:** Workflows

### Responses

**200** – Registered workflow function descriptors

Content-Type: `application/json`

```json
{
  "items": [
    {
      "name": "string"
    }
  ]
}
```

**400** – Missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/functions" \
  -H "Accept: application/json"
```

## GET `/workflows/grantable-features`

List grantable execution features

Declared ACL feature ids/titles intersected with the calling user’s own current grants (wildcard-aware). Drives the definition editor’s execution-permissions picker; gated by workflows.definitions.grant_features.

**Tags:** Workflows

**Requires authentication.**

### Responses

**200** – Grantable feature catalog

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "title": "string",
      "module": "string"
    }
  ]
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Missing workflows.definitions.grant_features

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/grantable-features" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## GET `/workflows/instances`

List workflow instances

Get a list of workflow instances with optional filters. Supports pagination and filtering by status, workflowId, correlationKey, etc.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| workflowId | query | any | Optional |
| status | query | any | Optional |
| outcome | query | any | Optional. Filter by the run VERDICT, independently of status. Comma-separated for several (e.g. partial_failure,failure). An unknown value is a 400. |
| correlationKey | query | any | Optional |
| entityType | query | any | Optional |
| entityId | query | any | Optional |
| parentInstanceId | query | any | Optional. Return only direct sub-workflow children of this parent instance. |
| hasParent | query | any | Optional. false = only top-level/standalone instances; true = only sub-workflow children. Ignored when parentInstanceId is set. |
| attention | query | any | Optional. true = only instances parked by a failure-queue error directive; false = only instances without an attention marker. |
| startedFrom | query | any | Optional. Lower bound on startedAt. A calendar day (YYYY-MM-DD) is taken from 00:00:00.000Z; a full ISO timestamp is taken verbatim. |
| startedTo | query | any | Optional. Upper bound on startedAt, inclusive. A calendar day (YYYY-MM-DD) covers the whole day up to 23:59:59.999Z. |
| limit | query | any | Optional |
| offset | query | any | Optional |

### Responses

**200** – List of workflow instances

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "definitionId": "00000000-0000-4000-8000-000000000000",
      "workflowId": "string",
      "version": 1,
      "status": "RUNNING",
      "outcome": null,
      "currentStepId": "string",
      "correlationKey": null,
      "metadata": null,
      "startedAt": "string",
      "completedAt": null,
      "pausedAt": null,
      "cancelledAt": null,
      "errorMessage": null,
      "errorDetails": null,
      "pendingTransition": null,
      "retryCount": 1,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "deletedAt": null
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  }
}
```

**400** – Invalid date range or unknown outcome

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/instances?limit=50&offset=0" \
  -H "Accept: application/json"
```

## POST `/workflows/instances`

Start workflow instance

Start a new workflow instance from a workflow definition. The workflow will execute immediately.

**Tags:** Workflows

### Request Body

Content-Type: `application/json`

```json
{
  "workflowId": "string"
}
```

### Responses

**201** – Workflow started successfully

Content-Type: `application/json`

```json
{
  "data": {
    "instance": {
      "id": "00000000-0000-4000-8000-000000000000",
      "definitionId": "00000000-0000-4000-8000-000000000000",
      "workflowId": "string",
      "version": 1,
      "status": "RUNNING",
      "outcome": null,
      "currentStepId": "string",
      "correlationKey": null,
      "metadata": null,
      "startedAt": "string",
      "completedAt": null,
      "pausedAt": null,
      "cancelledAt": null,
      "errorMessage": null,
      "errorDetails": null,
      "pendingTransition": null,
      "retryCount": 1,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "deletedAt": null
    },
    "execution": {
      "status": "RUNNING",
      "currentStep": "string",
      "message": "string"
    }
  },
  "message": "string"
}
```

**400** – Bad request - Validation failed or definition disabled/invalid

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow definition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"workflowId\": \"string\"
}"
```

## GET `/workflows/instances/{id}`

Get workflow instance

Get detailed information about a specific workflow instance including current state, context, and execution status.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Workflow instance details

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "definitionId": "00000000-0000-4000-8000-000000000000",
    "workflowId": "string",
    "version": 1,
    "status": "RUNNING",
    "outcome": null,
    "currentStepId": "string",
    "correlationKey": null,
    "metadata": null,
    "startedAt": "string",
    "completedAt": null,
    "pausedAt": null,
    "cancelledAt": null,
    "errorMessage": null,
    "errorDetails": null,
    "pendingTransition": null,
    "retryCount": 1,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string",
    "deletedAt": null
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/instances/:id" \
  -H "Accept: application/json"
```

## POST `/workflows/instances/{id}/advance`

Manually advance workflow to next step

Manually advance a workflow instance to the next step. Useful for manual progression, step-by-step testing, user-triggered transitions, and approval flows. Validates transitions and auto-progresses if possible.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Workflow advanced successfully

Content-Type: `application/json`

```json
{
  "data": {
    "instance": {
      "id": "00000000-0000-4000-8000-000000000000",
      "status": "string",
      "currentStepId": null,
      "previousStepId": null,
      "transitionFired": null
    }
  },
  "message": "string"
}
```

**400** – Invalid request, no valid transitions, or workflow already completed/cancelled/failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/:id/advance" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/workflows/instances/{id}/cancel`

Cancel workflow instance

Cancel a running or paused workflow instance. The workflow will be marked as CANCELLED and will not execute further.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Workflow cancelled successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "definitionId": "00000000-0000-4000-8000-000000000000",
    "workflowId": "string",
    "version": 1,
    "status": "RUNNING",
    "outcome": null,
    "currentStepId": "string",
    "correlationKey": null,
    "metadata": null,
    "startedAt": "string",
    "completedAt": null,
    "pausedAt": null,
    "cancelledAt": null,
    "errorMessage": null,
    "errorDetails": null,
    "pendingTransition": null,
    "retryCount": 1,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string",
    "deletedAt": null
  },
  "message": "string"
}
```

**400** – Bad request - Workflow cannot be cancelled in current status

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/:id/cancel" \
  -H "Accept: application/json"
```

## PATCH `/workflows/instances/{id}/context`

Merge a context patch and wake condition waiters

Shallow-merges a partial context patch into a RUNNING/PAUSED/FORKED workflow instance, then re-evaluates every WAIT_FOR_CONDITION waiter in that instance and resumes the ones whose predicate now holds. Reserved engine keys are rejected. Requires the workflows.instances.update_context feature.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "context": {}
}
```

### Responses

**200** – Context merged; woken lists the resumed step ids

Content-Type: `application/json`

```json
{
  "ok": true,
  "instanceId": "string",
  "woken": [
    "string"
  ]
}
```

**400** – Invalid body or reserved context key

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Instance not found in the caller scope

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Instance not updatable or stale version

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PATCH "https://makeitflow.90210.pl/api/workflows/instances/:id/context" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"context\": {}
}"
```

## GET `/workflows/instances/{id}/events`

Get workflow instance events

Get a chronological list of events for a workflow instance. Events track all state changes, transitions, and activities.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| eventType | query | any | Optional |
| limit | query | any | Optional |
| offset | query | any | Optional |

### Responses

**200** – List of workflow events

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "string",
      "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
      "stepInstanceId": null,
      "eventType": "string",
      "occurredAt": "string",
      "userId": null,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/instances/:id/events?limit=100&offset=0" \
  -H "Accept: application/json"
```

## POST `/workflows/instances/{id}/rerun-step`

Rerun a workflow instance from a step

Replay a FAILED or PAUSED instance from one of its executed steps, optionally with an edited context patch. The previous attempt keeps its terminal step-instance row; the replay gets a fresh one, and the rerun is audited as a STEP_RERUN workflow event.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "stepId": "string"
}
```

### Responses

**200** – Rerun started

Content-Type: `application/json`

```json
{
  "data": {
    "instance": {
      "id": "00000000-0000-4000-8000-000000000000",
      "definitionId": "00000000-0000-4000-8000-000000000000",
      "workflowId": "string",
      "version": 1,
      "status": "RUNNING",
      "outcome": null,
      "currentStepId": "string",
      "correlationKey": null,
      "metadata": null,
      "startedAt": "string",
      "completedAt": null,
      "pausedAt": null,
      "cancelledAt": null,
      "errorMessage": null,
      "errorDetails": null,
      "pendingTransition": null,
      "retryCount": 1,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "deletedAt": null
    },
    "editedContextDiff": {}
  },
  "message": "string"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – The step cannot be rerun (still parked, changed type, or the instance is not rerunnable)

Content-Type: `application/json`

```json
{
  "error": "string",
  "code": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/:id/rerun-step" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"stepId\": \"string\"
}"
```

## POST `/workflows/instances/{id}/retry`

Retry failed workflow instance

Retry a failed workflow instance from its current step. The workflow will be reset to RUNNING status and execution will continue.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Workflow retry initiated successfully

Content-Type: `application/json`

```json
{
  "data": {
    "instance": {
      "id": "00000000-0000-4000-8000-000000000000",
      "definitionId": "00000000-0000-4000-8000-000000000000",
      "workflowId": "string",
      "version": 1,
      "status": "RUNNING",
      "outcome": null,
      "currentStepId": "string",
      "correlationKey": null,
      "metadata": null,
      "startedAt": "string",
      "completedAt": null,
      "pausedAt": null,
      "cancelledAt": null,
      "errorMessage": null,
      "errorDetails": null,
      "pendingTransition": null,
      "retryCount": 1,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "deletedAt": null
    },
    "execution": {
      "status": "RUNNING",
      "currentStep": "string",
      "events": [
        {
          "eventType": "string",
          "occurredAt": "string"
        }
      ],
      "executionTime": 1
    }
  },
  "message": "string"
}
```

**400** – Bad request - Workflow cannot be retried in its current status or with its current outcome, or execution error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Forbidden - Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/:id/retry" \
  -H "Accept: application/json"
```

## POST `/workflows/instances/{id}/signal`

Send signal to specific workflow

Sends a signal to a specific workflow instance waiting for a signal. The workflow must be in PAUSED status and waiting for the specified signal.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "signalName": "string"
}
```

### Responses

**200** – Signal sent successfully

Content-Type: `application/json`

```json
{
  "success": true,
  "message": "string"
}
```

**400** – Invalid request body or signal name mismatch

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Instance or definition not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Workflow not paused or not waiting for signal

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error or transition failed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/:id/signal" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"signalName\": \"string\"
}"
```

## POST `/workflows/instances/{id}/step-through`

Continue one step, or stop stepping

Releases exactly the step the instance is currently parked on and resumes execution, or clears step-through so the run finishes on its own. To abort the run, use the cancel endpoint.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "action": "continue"
}
```

### Responses

**200** – The run advanced

Content-Type: `application/json`

```json
{
  "data": {
    "instanceId": "string",
    "status": "string",
    "currentStep": "string",
    "stepThrough": null
  }
}
```

**400** – Not a step-through run, or malformed payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/00000000-0000-4000-8000-000000000000/step-through" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"action\": \"continue\"
}"
```

## GET `/workflows/instances/{id}/steps`

Get workflow instance step executions

List the step executions recorded for a workflow instance, including per-step input, output, error payload, duration and attempt count.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| limit | query | any | Optional |
| offset | query | any | Optional |

### Responses

**200** – List of step executions

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
      "branchInstanceId": null,
      "stepId": "string",
      "stepName": "string",
      "stepType": "string",
      "status": "string",
      "inputData": null,
      "outputData": null,
      "errorData": null,
      "enteredAt": null,
      "exitedAt": null,
      "executionTimeMs": null,
      "retryCount": 1
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/instances/:id/steps?limit=100&offset=0" \
  -H "Accept: application/json"
```

## GET `/workflows/instances/{id}/would-do`

Get a dry run's "Would do" report

List every side effect a dry run suppressed, in execution order: simulated activities with their would-do output, activity types that refused simulation and stopped the run, user tasks that were not raised, and business rules whose action arm was withheld. A real (non-dry) run answers with an empty report.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |
| limit | query | any | Optional |
| offset | query | any | Optional |

### Responses

**200** – The would-do report

Content-Type: `application/json`

```json
{
  "isDryRun": true,
  "entries": [
    {
      "id": "string",
      "kind": "activity",
      "severity": "error",
      "stepId": null,
      "occurredAt": "string",
      "subject": "string",
      "detail": {}
    }
  ],
  "stoppedByRefusal": true,
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Workflow instance not found

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/instances/:id/would-do" \
  -H "Accept: application/json"
```

## POST `/workflows/instances/bulk-replay`

Bulk retry or cancel workflow instances

Queue a bulk retry or cancel over the failure queue. Work runs in a queue worker and reports through the progress module; the response returns the progress job id immediately.

**Tags:** Workflows

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "action": "retry",
  "ids": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
```

### Responses

**202** – Bulk replay queued

Content-Type: `application/json`

```json
{
  "ok": true,
  "progressJobId": null,
  "message": "string"
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "ok": true,
  "progressJobId": null,
  "message": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "ok": true,
  "progressJobId": null,
  "message": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "ok": true,
  "progressJobId": null,
  "message": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "ok": true,
  "progressJobId": null,
  "message": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/bulk-replay" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"action\": \"retry\",
  \"ids\": [
    \"00000000-0000-4000-8000-000000000000\"
  ]
}"
```

## GET `/workflows/instances/failure-queue`

List the workflow failure queue

Triage list of instances parked by a failure-queue error directive together with FAILED instances, plus normalized error groups so a batch of similar failures reads as one row.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| workflowId | query | any | Optional |
| errorGroup | query | any | Optional. Narrow the list to one normalized error group key. |
| limit | query | any | Optional |
| offset | query | any | Optional |

### Responses

**200** – Failure queue

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "definitionId": "00000000-0000-4000-8000-000000000000",
      "workflowId": "string",
      "version": 1,
      "status": "RUNNING",
      "outcome": null,
      "currentStepId": "string",
      "correlationKey": null,
      "metadata": null,
      "startedAt": "string",
      "completedAt": null,
      "pausedAt": null,
      "cancelledAt": null,
      "errorMessage": null,
      "errorDetails": null,
      "pendingTransition": null,
      "retryCount": 1,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "deletedAt": null
    }
  ],
  "groups": [
    {
      "key": "string",
      "label": "string",
      "count": 1,
      "workflowIds": [
        "string"
      ],
      "instanceIds": [
        "00000000-0000-4000-8000-000000000000"
      ]
    }
  ],
  "grouping": {
    "scannedCount": 1,
    "scanLimit": 1,
    "truncated": true
  },
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  }
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/instances/failure-queue?limit=50&offset=0" \
  -H "Accept: application/json"
```

## POST `/workflows/instances/validate-start`

Validate if workflow can be started

Evaluates pre-conditions defined on the START step and returns validation errors with localized messages if any fail. Returns canStart: true/false with details.

**Tags:** Workflows

### Request Body

Content-Type: `application/json`

```json
{
  "workflowId": "string"
}
```

### Responses

**200** – Validation result (canStart, errors, validatedRules)

Content-Type: `application/json`

```json
{
  "canStart": true,
  "workflowId": "string"
}
```

**400** – Invalid request body or missing context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/instances/validate-start" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"workflowId\": \"string\"
}"
```

## GET `/workflows/metrics/definitions`

Read per-definition workflow operational KPIs

Batch KPI read for the named workflow ids over a sliding window: runs started, terminal runs by outcome, success rate, run-duration p50/p95 and task SLA hit-rate. Dry runs are excluded from every figure. Served from the precomputed rollup when one is fresh, recomputed live otherwise; each item reports which.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| window | query | any | Optional. Sliding window length. |
| workflowIds | query | any | Required. Comma-separated logical workflow ids, at most 50 per request. |

### Responses

**200** – Per-definition metrics

Content-Type: `application/json`

```json
{
  "data": [
    {
      "workflowId": "string",
      "window": "24h",
      "windowStart": "string",
      "windowEnd": "string",
      "computedAt": "string",
      "source": "rollup",
      "metrics": {
        "runsStarted": 1,
        "runsTerminal": 1,
        "runsCompleted": 1,
        "runsFailed": 1,
        "runsCancelled": 1,
        "successRate": null,
        "durationSampleCount": 1,
        "avgDurationMs": null,
        "p50DurationMs": null,
        "p95DurationMs": null,
        "tasksWithDeadline": 1,
        "tasksMetDeadline": 1,
        "taskSlaHitRate": null
      }
    }
  ]
}
```

**400** – Invalid query or missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/metrics/definitions?window=7d&workflowIds=string" \
  -H "Accept: application/json"
```

## GET `/workflows/portal/tasks`

List the portal principal's tasks

Returns the customer-assigned tasks this portal principal may see. A portal admin additionally sees their company members' tasks but may not act on them. Tasks with no entity bindings are never portal-visible.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| status | query | any | Optional. Filter by status (comma-separated for multiple) |
| page | query | any | Optional. Page number |
| pageSize | query | any | Optional. Rows per page (max 100) |

### Responses

**200** – Portal task list

Content-Type: `application/json`

```json
{
  "ok": true,
  "tasks": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
      "stepInstanceId": "00000000-0000-4000-8000-000000000000",
      "branchInstanceId": null,
      "taskName": "string",
      "description": null,
      "status": "PENDING",
      "formSchema": null,
      "formData": null,
      "assignedTo": null,
      "assigneeKind": "user",
      "assignedToRoles": null,
      "entityTypes": null,
      "claimedBy": null,
      "claimedAt": null,
      "dueDate": null,
      "escalatedAt": null,
      "escalatedTo": null,
      "completedBy": null,
      "completedAt": null,
      "comments": null,
      "reassignedBy": null,
      "reassignedAt": null,
      "reassignReason": null,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "kind": "user_task",
      "proposalId": null,
      "priority": null,
      "entityBindings": null
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 1,
    "total": 1,
    "totalPages": 1
  }
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions or no company association

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/portal/tasks?page=1&pageSize=25" \
  -H "Accept: application/json"
```

## GET `/workflows/portal/tasks/{id}`

Read one portal task

Returns a single customer-assigned task the portal principal owns. Every refusal — foreign tenant, another customer, an unbound task, a nonexistent id — is the same 404.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Portal task

Content-Type: `application/json`

```json
{
  "ok": true,
  "task": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
    "stepInstanceId": "00000000-0000-4000-8000-000000000000",
    "branchInstanceId": null,
    "taskName": "string",
    "description": null,
    "status": "PENDING",
    "formSchema": null,
    "formData": null,
    "assignedTo": null,
    "assigneeKind": "user",
    "assignedToRoles": null,
    "entityTypes": null,
    "claimedBy": null,
    "claimedAt": null,
    "dueDate": null,
    "escalatedAt": null,
    "escalatedTo": null,
    "completedBy": null,
    "completedAt": null,
    "comments": null,
    "reassignedBy": null,
    "reassignedAt": null,
    "reassignReason": null,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string",
    "kind": "user_task",
    "proposalId": null,
    "priority": null,
    "entityBindings": null
  },
  "decisions": [
    {
      "id": "string",
      "label": "string",
      "transitionId": "string"
    }
  ],
  "formKey": null,
  "canComplete": true
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions or no company association

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Task not found

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/portal/tasks/:id" \
  -H "Accept: application/json"
```

## POST `/workflows/portal/tasks/{id}/complete`

Complete a portal task

Completes a customer-assigned task and resumes the workflow. Only the assignee may complete; a portal admin who can read a company member's task is refused.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "formData": {}
}
```

### Responses

**200** – Task completed

Content-Type: `application/json`

```json
{
  "ok": true,
  "task": null
}
```

**400** – Invalid request body or form data

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**401** – Authentication required

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**403** – Insufficient permissions or no company association

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**404** – Task not found or not actionable by this principal

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "ok": false,
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/portal/tasks/:id/complete" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"formData\": {}
}"
```

## GET `/workflows/rule-usage`

List workflows referencing a business rule

Returns the workflow definitions whose START pre-conditions or transition pre/post-conditions reference the given business rule.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| ruleId | query | any | Required |

### Responses

**200** – Usage references

Content-Type: `application/json`

```json
{
  "ruleId": "ORDER_ABOVE_LIMIT",
  "workflowCount": 1,
  "references": [
    {
      "workflowId": "order-approval",
      "version": 2,
      "kind": "transitionPreCondition",
      "locationId": "e_start_review"
    }
  ]
}
```

**400** – Invalid query parameters

Content-Type: `application/json`

```json
{
  "error": "Invalid query parameters"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "Unauthorized"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/rule-usage?ruleId=string" \
  -H "Accept: application/json"
```

## POST `/workflows/signals`

Send signal to workflows by correlation key

Sends a signal to all workflow instances waiting for the specified signal that match the correlation key. Returns the count of workflows that received the signal.

**Tags:** Workflows

### Request Body

Content-Type: `application/json`

```json
{
  "correlationKey": "string",
  "signalName": "string"
}
```

### Responses

**200** – Signal sent to matching workflows

Content-Type: `application/json`

```json
{
  "success": true,
  "message": "string",
  "count": 1
}
```

**400** – Missing tenant or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/signals" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"correlationKey\": \"string\",
  \"signalName\": \"string\"
}"
```

## GET `/workflows/task-settings`

Get tenant task-permission settings

Returns whether the business-context task-permission model (spec §6.4) is enabled for the tenant. Defaults to true.

**Tags:** Workflows

**Requires authentication.**

### Responses

**200** – Current settings

Content-Type: `application/json`

```json
{
  "taskPermissionsBusinessContext": true
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/task-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>"
```

## PUT `/workflows/task-settings`

Update tenant task-permission settings

Sets the tenant-scoped opt-out. Setting it to false restores the pre-6.4 READ filter on the task list, task detail and work inbox; it never affects claiming, completing, tenant/organization scoping or the portal task routes.

**Tags:** Workflows

**Requires authentication.**

### Request Body

Content-Type: `application/json`

```json
{
  "taskPermissionsBusinessContext": true
}
```

### Responses

**200** – Updated settings

Content-Type: `application/json`

```json
{
  "taskPermissionsBusinessContext": true,
  "ok": true
}
```

**400** – Invalid payload

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Missing authentication

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**503** – Settings storage unavailable

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X PUT "https://makeitflow.90210.pl/api/workflows/task-settings" \
  -H "Accept: application/json" \
  -H "authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d "{
  \"taskPermissionsBusinessContext\": true
}"
```

## GET `/workflows/tasks`

List user tasks

Returns paginated list of user tasks with optional filtering by status, assignee, workflow instance, overdue, and myTasks flags.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| status | query | any | Optional. Filter by status (comma-separated for multiple: PENDING,IN_PROGRESS,COMPLETED,CANCELLED,ESCALATED) |
| assignedTo | query | any | Optional. Filter by assigned user ID |
| workflowInstanceId | query | any | Optional. Filter by workflow instance ID |
| overdue | query | any | Optional. Filter overdue tasks (true/false) |
| myTasks | query | any | Optional. Show only tasks assigned to or claimable by current user |
| limit | query | any | Optional. Number of results (max 100) |
| offset | query | any | Optional. Pagination offset |

### Responses

**200** – User tasks list with pagination

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
      "stepInstanceId": "00000000-0000-4000-8000-000000000000",
      "branchInstanceId": null,
      "taskName": "string",
      "description": null,
      "status": "PENDING",
      "formSchema": null,
      "formData": null,
      "assignedTo": null,
      "assigneeKind": "user",
      "assignedToRoles": null,
      "entityTypes": null,
      "claimedBy": null,
      "claimedAt": null,
      "dueDate": null,
      "escalatedAt": null,
      "escalatedTo": null,
      "completedBy": null,
      "completedAt": null,
      "comments": null,
      "reassignedBy": null,
      "reassignedAt": null,
      "reassignReason": null,
      "tenantId": "00000000-0000-4000-8000-000000000000",
      "organizationId": "00000000-0000-4000-8000-000000000000",
      "createdAt": "string",
      "updatedAt": "string",
      "kind": "user_task",
      "proposalId": null,
      "priority": null,
      "entityBindings": null
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  }
}
```

**400** – Invalid query parameters or missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/tasks?limit=50&offset=0" \
  -H "Accept: application/json"
```

## GET `/workflows/tasks/{id}`

Get task details

Returns complete details of a user task by ID.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – User task details

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
    "stepInstanceId": "00000000-0000-4000-8000-000000000000",
    "branchInstanceId": null,
    "taskName": "string",
    "description": null,
    "status": "PENDING",
    "formSchema": null,
    "formData": null,
    "assignedTo": null,
    "assigneeKind": "user",
    "assignedToRoles": null,
    "entityTypes": null,
    "claimedBy": null,
    "claimedAt": null,
    "dueDate": null,
    "escalatedAt": null,
    "escalatedTo": null,
    "completedBy": null,
    "completedAt": null,
    "comments": null,
    "reassignedBy": null,
    "reassignedAt": null,
    "reassignReason": null,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string",
    "kind": "user_task",
    "proposalId": null,
    "priority": null,
    "entityBindings": null,
    "stepId": null,
    "decisions": [
      {
        "id": "string",
        "label": "string",
        "transitionId": "string"
      }
    ],
    "canComplete": true,
    "canClaim": true,
    "canRelease": true,
    "canReassign": true,
    "actBlockedReason": null
  }
}
```

**400** – Missing tenant or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – The task is bound to an entity type the caller may not view. Returned only to callers holding workflows.tasks.view_all (or a superadmin), who already see the row in a list view; everyone else receives the generic 404.

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Task not found, or not visible to the caller

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/tasks/:id" \
  -H "Accept: application/json"
```

## POST `/workflows/tasks/{id}/claim`

Claim a task from role queue

Allows a user to claim a task assigned to their role(s). Once claimed, the task moves to IN_PROGRESS status and is assigned to the claiming user.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Task claimed successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
    "stepInstanceId": "00000000-0000-4000-8000-000000000000",
    "branchInstanceId": null,
    "taskName": "string",
    "description": null,
    "status": "PENDING",
    "formSchema": null,
    "formData": null,
    "assignedTo": null,
    "assigneeKind": "user",
    "assignedToRoles": null,
    "entityTypes": null,
    "claimedBy": null,
    "claimedAt": null,
    "dueDate": null,
    "escalatedAt": null,
    "escalatedTo": null,
    "completedBy": null,
    "completedAt": null,
    "comments": null,
    "reassignedBy": null,
    "reassignedAt": null,
    "reassignReason": null,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string"
  },
  "message": "string"
}
```

**400** – Missing tenant or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – The task is visible to the caller but is not theirs to act on — it has no assignee and no role queue, so it must be reassigned first (§6.4: administration widens seeing, never acting).

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Task not found, or not visible to the caller

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Task already claimed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/tasks/:id/claim" \
  -H "Accept: application/json"
```

## POST `/workflows/tasks/{id}/complete`

Complete a task with form data

Validates form data against task schema, updates task with completion data, merges form data into workflow context, and resumes workflow execution.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{
  "formData": {}
}
```

### Responses

**200** – Task completed successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
    "stepInstanceId": "00000000-0000-4000-8000-000000000000",
    "branchInstanceId": null,
    "taskName": "string",
    "description": null,
    "status": "PENDING",
    "formSchema": null,
    "formData": null,
    "assignedTo": null,
    "assigneeKind": "user",
    "assignedToRoles": null,
    "entityTypes": null,
    "claimedBy": null,
    "claimedAt": null,
    "dueDate": null,
    "escalatedAt": null,
    "escalatedTo": null,
    "completedBy": null,
    "completedAt": null,
    "comments": null,
    "reassignedBy": null,
    "reassignedAt": null,
    "reassignReason": null,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string"
  },
  "message": "string"
}
```

**400** – Invalid request body, validation failed, or missing context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – The task is visible to the caller but is not theirs to act on — it has no assignee and no role queue, so it must be reassigned first (§6.4: administration widens seeing, never acting).

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Task not found, or not visible to the caller

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Task already completed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/tasks/:id/complete" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{
  \"formData\": {}
}"
```

## POST `/workflows/tasks/{id}/reassign`

Move a task to another assignee or role queue

Records who moved the task, when, and why (`reassignedBy` / `reassignedAt` / `reassignReason`) and logs a `USER_TASK_REASSIGNED` workflow event. Requires `workflows.tasks.reassign`. An in-flight claim is released and an IN_PROGRESS task returns to PENDING; the status vocabulary is unchanged. Honours the optimistic-lock header `x-om-ext-optimistic-lock-expected-updated-at`.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Request Body

Content-Type: `application/json`

```json
{}
```

### Responses

**200** – Task reassigned successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
    "stepInstanceId": "00000000-0000-4000-8000-000000000000",
    "branchInstanceId": null,
    "taskName": "string",
    "description": null,
    "status": "PENDING",
    "formSchema": null,
    "formData": null,
    "assignedTo": null,
    "assigneeKind": "user",
    "assignedToRoles": null,
    "entityTypes": null,
    "claimedBy": null,
    "claimedAt": null,
    "dueDate": null,
    "escalatedAt": null,
    "escalatedTo": null,
    "completedBy": null,
    "completedAt": null,
    "comments": null,
    "reassignedBy": null,
    "reassignedAt": null,
    "reassignReason": null,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string",
    "kind": "user_task",
    "proposalId": null,
    "priority": null,
    "entityBindings": null
  },
  "message": "string"
}
```

**400** – Missing tenant/organization context, or a body naming neither an assignee nor a role queue

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Visible to the caller but refused by the entity gate, with the blocking entity type named

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Task not found, or not visible to the caller

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Task is in a terminal status, or the record changed since it was loaded (optimistic lock)

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/tasks/:id/reassign" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{}"
```

## POST `/workflows/tasks/{id}/unclaim`

Release a claimed task back to its role queue

Clears the caller's claim and returns the task to PENDING so another holder of the queued role can pick it up. Refused when the task is claimed by somebody else or is no longer in progress.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| id | path | any | Required |

### Responses

**200** – Task released successfully

Content-Type: `application/json`

```json
{
  "data": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workflowInstanceId": "00000000-0000-4000-8000-000000000000",
    "stepInstanceId": "00000000-0000-4000-8000-000000000000",
    "branchInstanceId": null,
    "taskName": "string",
    "description": null,
    "status": "PENDING",
    "formSchema": null,
    "formData": null,
    "assignedTo": null,
    "assigneeKind": "user",
    "assignedToRoles": null,
    "entityTypes": null,
    "claimedBy": null,
    "claimedAt": null,
    "dueDate": null,
    "escalatedAt": null,
    "escalatedTo": null,
    "completedBy": null,
    "completedAt": null,
    "comments": null,
    "reassignedBy": null,
    "reassignedAt": null,
    "reassignReason": null,
    "tenantId": "00000000-0000-4000-8000-000000000000",
    "organizationId": "00000000-0000-4000-8000-000000000000",
    "createdAt": "string",
    "updatedAt": "string"
  },
  "message": "string"
}
```

**400** – Missing tenant or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – The task is visible to the caller but is not theirs to act on — it has no assignee and no role queue, so it must be reassigned first (§6.4: administration widens seeing, never acting).

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**404** – Task not found, not visible to the caller, or not claimed

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**409** – Task claimed by another user

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/tasks/:id/unclaim" \
  -H "Accept: application/json"
```

## GET `/workflows/templates`

List seeded workflow templates

Returns the shipped workflow template gallery: metadata (id, i18n name/description keys, category, icon) plus the complete workflow definition each template seeds.

**Tags:** Workflows

### Responses

**200** – Available workflow templates

Content-Type: `application/json`

```json
{
  "items": [
    {
      "id": "string",
      "nameKey": "string",
      "descriptionKey": "string",
      "category": "string",
      "icon": "string",
      "definition": {
        "steps": [
          {
            "stepId": "string",
            "stepName": "string",
            "stepType": "START"
          }
        ],
        "transitions": [
          {
            "transitionId": "string",
            "fromStepId": "string",
            "toStepId": "string",
            "trigger": "auto",
            "condition": null,
            "continueOnActivityFailure": false,
            "priority": 0
          }
        ]
      }
    }
  ]
}
```

**400** – Missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**403** – Insufficient permissions

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/templates" \
  -H "Accept: application/json"
```

## GET `/workflows/work-inbox`

List work items across every registered source

Merges every registered work-inbox source (workflow user tasks, plus any module that registers a provider) into one queue, filtered by kind/module/entity type/role/priority/status/overdue and ordered by priority, then due date, then age.

**Tags:** Workflows

### Parameters
| Name | Location | Type | Description |
| --- | --- | --- | --- |
| kind | query | any | Optional. Filter by source kind (comma-separated) |
| module | query | any | Optional. Filter by owning module id (comma-separated) |
| entityType | query | any | Optional. Filter by bound entity type (comma-separated) |
| role | query | any | Optional. Filter by queued role (comma-separated) |
| priority | query | any | Optional. Filter by priority (comma-separated: extreme,high,medium,low) |
| status | query | any | Optional. Filter by status (comma-separated) |
| overdue | query | any | Optional. Only items past their due date |
| myWork | query | any | Optional. Only items assigned to, claimed by, or queued to a role of the caller |
| assignedTo | query | any | Optional. Filter by assignee |
| workflowInstanceId | query | any | Optional. Filter by workflow instance |
| limit | query | any | Optional. Number of results (max 100) |
| offset | query | any | Optional. Pagination offset |

### Responses

**200** – Merged work items with pagination

Content-Type: `application/json`

```json
{
  "data": [
    {
      "id": "string",
      "kind": "string",
      "moduleId": "string",
      "title": "string",
      "description": null,
      "status": "string",
      "priority": null,
      "dueDate": null,
      "overdue": true,
      "createdAt": "string",
      "updatedAt": "string",
      "assignedTo": null,
      "assignedToRoles": null,
      "claimedBy": null,
      "entityTypes": [
        "string"
      ],
      "entityBindings": [
        {
          "entityType": "string",
          "entityId": "string",
          "label": null
        }
      ],
      "detailHref": null,
      "actions": [
        {
          "id": "string",
          "labelKey": "string",
          "endpoint": "string",
          "appliesTo": "claimable"
        }
      ]
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 1,
    "offset": 1,
    "hasMore": true
  },
  "meta": {
    "kinds": [
      "string"
    ],
    "degradedKinds": [
      "string"
    ]
  }
}
```

**400** – Missing tenant context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X GET "https://makeitflow.90210.pl/api/workflows/work-inbox?limit=50&offset=0" \
  -H "Accept: application/json"
```

## POST `/workflows/work-inbox/next`

Claim the top claimable item from the work inbox

Walks the caller's claimable queue in inbox order and claims the first item it wins. The claim is a conditional update, so concurrent callers never receive the same item — a caller that loses the race moves on to the next candidate. Returns null data when nothing is claimable.

**Tags:** Workflows

### Responses

**200** – The claimed item, or null when nothing was claimable

Content-Type: `application/json`

```json
{
  "data": null,
  "message": "string"
}
```

**400** – Missing tenant or organization context

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**401** – Unauthorized

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

**500** – Internal server error

Content-Type: `application/json`

```json
{
  "error": "string"
}
```

### Example

```bash
curl -X POST "https://makeitflow.90210.pl/api/workflows/work-inbox/next" \
  -H "Accept: application/json"
```