Developers › API reference › Orders
POST /api/v1/orders/{id}/amend
Amend quantity or limit (compliance re-checked; If-Match).
- Scope
orders:write - Idempotency-Key
- If-Match
- operationId
ordersAmend
The token needs the scope orders:write, and the person or service account behind it needs the matching privileges and account permissions, exactly as on the screens. See Scopes.
Idempotency-Key. Send a unique Idempotency-Key (up to 255 characters, e.g. a UUID) with every POST. Retrying with the same key and body replays the first answer for 24 hours, so a timeout never creates a second order; the same key with a different body is refused (idempotency_key_reused).
If-Match. Send If-Match with the ETag of your latest GET. If someone changed the resource since, you get 412 precondition_failed and nothing changes: GET it again, re-apply your change and retry.
Request
POST /api/v1/orders/{id}/amend
Path parameters
| Name | Description | Example |
|---|---|---|
id | The id of the order. | 5301 |
Headers
| Header | Required | Value |
|---|---|---|
Authorization | yes | Bearer <token>: an OAuth access token (vat_…) or a personal access token (vpt_…). Get a token |
Idempotency-Key | yes | A unique string up to 255 characters (a UUID). Idempotency |
If-Match | yes | The ETag of your latest GET of this resource. ETags |
Content-Type | yes | application/json |
Body: OrderAmend
| Field | Type | Required | Description |
|---|---|---|---|
quantity | any | no | New total quantity. |
limit_price | any | no | New limit price. |
reason | string | no | Why (kept in the history). |
Decimals (money, prices, quantities, percentages) are sent as strings, ids as strings, times as ISO 8601 UTC.
Examples
Keep the token in an environment variable (VESTORIS_TOKEN), never in the script.
curl
curl -X POST "https://vestoris.com/api/v1/orders/5301/amend" \
-H "Authorization: Bearer $VESTORIS_TOKEN" \
-H 'Idempotency-Key: 7f9c2b1e-4d0a-4a7e-9a51-3c2f0b8d6e11' \
-H 'If-Match: "3f1a9c0e5b7d2a4c8e6f0b1d3a5c7e9f"' \
-H "Content-Type: application/json" \
-d '{"quantity":"1500","limit_price":"231.50","reason":"Client reduced size"}'
Python (requests)
import os, requests
r = requests.post(
"https://vestoris.com/api/v1/orders/5301/amend",
headers={
"Authorization": f"Bearer {os.environ['VESTORIS_TOKEN']}",
"Idempotency-Key": "7f9c2b1e-4d0a-4a7e-9a51-3c2f0b8d6e11",
"If-Match": "\"3f1a9c0e5b7d2a4c8e6f0b1d3a5c7e9f\"",
},
json={
"quantity": "1500",
"limit_price": "231.50",
"reason": "Client reduced size"
},
timeout=30,
)
r.raise_for_status() # errors are application/problem+json with a stable "code"
print(r.json())
JavaScript (fetch)
const res = await fetch("https://vestoris.com/api/v1/orders/5301/amend", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VESTORIS_TOKEN}`,
"Idempotency-Key": "7f9c2b1e-4d0a-4a7e-9a51-3c2f0b8d6e11",
"If-Match": "\"3f1a9c0e5b7d2a4c8e6f0b1d3a5c7e9f\"",
"Content-Type": "application/json",
},
body: JSON.stringify({
"quantity": "1500",
"limit_price": "231.50",
"reason": "Client reduced size"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.detail}`); // problem+json
console.log(data);
Response
200 OK, application/json: Order. With an ETag header. Rate-limit headers: RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset.
Response fields
| Field | Type | Description |
|---|---|---|
id | id (string) | The record's id (a string of digits). |
security_id | id (string) | The security's id. |
symbol | string | Ticker symbol. |
side | string | "buy" or "sell". |
order_type | string | "market" or "limit". |
limit_price | decimal string or null | Limit price (null for a market order). |
quantity | decimal string | Total shares across the allocations. |
filled_quantity | decimal string or null | Shares filled so far (simulated). |
avg_fill_price | decimal string or null | Average price of the simulated fills so far. |
state | string | proposed, pending_compliance, compliance_hold, pending_approval, approved, working, partially_filled, filled, cancelled or rejected. |
compliance_state | string | The latest compliance result: "pass", "warn", "block" or "pending". |
is_block | boolean | True for a block order across several accounts. |
algo | string | The simulated execution algorithm: "vwap", "twap" or "none" (all at once); "" before release. |
slices | integer | How many slices the simulator works the order in. |
arrival_price | decimal string or null | The simulated price when the order was released (the benchmark for slippage). |
approval_required | boolean | Whether the order needs an approver (four eyes). |
approval_reason | string | Why the order needs an approver ("" when it does not). |
status_reason | string | Why the order is in its state. |
notes | string | Notes. |
venue | string | Simulated venue. |
created_by | id (string) or null | The user who created it. |
approved_by | id (string) or null | The user who approved the order. |
trader_id | id (string) or null | The trader the order is assigned to. |
pipeline_run_id | id (string) or null | The Intent Pipeline request it came from. |
proposal_id | id (string) or null | The rebalance proposal it came from. |
allocations | list of Allocation | How the order is split between accounts. |
allocations[].account_id | id (string) | The account's id. |
allocations[].quantity | decimal string or null | Shares for the account. |
allocations[].filled_quantity | decimal string or null | Shares filled for the account. |
hidden_allocations | integer | Allocations on accounts you may not see (counted, never shown). |
allocated_at | date-time or null | When Operations confirmed the allocation. |
created_at | date-time or null | When it was created. |
submitted_at | date-time or null | When the order was submitted. |
approved_at | date-time or null | When the order was approved. |
working_at | date-time or null | When the order started working in the simulator. |
done_at | date-time or null | When the order reached a final state. |
simulated | boolean | Always true: simulated data, paper trading. |
result | object | The outcome. |
result.state | string | proposed, pending_compliance, compliance_hold, pending_approval, approved, working, partially_filled, filled, cancelled or rejected. |
result.compliance | list | The results of the compliance checks (rule, outcome, measured value, limit). |
result.approvals_needed | list | Who still has to approve. |
result.needs_override | boolean | True when a soft warning waits for an override reason. |
result.override | any | The override request, if any. |
history | list of OrderHistory | Every state change, oldest first. |
history[].from | string | State before. |
history[].to | string | State after. |
history[].by | id (string) or null | The user who made the change. |
history[].reason | string | Why. |
history[].at | date-time or null | When it happened. |
Example response
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "3f1a9c0e5b7d2a4c8e6f0b1d3a5c7e9f"
{
"id": "1042",
"security_id": "3",
"symbol": "AAPL",
"side": "buy",
"order_type": "limit",
"limit_price": "232.00",
"quantity": "1800",
"filled_quantity": "0",
"avg_fill_price": "231.52",
"state": "pending_approval",
"compliance_state": "pass",
"is_block": false,
"algo": "vwap",
"slices": 4,
"arrival_price": "231.45",
"approval_required": true,
"approval_reason": "Order value $1.25M is above the firm threshold of $1M",
"status_reason": "Order value above the approval threshold",
"notes": "Rebalance, Growth accounts",
"venue": "SIM",
"created_by": "7",
"approved_by": null,
"trader_id": null,
"pipeline_run_id": null,
"proposal_id": null,
"allocations": [
{
"account_id": "12",
"quantity": "1200",
"filled_quantity": "0"
}
],
"hidden_allocations": 0,
"allocated_at": null,
"created_at": "2026-10-27T14:30:00Z",
"submitted_at": "2026-10-27T14:30:00Z",
"approved_at": null,
"working_at": null,
"done_at": null,
"simulated": true,
"result": {
"state": "pending_approval",
"compliance": [],
"approvals_needed": [
"portfolio_manager"
],
"needs_override": false,
"override": null
},
"history": [
{
"from": "pending_compliance",
"to": "pending_approval",
"by": "7",
"reason": "Above the firm approval threshold",
"at": "2026-10-27T14:30:00Z"
}
]
}
Example values. Your values depend on your firm's data; prices, orders and fills are simulated.
Status codes and errors
Errors are application/problem+json (RFC 9457) with a stable code to program against; the detail says what to fix. See Errors.
| Status | When | Problem codes |
|---|---|---|
| 200 | Success | |
| 200 / 201 | The same Idempotency-Key again: the first answer is replayed (24 hours) | |
| 400 | The request is malformed | invalid_request invalid_json |
| 401 | No token, or it is invalid or expired | invalid_token |
| 403 | The token lacks the scope, or the person or service account behind it lacks the privilege or account permission | insufficient_scope forbidden ip_not_allowed |
| 404 | Not found, or not visible to you (the API never confirms what you may not see) | not_found |
| 409 | Not possible in the current state | invalid_transition conflict idempotency_in_progress |
| 412 | The resource changed since your GET: get it again and retry with the new ETag | precondition_failed |
| 422 | Validation failed (the detail says which field), or blocked | validation_failed compliance_blocked idempotency_key_reused |
| 428 | A required header is missing | idempotency_key_required precondition_required |
| 429 | Rate limited: wait for Retry-After seconds | rate_limited |
{
"type": "https://vestoris.com/developers/errors#validation_failed",
"title": "Validation failed",
"status": 422,
"detail": "Quantity must be greater than zero.",
"code": "validation_failed",
"instance": "/api/v1/orders/5301/amend"
}
On the screens
The same thing in the app is explained in: