# Search

search.messages, search.all and search.files with Slack's query modifiers, checking access for messages; files are searched by text without access checks.

`search.messages`, `search.all` and `search.files` answer a query the way Slack's search does, with its modifiers, over the workspace's messages and files. They take a user (`xoxp-`) token and answer a bot token `not_allowed_token_type`, as Slack does. Search as a seeded user for messages one person wrote in one channel, then try a bot token and an unknown modifier:

```bash
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"design_studio"}' -o /dev/null
curl -s "$RYSTIC_URL/api/search.messages" -H 'Authorization: Bearer xoxp-anything' -H 'X-Rystic-Actor: UWDC0000001' --data-urlencode 'query=in:#help from:<@UWDC0000022> shared drive' | jq -c '{ok, total: .messages.total}'
# -> {"ok":true,"total":2}
curl -s "$RYSTIC_URL/api/search.messages" -H 'Authorization: Bearer xoxp-anything' -H 'X-Rystic-Actor: UWDC0000001' --data-urlencode 'query=in:#help "shared drive" before:2026-03-01' | jq -c '{ok, total: .messages.total}'
# -> {"ok":true,"total":7}
curl -s "$RYSTIC_URL/api/search.messages" -H 'Authorization: Bearer xoxb-local' --data-urlencode 'query=drive' | jq -c .
# -> {"error":"not_allowed_token_type","ok":false}
curl -s "$RYSTIC_URL/api/search.messages" -H 'Authorization: Bearer xoxp-anything' -H 'X-Rystic-Actor: UWDC0000001' --data-urlencode 'query=in:#help nosuchmodifier:x' | jq -c '{ok, total: .messages.total}'
# -> {"ok":true,"total":0}
```

### What a caller can find

`search.messages` and `search.all` answer messages only from conversations the token's user can read: every public channel and the private channels, DMs and group DMs the user is in. `search.files` and the file results of `search.all` still answer every file. A thread reply's permalink ends in `?thread_ts=<the thread's ts>`.

### Modifiers

The messages of `search.messages` and `search.all` read Slack's search modifiers, as Slack does:

- `in:` names a channel (`#name`, `name`, `<#C…>`, `<#C…|name>`) or a DM (`<@U…>`, `@name`).
- `from:` names an author (`<@U…>`, `@name`, `name` or `me` for the token's user).
- `has:` takes `link`, `pin` or `reaction`.
- `before:`, `after:`, `on:` and `during:` name a date (`YYYY-MM-DD`, `YYYY/MM/DD`, `today`, `yesterday`, `YYYY-MM`, a month's name or `YYYY`) in the token's user's time zone, where `after:` leaves the named day out.

Bare words match whole words in any case and every word must match; `"a phrase"` keeps its order and `-` excludes a word or a modifier. `AND` and parentheses group, while `OR` is an ordinary word. Two `in:` or two `from:` terms match either one. Modifiers don't apply to files, so `search.files` and the file results of `search.all` match the whole query as text.

### Forgiving input

No query is refused: an unknown modifier or an unreadable date matches nothing, and an unknown `has:` value is ignored. Unbalanced brackets or quotes are forgiven. `highlight=true` wraps each searched word in U+E000 and U+E001, never a modifier.

### Not modeled

`has::emoji:` is ignored, where Slack narrows to that reaction. The unrelated low-score matches Slack appends to a query holding an unknown term are not returned.

---

Source: https://www.rystic.ai/docs/simulators/slack/features/search · Markdown: https://www.rystic.ai/docs/simulators/slack/features/search.md
