# Portal

URL: /business/nouns/portal · Id: `noun:portal`

> A Portal is the signed-in part of a Site where each Customer orders, tracks delivery, accepts work, and pays, seeing only their own records.

A Portal is the signed-in part of a [Site](/business/nouns/site) where each [Customer](/business/nouns/customer) orders, tracks delivery, accepts work, and pays, seeing only their own records.

## Properties
| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | `string` | Yes | Where it is mounted on the Site, `/portal` by default. |
| `tools` | `string[]` | No | Developer tools a keyed Offer adds: `keys`, `usage`, `requests`, `watches`, `version` and `testMode`. |

## Object
```json
{
  "$id": "https://api.sb/tutorloop.com/portals/portal_1",
  "$type": "Portal",
  "path": "/",
  "tools": [
    "keys"
  ]
}
```

## Relationships
- <a id="rel-included-in"></a>A Portal **is included in** one [Site](/business/nouns/site): a [Site](/business/nouns/site) includes one Portal, the signed-in part where each [Customer](/business/nouns/customer) sees only their own records. `includedIn`, inverse [`includes`](/business/nouns/site#rel-includes).
- <a id="rel-serves"></a>A Portal **serves** many [Customers](/business/nouns/customer): [Customers](/business/nouns/customer) sign in to a Portal to order, track delivery, accept work, and pay. `serves`, inverse [`signsInto`](/business/nouns/customer#rel-signs-into).

## Verbs
| Verb | Description | Subject | Event | Class |
| --- | --- | --- | --- | --- |
| <a id="create"></a>[Portal.create](/business/nouns/portal/create) | Creates a Portal. Inherited from [Noun](/business/nouns/noun). | None. | `Portal.created` | Two-way: `try`, `send`, `do` |
| <a id="get"></a>[Portal.get](/business/nouns/portal/get) | Returns one Portal by id. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="list"></a>[Portal.list](/business/nouns/portal/list) | Returns Portals, newest first, one page at a time. Inherited from [Noun](/business/nouns/noun). | None. | None. | Read: `try`, `do` |
| <a id="update"></a>[Portal.update](/business/nouns/portal/update) | Changes the given properties of a Portal. Inherited from [Noun](/business/nouns/noun). | None. | `Portal.updated` | Two-way: `try`, `send`, `do` |
| <a id="delete"></a>[Portal.delete](/business/nouns/portal/delete) | Deletes a Portal; its history is kept. Inherited from [Noun](/business/nouns/noun). | None. | `Portal.deleted` | One-way: `send`, `do` |

## Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.

| Operation | `owner` | `admin` | `member` | `viewer` |
| --- | --- | --- | --- | --- |
| `Portal.create` | Yes | Yes | Yes | No |
| `Portal.get` | Yes | Yes | Yes | Yes |
| `Portal.list` | Yes | Yes | Yes | Yes |
| `Portal.update` | Yes | Yes | Yes | No |
| `Portal.delete` | Yes | Yes | Yes | No |

## Call it

**Ask**

```text
Add a portal to QuietCopy.
```

**API**

```bash
curl -X POST https://api.sb/quietcopy.com/portals \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"path":"/"}'
```

```json
{
  "api": "https://api.sb/quietcopy.com",
  "portal": {
    "$id": "https://api.sb/quietcopy.com/portals/portal_1",
    "$type": "Portal",
    "path": "/"
  },
  "action": {
    "$id": "https://api.sb/quietcopy.com/actions/action_1",
    "operation": "Portal.create",
    "status": "done"
  },
  "links": {
    "self": "https://api.sb/quietcopy.com/actions/action_1"
  }
}
```

**SDK**

```ts
import { $ } from 'startup-builder'

const portal = await $.Portal.create({ path: '/' })
```

**CLI**

```bash
npx startup-builder do Portal.create --json '{"path":"/"}'
```

**MCP**

```json
{
  "name": "do",
  "arguments": {
    "code": "return await $.Portal.create({ path: '/' })"
  }
}
```

## Example
A client of a bookkeeping service signs in at `/portal`, accepts last month's close, uploads two receipts, and pays the [Invoice](/business/nouns/invoice). She sees only her own records.