# The web and keys

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

## m.fetch

```python
m.fetch(url, *, method='GET', headers=None, body=None, key=None, timeout=20)
```

One https request, made by your Ownbox.

Only to a host the owner allowed. `key` names a key the owner saved: your Ownbox attaches it, only for that key's own host, and the machine never sees it. A redirect is handed back, not followed. `body` is text, bytes, or a dict sent as JSON.

**Needs in machine.yaml:** `fetch: [host]`, and `keys: [...]` for a key

**Returns:** A response: `.status`, `.headers` (lower-case names), `.content` (bytes), `.text`, `.json()` and `.ok`.

Example (inside a job):

```python
try:
    r = m.fetch("https://api.example.com/v1/quotes", key="example")
    quotes = r.json() if r.ok else []
except sdk.BoxRefused as e:
    m.save_setting("last_fetch_error", e.code)
```

## m.keys_page

```python
m.keys_page
```

The owner's page for this machine's keys.

Where the owner enters a key the machine named in machine.yaml, and sets its monthly limit for `m.spend`. Link to it when a key is missing.

**Needs in machine.yaml:** Nothing

**Returns:** A path on the Ownbox.

Example (inside a job):

```python
m.save_setting("keys_at", m.keys_page)
```

## m.secret

```python
m.secret(name, *, label=None, help='')
```

**Always refused.** Never available to a custom machine.

Always refused `never_readable`. A machine never reads a key: name it on the request, `m.fetch(url, key=...)`.

