> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pool.day/llms.txt
> Use this file to discover all available pages before exploring further.

# Signals

> Get an event when the person saves something new that matches: a product, a concert, or a rule you write in plain words.

A signal says that a new capture matched a subscription: "saved a bag", "saved a concert". Signals are delivered inside your app. Forward them to your own server to act on them.

## Subscribe

```swift theme={null}
let grant = try await pool.authorization.requestAccess(
    AccessRequest(data: [.products, .music, .events], operations: [.observe], purpose: "Tell you when something you saved is back in stock")
)

// Every new capture where PoolKit finds a product.
for try await signal in pool.signals.subscribe(to: .saved(.product), using: grant) {
    send(signal.id, signal.thing?.name, signal.thing?.brand, signal.thing?.price, signal.capturedAt)
}

// Or a rule in plain words, matched like classify.
for try await signal in pool.signals.subscribe(rule: "songs or concerts", using: grant) {
    send(signal)
}
```

* `.saved(type)` fires for each new capture with a thing of that type. The grant has to cover the type.
* A rule is matched the way [classify](https://docs.pool.day/classify.md) matches it, with the same refusals and the same optional cloud assist. The default threshold is 0.6.
* Only captures taken after the subscription was first made count. A subscription never replays the library.

## What a signal holds

| Field | Meaning |
| - | - |
| `id` | Stable for one capture and one subscription. Use it to drop duplicates on your server. |
| `subscription` | `.saved(type)` or `.rule(text)` |
| `thing` | The strongest thing on the capture that the grant covers: `type`, `name`, and `brand`, `price`, `place`, `date` when PoolKit found them |
| `asset` | The capture |
| `probability` | How sure PoolKit is |
| `decidedBy` | `.onDevice` or `.cloud` |
| `evidenceIDs` | Pass to `evidence(id:using:)` to show why. See [Evidence](https://docs.pool.day/evidence.md). |
| `capturedAt`, `emittedAt` | When the capture was taken, and when the signal was made |

A signal says what was saved, with evidence. It never says what the person likes.

## Captures indexed in the background

With [background indexing](https://docs.pool.day/indexing.md) registered, PoolKit finds new captures while your app is closed. Their signals wait on the device until you pick them up.

```swift theme={null}
// At launch, or in your background task:
let missed = try await pool.signals.pending(.rule("songs or concerts"), using: grant)
upload(missed)
try await pool.signals.acknowledge(missed)
```

* A stream marks a signal as delivered when it yields it, so no signal arrives twice.
* `pending` returns undelivered signals, oldest first, and leaves them undelivered until you call `acknowledge`. Acknowledge after your server confirms.
* When a capture is deleted, its signals are deleted with it.

## Delivery to your server

In this version PoolKit does not call your server. Your app does, with whatever it chooses to send. Delivery from Pool by webhook comes with [Pool Connect](https://docs.pool.day/limits.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.