# ai.subscriptions.policy.update

Approve explicit subscription connections and models for background tasks, or keep the existing API model route. The owner must also allow agent use. Unsupported or unavailable subscriptions fail without paid fallback. Administrators with human sign-in only.

`POST /api/v1/accounting/ai.subscriptions.policy.update`

Permissions: `accounting:read`, `accounting:write`, `accounting:admin` · Roles: admin · Idempotency key required · Send `expectedRevision`

Not available over MCP: Choosing and sharing a personal subscription is the signed-in person's explicit choice in Settings or the CLI, never an agent's delegation.

## Fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `allowPersonalChat` | boolean | Yes |  |
| `agents` | object | Yes |  |
| `agents.source` | "gateway" | Yes | Where the record came from. |
| `agents.modelId` | string or null | Yes |  |
| `agents.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `agents.source` | "subscription" | Yes | Where the record came from. |
| `agents.connectionId` | string (ID) | Yes | The ID of the related record. |
| `agents.modelId` | string | Yes | 1–160 characters; Matches ^[a-zA-Z0-9][a-zA-Z0-9_./:@+-]*$. |
| `agents.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides` | object | Yes | No other fields. |
| `overrides.emailReading` | object |  |  |
| `overrides.emailReading.source` | "gateway" | Yes | Where the record came from. |
| `overrides.emailReading.modelId` | string or null | Yes |  |
| `overrides.emailReading.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.emailReading.source` | "subscription" | Yes | Where the record came from. |
| `overrides.emailReading.connectionId` | string (ID) | Yes | The ID of the related record. |
| `overrides.emailReading.modelId` | string | Yes | 1–160 characters; Matches ^[a-zA-Z0-9][a-zA-Z0-9_./:@+-]*$. |
| `overrides.emailReading.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.emailChecking` | object |  |  |
| `overrides.emailChecking.source` | "gateway" | Yes | Where the record came from. |
| `overrides.emailChecking.modelId` | string or null | Yes |  |
| `overrides.emailChecking.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.emailChecking.source` | "subscription" | Yes | Where the record came from. |
| `overrides.emailChecking.connectionId` | string (ID) | Yes | The ID of the related record. |
| `overrides.emailChecking.modelId` | string | Yes | 1–160 characters; Matches ^[a-zA-Z0-9][a-zA-Z0-9_./:@+-]*$. |
| `overrides.emailChecking.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.secondOpinion` | object |  |  |
| `overrides.secondOpinion.source` | "gateway" | Yes | Where the record came from. |
| `overrides.secondOpinion.modelId` | string or null | Yes |  |
| `overrides.secondOpinion.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.secondOpinion.source` | "subscription" | Yes | Where the record came from. |
| `overrides.secondOpinion.connectionId` | string (ID) | Yes | The ID of the related record. |
| `overrides.secondOpinion.modelId` | string | Yes | 1–160 characters; Matches ^[a-zA-Z0-9][a-zA-Z0-9_./:@+-]*$. |
| `overrides.secondOpinion.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.vision` | object |  |  |
| `overrides.vision.source` | "gateway" | Yes | Where the record came from. |
| `overrides.vision.modelId` | string or null | Yes |  |
| `overrides.vision.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `overrides.vision.source` | "subscription" | Yes | Where the record came from. |
| `overrides.vision.connectionId` | string (ID) | Yes | The ID of the related record. |
| `overrides.vision.modelId` | string | Yes | 1–160 characters; Matches ^[a-zA-Z0-9][a-zA-Z0-9_./:@+-]*$. |
| `overrides.vision.effort` | enum or null | Yes | One of: `none`, `low`, `medium`, `high`, `xhigh`, `max`, `ultra`. |
| `expectedRevision` | integer | Yes | The record's current revision, from the last time you read it. If someone changed the record since, the request is refused with a conflict so you can reload and check before trying again. 0 to 9007199254740991. |
| `idempotencyKey` | string | Yes | Any unique text you generate once per intended change, so a retried request only happens once. Send it as the Idempotency-Key header instead if you prefer; if you send both they must match. 8–200 characters. |

## Example request

```bash
curl https://app.getoatmilk.com/api/v1/accounting/ai.subscriptions.policy.update \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "allowPersonalChat": true,
  "agents": {
    "source": "gateway",
    "modelId": "model_id",
    "effort": "none"
  },
  "overrides": {},
  "expectedRevision": 3
}'
```

Reference page: https://app.getoatmilk.com/docs/api/ai.subscriptions.policy.update
