# The team and money

Part of the [Ownbox SDK reference](https://www.ownbox.io/sdk/reference.md).

## m.notify

```python
m.notify(member, text, *, key='notice')
```

Tell one member of the owner's team one thing.

`member` is a user id on the Ownbox, never an address: a page the machine draws is handed the person viewing it, with their `id`. The notice goes on their phone and by email in the next notice slot (morning or evening), once per key per slot, so a machine that asks twenty times in a morning tells them once. Put what must be seen every morning on the Morning Review instead. Never raises.

**Needs in machine.yaml:** Nothing

**Returns:** `{"status": "sent" | "skipped" | "refused", "code", "reason"}`. Decide on `code`: "not_a_member", "bad_text", "off", "outside_slot", "already_sent", "nobody", "all_failed", "error".

Example (inside a job):

```python
answer = m.notify(m.setting("who_to_tell", default=""), "Three quotes wait for a reply.", key="quotes_waiting")
```

## m.spend

```python
m.spend(vendor, units=1, *, key)
```

Record a paid unit of a service before the call that spends it.

For a service the machine holds a key for. It spends nothing until the owner sets a monthly limit for that key, next to the key on the machine's Keys page: until then the answer is `no_cap`. The limit is in the service's own units, per billing cycle. The same `key` is counted once, so a retry never pays twice. Never raises.

**Needs in machine.yaml:** `keys: [...]`, and the owner's monthly limit for that key

**Returns:** `{"status": "recorded" | "duplicate" | "refused", "code", "reason", "left"}`. Decide on `code`: "recorded", "duplicate", "no_cap", "over_cap", "not_granted", "bad_units", "bad_key". `left` is what this cycle's limit has left.

Example (inside a job):

```python
paid = m.spend("example", 1, key="lookup:41")
if paid.get("code") in ("recorded", "duplicate"):
    r = m.fetch("https://api.example.com/v1/lookup", key="example")
```

