# Add, update or remove a position

> Everything the editor does: { "op": "add" | "update" | "remove", "position": {...} }. A refusal says what to fix, in words.

Source: https://firmtape.com/docs/developers/orders/positions-change

Everything the editor does: `{ "op": "add" | "update" | "remove", "position": {...} }`. A refusal says what to fix, in words.

`POST /api/positions`

Plan ORDERS · Key scope orders · Limit 20,000 calls a day on Orders API, 100,000 on Orders Team, per account · Version 1.0.0 · Since 2026-10-04

**This endpoint serves:** [ORDERS: POSITIONS panel and editor](https://firmtape.com/docs/orders#positions-panel), [ORDERS: Conditions and the not counted list](https://firmtape.com/docs/orders#positions-conditions). **Plan:** [ORDERS](https://firmtape.com/features/orders). Free on every finished session. Today's ledger, live, and the live POSITIONS check are the ORDERS plan.

## Body

| Field | Meaning | Unit |
| --- | --- | --- |
| `op` (add \| update \| remove) | `add`, `update` or `remove`. |  |
| `position` (object) | A short options position: `kind` (`condor`, `strangle`, `put_spread`, `call_spread`), `legs` (`lp`, `sp`, `sc`, `lc`, rising), `entry` (`HH:MM` ET) and optionally `conditions`, `label`, `alert` (`{ channel: telegram \| email \| webhook \| off, url, before }`) and `session`. |  |
| `position.id` (string) | `p_...`, given by `add`. |  |
| `position.kind` (condor \| strangle \| put_spread \| call_spread) | `condor`, `strangle`, `put_spread` or `call_spread`. |  |
| `position.legs` (object) | The strikes, rising, as the kind needs them. |  |
| `position.legs.lp` (number) | Long put. |  |
| `position.legs.sp` (number) | Short put. |  |
| `position.legs.sc` (number) | Short call. |  |
| `position.legs.lc` (number) | Long call. |  |
| `position.entry` (string) | Entry minute, `HH:MM` ET. |  |
| `position.conditions` (array) | `[{ id, on, threshold }]`: which conditions count, and where they switch on. |  |
| `position.label` (object) | `{ caution, skip }`: how many conditions on make each label. |  |
| `position.alert` (object) | `{ channel: telegram \| email \| webhook \| off, url, before }`: where the alerts go and how many minutes before entry they start. |  |
| `position.session` (string) | `YYYY-MM-DD`: the session the strikes were set against. |  |

## Response

`{ ok: true, ... }`; `add` answers the new `id`.

| Field | Meaning | Unit |
| --- | --- | --- |
| `ok` (boolean) | Done. |  |

## Errors

| Status | Code | What to do |
| --- | --- | --- |
| 400 | `bad_json`, `bad_op`, `invalid` | The body cannot be used; `message` says why. Send `Content-Type: application/json` and a JSON object. |
| 401 | `no_key` | No key, or a revoked one. Send `Authorization: Bearer <key>` with a key of the product's scope. |
| 403 | `plan` | The account is not on the Orders API or Team plan. Move to the Orders API or Team plan. |
| 404 | `not_found` | No position with this id. Check the path or the id. |
| 405 | `method` | GET or POST only. Send a GET or a POST. |
| 429 | `rate` | The day's calls are spent. Wait for midnight ET, when the count resets. |

## Request

```sh
curl -X POST \
  -H "Authorization: Bearer $FIRMTAPE_ORDERS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"op":"add","position":{"kind":"condor","legs":{"lp":7690,"sp":7700,"sc":7745,"lc":7755},"entry":"13:45","alert":{"channel":"webhook","url":"https://your.server/hook","before":10}}}' \
  "https://firmtape.com/api/positions"
```

```python
import os, requests

H = {"Authorization": f"Bearer {os.environ['FIRMTAPE_ORDERS_KEY']}"}
r = requests.post("https://firmtape.com/api/positions", headers=H, json={"op":"add","position":{"kind":"condor","legs":{"lp":7690,"sp":7700,"sc":7745,"lc":7755},"entry":"13:45","alert":{"channel":"webhook","url":"https://your.server/hook","before":10}}})
print(r.status_code, r.text[:500])
```

```js
const r = await fetch("https://firmtape.com/api/positions", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.FIRMTAPE_ORDERS_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({"op":"add","position":{"kind":"condor","legs":{"lp":7690,"sp":7700,"sc":7745,"lc":7755},"entry":"13:45","alert":{"channel":"webhook","url":"https://your.server/hook","before":10}}}),
});
console.log(r.status, await r.text());
```

## Example response

```json
{
  "error": {
    "code": "bad_json",
    "message": "The body is not JSON."
  }
}
```

## Changes

- 2026-10-04: Added.
