# QAction REST API > QAction is a Full Lifecycle Work Management Platform. This file helps AI assistants understand the API's patterns and conventions. ## Documentation - OpenAPI Spec: /openapi.yaml (machine-readable, full endpoint details) - Migration Guide: /migrations/legacy-jars-to-v1.md (detailed examples) - Interactive Docs: https://developers.qflow.com ## Base URL ``` https://{server}/api/v1/{resource} ``` ## Authentication All endpoints require Bearer token authentication: ``` Authorization: Bearer {token} ``` Tokens obtained via: - `POST /authentication/login` with X-API-Key and X-Client-Id headers - `POST /authentication/impersonate` for admin impersonation scenarios ## Core Concepts ### Custom Objects (IMPORTANT) QAction uses a **generic object model** where business entities are "Custom Objects" with dynamic fields. This is the most common source of confusion. **Object types are path parameters, not fixed schemas:** - `/object/QPerson/{id}` - Person object - `/object/Obligation/{id}` - Obligation object - `/object/EntityCustomer/{id}` - Customer/Borrower object - `/object/{AnyCustomType}/{id}` - Any configured object type **Response structure:** ```json { "id": "uuid", "type": "Obligation", "indexValues": [ { "name": "CDMObligationNumber", "value": "12345678" }, { "name": "ObligationAmount", "value": 750000.00 }, { "name": "Status", "value": "APPROVED" } ] } ``` The `indexValues` array contains all the object's fields. Field names vary by object type configuration. ### IndexValue vs QueryValue **IndexValue** - Used for CREATE and UPDATE operations: ```json [ { "name": "fieldName", "value": "fieldValue" }, { "name": "dateField", "value": "2025-01-15", "type": "DATE" }, { "name": "numericField", "value": 42 } ] ``` Types: `PRIMITIVE` (default), `DATE` **QueryValue** - Used for SEARCH operations: ```json [ { "name": "status", "value": "ACTIVE", "type": "PRIMITIVE" }, { "name": "createDate", "value": {"from": "2025-01-01", "to": "2025-12-31"}, "type": "DATE_RANGE" }, { "name": "description", "value": {"text": "invoice", "exactMatch": true}, "type": "TEXT_QUERY" } ] ``` Types: `PRIMITIVE`, `DATE`, `DATE_RANGE`, `TEXT_QUERY`, `TEXT_QUERY_LIST` ### Common Patterns **Search for objects:** ```http POST /object/{type}/search?pageSize=50&pageNumber=0 Content-Type: application/json [ { "name": "externalId", "value": "12345" } ] ``` **Create object:** ```http POST /object/{type} Content-Type: application/json [ { "name": "field1", "value": "value1" }, { "name": "field2", "value": 123 } ] ``` **Update object (partial):** ```http PATCH /object/{type}/{id} Content-Type: application/json [ { "name": "fieldToUpdate", "value": "newValue" } ] ``` **Get by ID:** ```http GET /object/{type}/{id} ``` ## Pagination All list endpoints use 0-indexed pagination: ``` ?pageSize=50&pageNumber=0 ``` - `pageNumber` starts at 0 (first page) - Default `pageSize` varies by endpoint Response includes pagination metadata: ```json { "data": [...], "pagination": { "pageNumber": 0, "pageSize": 50, "totalItems": 1234, "totalPages": 25 } } ``` ## Date Handling Dates can be provided in multiple formats: **For IndexValue (create/update):** - ISO date: `"2025-01-15"` - ISO datetime with timezone: `"2025-01-15T10:30:00.000-05:00"` - Epoch milliseconds: `1704067200000` **For QueryValue (search):** - Simple date: `"2025-01-15"` with type `DATE` - Date range: `{"from": "2025-01-01", "to": "2025-12-31"}` with type `DATE_RANGE` - Either `from` or `to` can be omitted for open-ended ranges ## Key Endpoints ### Documents | Method | Endpoint | Description | |--------|----------|-------------| | POST | /document | Upload document (multipart/form-data) | | GET | /document/{id} | Get document metadata | | GET | /document/{id}/download | Download document content | | PUT | /document/{id}/update | Update document metadata | | POST | /document/query | Search documents | | DELETE | /document/{id} | Delete document | ### Workflows | Method | Endpoint | Description | |--------|----------|-------------| | GET | /workflow/inbox | Get user's tasks | | GET | /workflow/task/{id} | Get task details | | POST | /workflow/task/{id}/start | Start working on task | | POST | /workflow/task/{id}/complete/{actionId} | Complete task | | POST | /workflow/task/{id}/put-back | Return task to queue | | POST | /workflow/fire-event/{name}/{type} | Trigger workflow event | | GET | /workflow/folderSearch | Search workflow folders | ### Custom Objects | Method | Endpoint | Description | |--------|----------|-------------| | POST | /object/{type}/search | Search objects | | POST | /object/{type} | Create object | | GET | /object/{type}/{id} | Get object by ID | | PATCH | /object/{type}/{id} | Update object | | DELETE | /object/{type}/{id} | Delete object | ### Lists of Values (LOV) | Method | Endpoint | Description | |--------|----------|-------------| | GET | /lov | Get all LOVs | | GET | /lov/{id}/entry | Get LOV entries | ### Classification | Method | Endpoint | Description | |--------|----------|-------------| | GET | /classification | Get all classifications | | GET | /classification/{id} | Get classification details | | GET | /classification/{id}/document-types | Get document types | ## Error Responses ```json { "error": "Error message", "code": "ERROR_CODE", "details": {} } ``` | Status | Meaning | |--------|---------| | 400 | Bad request / validation error | | 401 | Missing or invalid authentication | | 403 | Insufficient permissions | | 404 | Resource not found | | 500 | Internal server error | ## Common Gotchas 1. **Search uses POST, not GET** - The `/search` endpoints use POST with a JSON body, not query parameters. 2. **Type parameter is required** - When working with custom objects, the type (e.g., "Obligation", "QPerson") must be in the URL path. 3. **Fields are in indexValues array** - Don't look for named properties on custom objects. All fields are in the `indexValues` array with `name` and `value` properties. 4. **Pagination is 0-indexed** - First page is `pageNumber=0`, not 1. 5. **QueryValue types matter** - For search operations, use the appropriate type (DATE_RANGE for date ranges, TEXT_QUERY for partial matching, etc.). 6. **PATCH for updates** - Use PATCH (not PUT) for partial updates to custom objects. 7. **Document uploads use multipart** - Document creation requires `multipart/form-data`, not JSON. 8. **UUID identifiers** - All entity IDs are UUIDs (e.g., "b6ad0118-6141-4073-8702-599a35df69aa"). ## Example: Complete Workflow ```bash # 1. Search for an obligation curl -X POST "https://server/api/v1/object/Obligation/search" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '[{"name": "CDMObligationNumber", "value": "12345678"}]' # 2. Update the obligation curl -X PATCH "https://server/api/v1/object/Obligation/{id}" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '[{"name": "Status", "value": "APPROVED"}]' # 3. Upload a document curl -X POST "https://server/api/v1/document" \ -H "Authorization: Bearer {token}" \ -F "file=@document.pdf" \ -F 'document={"classificationId":"uuid","documentTypeId":"uuid","indexValues":[{"name":"title","value":"Contract"}]}' # 4. Fire a workflow event curl -X POST "https://server/api/v1/workflow/fire-event/NewDocument/START" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '[{"name": "documentId", "value": "{docId}"}]' ``` ## Version Information - Current: v1 (stable) - Base path: /api/v1/