> For the complete documentation index, see [llms.txt](https://documentation.opencrvs.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.opencrvs.org/setup/3.-installation/3.2-set-up-your-own-country-configuration/3.2.9-countryconfig-apis-explained/4.2.9.1-configurable-workqueue-api.md).

# 4.2.9.1 Configurable workqueue API

### Workqueue endpoint – configuring queues with slugs & Elasticsearch queries

**Path (countryconfig repo)**\
`src/api/workqueue/`

The workqueue endpoint in the countryconfig service is responsible for returning the **list of workqueues** that the client should show, including:

* a **slug** (identifier),
* label/description (for the UI),
* and the **Elasticsearch query** that defines *which records appear in that queue*.

Everything is configured in:

```ts
src/api/workqueue/workqueueConfig.ts
```

and wired into user permissions via:

```ts
src/data-seeding/roles/roles.ts
```

At runtime, OpenCRVS Core uses these configs to:

1. Decide **which queues a user can see** (based on their role→queue slugs), and
2. Run the **Elasticsearch query** for each queue to fetch the records that should be listed there.

The queries themselves are built using the [**`QueryExpressions`**](https://github.com/opencrvs/opencrvs-core/blob/625cd2662a5101caac5a1f7b26a6c8ed77c27246/packages/commons/src/events/EventIndex.ts#L172) **DSL** from `EventIndex` in `opencrvs-core`, which compiles down to Elasticsearch queries.

***

### 1. What lives in `workqueueConfig.ts`

`workqueueConfig.ts` defines all available workqueues for your country. Conceptually it’s a list (or map) of objects, one per queue, along the lines of:

```ts
export const workqueueConfig = [
  {
    slug: 'draft',
    label: { ... },
    description: { ... },
    // optional: icon, sort, etc.
    query: <QueryExpression>
  },
  {
    slug: 'ready-for-review',
    label: { ... },
    query: <QueryExpression>
  },
  ...
]
```

Each entry represents **one queue** in the UI, such as:

* `draft`
* `in-progress`
* `ready-for-review`
* `requires-updates`
* `sent-for-approval`
* `ready-to-print`
* `ready-to-issue`
* etc.

The **slug** is the key thing:

* It’s how the **client** and **roles** refer to the queue.
* It’s what you reference in [`roles.ts`](https://roles.tshttps/github.com/opencrvs/opencrvs-countryconfig/blob/0fc50a9d21d2c7525e5b8e3b8f1cd7c0ca7a7328/src/data-seeding/roles/roles.ts#L30) when granting access.

The **query** is a **typed `QueryExpression`** that describes which events should appear in that queue, using the same status semantics as the product docs (In progress, Ready for review, Requires updates, Ready to print, Ready to issue, etc.). [documentation.opencrvs.org+1](https://documentation.opencrvs.org/product-specifications/workflow-management?utm_source=chatgpt.com)

***

### 2. How roles use workqueue slugs

The seeded roles in:

```ts
src/data-seeding/roles/roles.ts
```

include a mapping from **role → allowed workqueue slugs**.

Roughly:

```ts
{
  id: 'REGISTRATION_AGENT',
  // ...
  scopes: [
    // ...
    'workqueue[id=assigned-to-you|recent|requires-updates-self|sent-for-review]',
    // ...
  ]
}
```

This means:

* When a user logs in, their roles determine which **queue slugs** they can see.
* The client then asks the workqueue endpoint for definitions and filters them down to the ones the user is allowed to access.
* That’s why a Field Agent, Registration Agent and Registrar see **different queues** (even if some share the same underlying statuses).

So the flow is:

1. `roles.ts` says: “This role can see queues `A`, `B`, `C` …”
2. `workqueueConfig.ts` says: “Queue `A` means this label + this ES query, `B` means …”
3. The workqueue endpoint exposes that whole config to the UI & core.

***

### 3. The query: using `QueryExpressions` → Elasticsearch

The **query** field in each workqueue config is where the real power lives.

Instead of hand-writing Elasticsearch JSON, you use the **`QueryExpressions` DSL** from `opencrvs-core` (the same layer used for search & dedup queries).

Patterns you’ll typically see:

```ts
import { and, or, not, field, user } from '@opencrvs/events/EventIndex' // conceptually

export const draftQueue = {
  slug: 'draft',
  label: { ... },
  query: and(
    field('status').isEqualTo('IN_PROGRESS'),
    field('isDraft').isEqualTo(true),
    user('scope').has('record.declare.birth') // user-specific filtering
  )
}
```

The key ideas:

* **`field('...')`** refers to an indexed property of the event (e.g. status, event type, office, assigned user, timestamps).
* **Logical combinators** like `and`, `or`, `not` build complex boolean queries.
* **User-aware helpers** like `user('officeId')` or `user('primaryOfficeId')` can scope records to the current user’s office or jurisdiction.
* At runtime, these **QueryExpressions** are compiled into Elasticsearch queries against the **event index** (see `EventIndex.ts` in opencrvs-core).

This is how you implement things like:

* “Draft” → events with status `IN_PROGRESS` created by the current user.
* “Ready for review” → events with status `IN_REVIEW` or `VALIDATED` assigned to the user’s office.
* “Requires updates” → events with status `REQUIRES_UPDATES`.
* “Ready to print” → events with status `REGISTERED` with no certificates yet.

So **each queue is literally “just” an ES query** defined via this DSL.

### 4. Mental model

You can think of the **workqueue endpoint** as:

> “A country-specific list of *named Elasticsearch queries* (`slug` + `label` + `QueryExpression`) that define which records appear in each queue, and which queues each role can access.”

* **`workqueueConfig.ts`** → defines the queues and their queries.
* **`roles.ts`** → decides who can see which queues (by slug).
* **`EventIndex` / `QueryExpressions`** → turns those definitions into real ES queries over the event index.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.opencrvs.org/setup/3.-installation/3.2-set-up-your-own-country-configuration/3.2.9-countryconfig-apis-explained/4.2.9.1-configurable-workqueue-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
