Skip to content

Commit 5723993

Browse files
Merge branch 'main' into feat/braze-merge-users
2 parents 24a74a3 + ae4a6f8 commit 5723993

501 files changed

Lines changed: 417205 additions & 2517 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/commands/endpoint-mapping.md

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Parse the spec and index: base URL, API version, auth scheme, all endpoints (pat
3434
### Phase 2: Action-to-Endpoint Matching
3535

3636
For each action, find matching endpoint(s) using this priority:
37+
3738
1. Exact operationId match
3839
2. Semantic match (description alignment)
3940
3. Path + Method match
@@ -42,6 +43,23 @@ For each action, find matching endpoint(s) using this priority:
4243

4344
Verify: HTTP method aligns, path params can be sourced, request body accommodates fields, response has needed IDs.
4445

46+
#### Prefer a batch/bulk endpoint when one exists
47+
48+
For **every** action, look for a dedicated batch/bulk endpoint alongside the single-record endpoint. These are the endpoints that will back `performBatch` in code, so identifying them here is required.
49+
50+
Signals that an endpoint is a batch endpoint:
51+
52+
- Path or operationId contains `batch`, `bulk`, `import`, `collection`, `events`, or a plural resource (`/users` accepting an array vs `/users/{id}`).
53+
- Request body schema is an **array** (or an object wrapping an array, e.g. `{ "data": [...] }`, `{ "records": [...] }`, `{ "events": [...] }`).
54+
- Docs mention "up to N records per request", a batch/bulk limit, or bulk import semantics.
55+
56+
For each action, record BOTH when available:
57+
58+
- **Single endpoint** — sends one record (backs `perform`).
59+
- **Batch endpoint** — accepts many records (backs `performBatch`).
60+
61+
**Preference rule:** when a batch endpoint exists, it is the preferred delivery path — flag it as such and capture its records-per-request limit and array wrapper key (if any). If the API only exposes a single-record endpoint that happens to accept an array of records at the same path/method, note that the same endpoint serves both paths. If no batch capability exists at all, say so explicitly (this tells the generator not to invent one).
62+
4563
### Phase 3: Field-Level Mapping
4664

4765
For every action-endpoint pair, map each field: source field, target field (API JSON path), Segment event path, target type, transformation needed, required by API.
@@ -72,6 +90,7 @@ Generated: <current date>
7290
---
7391

7492
## API Overview
93+
7594
- **Base URL:** <url>
7695
- **API Version:** <version>
7796
- **Auth:** <scheme>
@@ -89,19 +108,23 @@ Generated: <current date>
89108
**API Operation:** `<operationId>``<HTTP METHOD>`
90109
**Endpoint URI:** `<full path>`
91110

111+
**Batch Endpoint:** `<operationId>``<HTTP METHOD>` `<full path>` — records-per-request limit: `<N or "undocumented">`, array wrapper key: `<key or "root array">`
112+
_(If no batch endpoint exists, write: "None — API accepts one record per call." If the single endpoint itself accepts an array, write: "Same as single endpoint — accepts an array of records.")_
113+
92114
#### Field Mapping Table
93115

94-
| Source Field | Segment Path | Target Field (API) | Target Type | Transform | Required by API |
95-
|---|---|---|---|---|---|
96-
| `email` | `$.traits.email` | `$.properties.email` | string | Direct | Yes |
116+
| Source Field | Segment Path | Target Field (API) | Target Type | Transform | Required by API |
117+
| ------------ | ---------------- | -------------------- | ----------- | --------- | --------------- |
118+
| `email` | `$.traits.email` | `$.properties.email` | string | Direct | Yes |
97119

98120
#### Mandatory API Parameters (not in action fields)
99121

100-
| Parameter | Location | Source | Value |
101-
|---|---|---|---|
102-
| `projectId` | path | settings | `settings.projectId` |
122+
| Parameter | Location | Source | Value |
123+
| ----------- | -------- | -------- | -------------------- |
124+
| `projectId` | path | settings | `settings.projectId` |
103125

104126
#### Response Handling
127+
105128
- **Success (200/201):** <what to extract>
106129
- **Error (4xx/5xx):** <handling>
107130

@@ -110,6 +133,7 @@ Generated: <current date>
110133
## Gap Reconciliations
111134

112135
### Gap: <Action Name>
136+
113137
**Reason:** ...
114138
**Nearest Proxy:** ...
115139
**Composite Sequence:** ...
@@ -118,9 +142,9 @@ Generated: <current date>
118142

119143
## Coverage Summary
120144

121-
| Action | Endpoint Match | Match Type | Gaps |
122-
|---|---|---|---|
123-
| `actionOne` | `POST /resource` | Direct | None |
145+
| Action | Endpoint Match | Match Type | Gaps |
146+
| ----------- | ---------------- | ---------- | ---- |
147+
| `actionOne` | `POST /resource` | Direct | None |
124148
```
125149

126150
### `endpoint-mapping.json`
@@ -134,9 +158,7 @@ Machine-readable format:
134158
"configuration": {
135159
"authType": "<auth method>",
136160
"authDetails": "<description>",
137-
"settings": [
138-
{ "name": "setting_name", "type": "string", "required": true, "description": "Description" }
139-
]
161+
"settings": [{ "name": "setting_name", "type": "string", "required": true, "description": "Description" }]
140162
},
141163
"apiOverview": {
142164
"baseUrl": "<url>",
@@ -161,6 +183,16 @@ Machine-readable format:
161183
"httpMethod": "POST",
162184
"endpointUri": "/resource/{id}",
163185
"matchType": "direct",
186+
"batchEndpoint": {
187+
"supported": true,
188+
"apiOperation": "batchOperationId",
189+
"httpMethod": "POST",
190+
"endpointUri": "/resource/batch",
191+
"sameAsSingle": false,
192+
"arrayWrapperKey": "records",
193+
"maxRecordsPerRequest": 1000,
194+
"notes": "Preferred delivery path; backs performBatch"
195+
},
164196
"fieldMappings": [
165197
{
166198
"sourceField": "email",
@@ -179,20 +211,19 @@ Machine-readable format:
179211
}
180212
],
181213
"gapReconciliations": [],
182-
"coverageSummary": [
183-
{ "action": "actionName", "endpoint": "POST /resource", "matchType": "direct", "hasGap": false }
184-
]
214+
"coverageSummary": [{ "action": "actionName", "endpoint": "POST /resource", "matchType": "direct", "hasGap": false }]
185215
}
186216
```
187217

188218
## Constraints
189219

190220
- **ZERO-DROP RULE**: Every action MUST appear in output — no exceptions.
191221
- **DO NOT** generate TypeScript code — only the mapping analysis.
192-
- **DO NOT** invent API endpoints not in the spec — flag as a gap.
222+
- **DO NOT** invent API endpoints not in the spec — flag as a gap. This includes batch endpoints: only record a batch endpoint that actually exists in the spec; if none exists, set `"supported": false`.
193223
- **DO NOT** skip required API fields.
194224
- Every field mapping MUST have a transformation type (even if "Direct").
195225
- Every path parameter MUST have a defined source.
226+
- Every action MUST have a `batchEndpoint` object. When a real batch/bulk endpoint exists, it is the preferred delivery path and MUST be captured with its array wrapper key and records-per-request limit.
196227

197228
## Validation Checklist
198229

@@ -202,6 +233,7 @@ Machine-readable format:
202233
- [ ] Every gap has a reconciliation report
203234
- [ ] Every path parameter has a source
204235
- [ ] Response handling is defined for each mapping
236+
- [ ] Every action records a batch endpoint (or explicitly states none exists); when one exists it is flagged as the preferred delivery path with its array wrapper key and record limit
205237

206238
## Post-Output
207239

0 commit comments

Comments
 (0)