Skip to content

Commit abd8e4a

Browse files
authored
fix(auto-monitor-setups): update bulk upsert to atomic semantics (#173)
1 parent 196cabc commit abd8e4a

1 file changed

Lines changed: 42 additions & 41 deletions

File tree

api-reference/auto-monitor-setups/bulk-upsert-auto-monitor-setups.mdx

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ Each item is upserted independently using the same semantics as [Update by Exter
1313
See [Authentication](/api-reference/introduction) for details.
1414
</Note>
1515

16-
## Partial Success Semantics
16+
## Atomic Semantics
1717

18-
The endpoint returns **`207 Multi-Status`** when the batch is accepted, even if some items inside fail. Each item carries its own `status` (`ok` or `error`) — you must iterate the response array to check per-item results.
18+
The batch is applied **atomically** — it either fully succeeds or nothing is written. If any item fails validation, or the database write fails, **no** setups are persisted. On success the endpoint returns **`200 OK`** with the full list of upserted setups.
1919

20-
Request-level errors (empty batch, more than 100 items, duplicate `external_id` within the batch, missing `external_id` on any item) reject the **entire** batch with `400 Bad Request`. No items are written.
20+
Because the batch is all-or-nothing, there are no per-item status flags: every item in the response was written successfully. Failures are surfaced as a single request-level error (`400` or `500`) identifying the first offending item.
2121

2222
## Request Body
2323

@@ -61,61 +61,60 @@ curl -X POST https://api.traceloop.com/v2/auto-monitor-setups/bulk \
6161

6262
## Response
6363

64-
### 207 Multi-Status
64+
### 200 OK
6565

66-
Returned when the batch is accepted. The `setups` array contains one entry per input item, in the **same order** as the request.
67-
68-
Each entry has:
69-
70-
| Field | Type | Description |
71-
|-------|------|-------------|
72-
| `external_id` | string | The `external_id` of the input item. |
73-
| `status` | string | `ok` if the item was upserted, `error` if it failed. |
74-
| `result` | object | Present when `status` is `ok`. The full upserted setup, matching the [Create](/api-reference/auto-monitor-setups/create-an-auto-monitor-setup) response shape. |
75-
| `error` | string | Present when `status` is `error`. Human-readable message prefixed with the item index, e.g. `setups[1]: unknown evaluator slug "..."`. Internal errors are reported as `setups[N]: internal error` — the underlying cause is logged server-side but not returned to the client. |
66+
Returned when the entire batch is upserted successfully. The `setups` array contains one entry per input item, in the **same order** as the request. Each entry is a full setup object, matching the [Create](/api-reference/auto-monitor-setups/create-an-auto-monitor-setup) response shape.
7667

7768
```json
7869
{
7970
"setups": [
8071
{
72+
"id": "cmm...",
8173
"external_id": "openai-gpt4o-monitor",
82-
"status": "ok",
83-
"result": {
84-
"id": "cmm...",
85-
"external_id": "openai-gpt4o-monitor",
86-
"org_id": "c108269c-...",
87-
"project_id": "cm9v2g95l...",
88-
"env_project_id": "cm9v2ga9i...",
89-
"init_rules": [
90-
{ "key": "gen_ai.system", "value": "openai", "source": "span_attributes", "operator": "equals" },
91-
{ "key": "gen_ai.request.model", "value": "gpt-4o", "source": "span_attributes", "operator": "equals" }
92-
],
93-
"evaluators": [
94-
{ "evaluator_type": "answer-relevancy", "status": "pending" },
95-
{ "evaluator_type": "toxicity-detector", "status": "pending" }
96-
],
97-
"status": "pending",
98-
"created_at": "2026-05-20T10:30:00Z",
99-
"updated_at": "2026-05-20T10:30:00Z"
100-
}
74+
"org_id": "c108269c-...",
75+
"project_id": "cm9v2g95l...",
76+
"env_project_id": "cm9v2ga9i...",
77+
"init_rules": [
78+
{ "key": "gen_ai.system", "value": "openai", "source": "span_attributes", "operator": "equals" },
79+
{ "key": "gen_ai.request.model", "value": "gpt-4o", "source": "span_attributes", "operator": "equals" }
80+
],
81+
"evaluators": [
82+
{ "evaluator_type": "answer-relevancy", "status": "pending" },
83+
{ "evaluator_type": "toxicity-detector", "status": "pending" }
84+
],
85+
"status": "pending",
86+
"created_at": "2026-05-20T10:30:00Z",
87+
"updated_at": "2026-05-20T10:30:00Z"
10188
},
10289
{
90+
"id": "cmm...",
10391
"external_id": "anthropic-monitor",
104-
"status": "error",
105-
"error": "setups[1]: unknown evaluator slug \"answer-relevancy-typo\""
92+
"org_id": "c108269c-...",
93+
"project_id": "cm9v2g95l...",
94+
"env_project_id": "cm9v2ga9i...",
95+
"init_rules": [
96+
{ "key": "gen_ai.system", "value": "anthropic", "source": "span_attributes", "operator": "equals" }
97+
],
98+
"evaluators": [
99+
{ "evaluator_type": "answer-relevancy", "status": "pending" }
100+
],
101+
"status": "pending",
102+
"created_at": "2026-05-20T10:30:00Z",
103+
"updated_at": "2026-05-20T10:30:00Z"
106104
}
107105
]
108106
}
109107
```
110108

111109
### 400 Bad Request
112110

113-
Returned when the batch is rejected without writing any items. Causes:
111+
Returned when the batch is rejected without writing any items. The `error` message identifies the first offending item by index. Causes:
114112

115-
- Empty `setups` array
116-
- More than 100 items
117-
- Any item missing `external_id`
118-
- Two items in the batch share the same `external_id`
113+
- Empty `setups` array — `setups must contain at least 1 item`
114+
- More than 100 items — `setups exceeds max of 100`
115+
- Any item missing `external_id``setups[N]: external_id is required`
116+
- Two items in the batch share the same `external_id``setups[N]: duplicate external_id "..." (also at setups[M])`
117+
- Any item fails validation — e.g. an unknown evaluator slug, an invalid selector, or an invalid evaluator config, prefixed with the item index: `setups[N]: evaluators[0]: unknown evaluator slug "..."`
119118

120119
```json
121120
{
@@ -125,8 +124,10 @@ Returned when the batch is rejected without writing any items. Causes:
125124

126125
### 500 Internal Server Error
127126

127+
Returned when the database write fails. No items are persisted. The underlying cause is logged server-side and not returned to the client.
128+
128129
```json
129130
{
130-
"error": "internal server error"
131+
"error": "Internal server error"
131132
}
132133
```

0 commit comments

Comments
 (0)