@kirimdev/sdk 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/openapi.json CHANGED
@@ -44,6 +44,10 @@
44
44
  "name": "Labels",
45
45
  "description": "Coloured tags for contacts and conversations. Team-scoped per Kirimdev's internal model."
46
46
  },
47
+ {
48
+ "name": "Customers",
49
+ "description": "End-customers (tenant-of-tenant) — your platform's own clients. Each Customer can connect their own WhatsApp accounts via setup links and you send messages on their behalf. Distinct from `Contacts`."
50
+ },
47
51
  {
48
52
  "name": "Webhook Subscriptions",
49
53
  "description": "Subscribe to events, rotate signing secrets, pause/resume delivery."
@@ -100,6 +104,50 @@
100
104
  "error"
101
105
  ]
102
106
  },
107
+ "WhatsappAccountEmbedded": {
108
+ "type": "object",
109
+ "properties": {
110
+ "phone_number": {
111
+ "type": [
112
+ "string",
113
+ "null"
114
+ ]
115
+ },
116
+ "phone_number_id": {
117
+ "type": [
118
+ "string",
119
+ "null"
120
+ ],
121
+ "example": "106540352242922",
122
+ "description": "Meta `business_phone_number_id` — use as the `{phone_number_id}` path segment in `/v1/{phone_number_id}/...` endpoints."
123
+ },
124
+ "customer": {
125
+ "type": [
126
+ "object",
127
+ "null"
128
+ ],
129
+ "properties": {
130
+ "id": {
131
+ "type": "string",
132
+ "example": "cus_01HXYZABCDEFGHJKMNPQRSTVWX"
133
+ },
134
+ "name": {
135
+ "type": "string"
136
+ }
137
+ },
138
+ "required": [
139
+ "id",
140
+ "name"
141
+ ],
142
+ "description": "End-customer (multi-tenant platform mode) that owns this account. NULL for direct-org accounts."
143
+ }
144
+ },
145
+ "required": [
146
+ "phone_number",
147
+ "phone_number_id",
148
+ "customer"
149
+ ]
150
+ },
103
151
  "Message": {
104
152
  "type": "object",
105
153
  "properties": {
@@ -144,7 +192,8 @@
144
192
  "type": "object",
145
193
  "properties": {
146
194
  "code": {
147
- "type": "string"
195
+ "type": "string",
196
+ "description": "Stable Kirim error code. Known values include `outside_24h_window`, `marketing_opted_out`, `marketing_blocked_by_user`, `recipient_unavailable`, `unsupported_message_type`, `account_restricted`, `account_locked`, `consent_required`, `customer_suspended`, `permission_revoked`, `auth_expired`, `app_rate_limited`, `account_rate_limited`, `template_not_found`, `template_paused`, `template_policy_violation`, `flow_blocked`, `media_upload_failed`, `media_download_failed`, `undeliverable`, `policy_violation`, `upstream_error`."
148
197
  },
149
198
  "message": {
150
199
  "type": "string"
@@ -207,18 +256,7 @@
207
256
  },
208
257
  "components": {},
209
258
  "whatsapp_account": {
210
- "type": "object",
211
- "properties": {
212
- "phone_number": {
213
- "type": [
214
- "string",
215
- "null"
216
- ]
217
- }
218
- },
219
- "required": [
220
- "phone_number"
221
- ]
259
+ "$ref": "#/components/schemas/WhatsappAccountEmbedded"
222
260
  },
223
261
  "provider_template_id": {
224
262
  "type": [
@@ -284,6 +322,14 @@
284
322
  "type": "string",
285
323
  "example": "connected",
286
324
  "description": "Lifecycle state of the account (e.g. `connected`, `disconnected`, `degraded`, `onboarding`)."
325
+ },
326
+ "customer_id": {
327
+ "type": [
328
+ "string",
329
+ "null"
330
+ ],
331
+ "example": "cus_01HXYZABCDEFGHJKMNPQRSTVWX",
332
+ "description": "Public id of the end-customer (multi-tenant platform mode) that owns this account. NULL for direct-org accounts. Filter the list endpoint via `?customer_id=cus_...`."
287
333
  }
288
334
  },
289
335
  "required": [
@@ -291,7 +337,8 @@
291
337
  "phone_number_id",
292
338
  "phone_number",
293
339
  "name",
294
- "status"
340
+ "status",
341
+ "customer_id"
295
342
  ]
296
343
  },
297
344
  "WebhookSubscription": {
@@ -538,18 +585,7 @@
538
585
  ]
539
586
  },
540
587
  "whatsapp_account": {
541
- "type": "object",
542
- "properties": {
543
- "phone_number": {
544
- "type": [
545
- "string",
546
- "null"
547
- ]
548
- }
549
- },
550
- "required": [
551
- "phone_number"
552
- ]
588
+ "$ref": "#/components/schemas/WhatsappAccountEmbedded"
553
589
  },
554
590
  "assignee": {
555
591
  "type": [
@@ -659,18 +695,7 @@
659
695
  "additionalProperties": {}
660
696
  },
661
697
  "whatsapp_account": {
662
- "type": "object",
663
- "properties": {
664
- "phone_number": {
665
- "type": [
666
- "string",
667
- "null"
668
- ]
669
- }
670
- },
671
- "required": [
672
- "phone_number"
673
- ]
698
+ "$ref": "#/components/schemas/WhatsappAccountEmbedded"
674
699
  },
675
700
  "created_at": {
676
701
  "type": "string",
@@ -749,6 +774,172 @@
749
774
  "updated_at"
750
775
  ]
751
776
  },
777
+ "Customer": {
778
+ "type": "object",
779
+ "properties": {
780
+ "id": {
781
+ "type": "string",
782
+ "example": "cus_01HXYZABCDEFGHJKMNPQRSTVWX"
783
+ },
784
+ "object": {
785
+ "type": "string",
786
+ "enum": [
787
+ "customer"
788
+ ]
789
+ },
790
+ "name": {
791
+ "type": "string"
792
+ },
793
+ "email": {
794
+ "type": [
795
+ "string",
796
+ "null"
797
+ ]
798
+ },
799
+ "status": {
800
+ "type": "string",
801
+ "enum": [
802
+ "pending",
803
+ "active",
804
+ "suspended",
805
+ "archived"
806
+ ]
807
+ },
808
+ "metadata": {
809
+ "type": [
810
+ "object",
811
+ "null"
812
+ ],
813
+ "additionalProperties": {}
814
+ },
815
+ "archived_at": {
816
+ "type": [
817
+ "string",
818
+ "null"
819
+ ],
820
+ "format": "date-time"
821
+ },
822
+ "team_id": {
823
+ "type": "string"
824
+ },
825
+ "created_at": {
826
+ "type": "string",
827
+ "format": "date-time"
828
+ },
829
+ "updated_at": {
830
+ "type": "string",
831
+ "format": "date-time"
832
+ }
833
+ },
834
+ "required": [
835
+ "id",
836
+ "object",
837
+ "name",
838
+ "email",
839
+ "status",
840
+ "metadata",
841
+ "archived_at",
842
+ "team_id",
843
+ "created_at",
844
+ "updated_at"
845
+ ]
846
+ },
847
+ "CustomerSetupLink": {
848
+ "type": "object",
849
+ "properties": {
850
+ "id": {
851
+ "type": "string",
852
+ "example": "csl_01HXYZABCDEFGHJKMNPQRSTVWX"
853
+ },
854
+ "object": {
855
+ "type": "string",
856
+ "enum": [
857
+ "customer_setup_link"
858
+ ]
859
+ },
860
+ "customer_id": {
861
+ "type": "string"
862
+ },
863
+ "status": {
864
+ "type": "string",
865
+ "enum": [
866
+ "active",
867
+ "consumed",
868
+ "expired",
869
+ "revoked"
870
+ ]
871
+ },
872
+ "token_last4": {
873
+ "type": "string"
874
+ },
875
+ "expires_at": {
876
+ "type": "string",
877
+ "format": "date-time"
878
+ },
879
+ "consumed_at": {
880
+ "type": [
881
+ "string",
882
+ "null"
883
+ ],
884
+ "format": "date-time"
885
+ },
886
+ "success_redirect_url": {
887
+ "type": [
888
+ "string",
889
+ "null"
890
+ ],
891
+ "format": "uri",
892
+ "description": "Where the tenant is redirected after successful Embedded Signup. We append `?customer_id=&account_id=&status=success` on the redirect."
893
+ },
894
+ "failure_redirect_url": {
895
+ "type": [
896
+ "string",
897
+ "null"
898
+ ],
899
+ "format": "uri",
900
+ "description": "Where the tenant is redirected on failure (link error, Meta signup cancelled, etc.). We append `?customer_id=&status=failed&reason=<code>`."
901
+ },
902
+ "created_at": {
903
+ "type": "string",
904
+ "format": "date-time"
905
+ }
906
+ },
907
+ "required": [
908
+ "id",
909
+ "object",
910
+ "customer_id",
911
+ "status",
912
+ "token_last4",
913
+ "expires_at",
914
+ "consumed_at",
915
+ "success_redirect_url",
916
+ "failure_redirect_url",
917
+ "created_at"
918
+ ]
919
+ },
920
+ "CustomerSetupLinkWithToken": {
921
+ "allOf": [
922
+ {
923
+ "$ref": "#/components/schemas/CustomerSetupLink"
924
+ },
925
+ {
926
+ "type": "object",
927
+ "properties": {
928
+ "setup_url": {
929
+ "type": "string",
930
+ "format": "uri"
931
+ },
932
+ "token": {
933
+ "type": "string"
934
+ }
935
+ },
936
+ "required": [
937
+ "setup_url",
938
+ "token"
939
+ ]
940
+ }
941
+ ]
942
+ },
752
943
  "MessageListItem": {
753
944
  "type": "object",
754
945
  "properties": {
@@ -811,7 +1002,8 @@
811
1002
  "type": "object",
812
1003
  "properties": {
813
1004
  "code": {
814
- "type": "string"
1005
+ "type": "string",
1006
+ "description": "Stable Kirim error code. Known values include `outside_24h_window`, `marketing_opted_out`, `marketing_blocked_by_user`, `recipient_unavailable`, `unsupported_message_type`, `account_restricted`, `account_locked`, `consent_required`, `customer_suspended`, `permission_revoked`, `auth_expired`, `app_rate_limited`, `account_rate_limited`, `template_not_found`, `template_paused`, `template_policy_violation`, `flow_blocked`, `media_upload_failed`, `media_download_failed`, `undeliverable`, `policy_violation`, `upstream_error`."
815
1007
  },
816
1008
  "message": {
817
1009
  "type": "string"
@@ -1037,6 +1229,47 @@
1037
1229
  "request_id"
1038
1230
  ]
1039
1231
  },
1232
+ "SyncTemplatesResponse": {
1233
+ "type": "object",
1234
+ "properties": {
1235
+ "data": {
1236
+ "type": "object",
1237
+ "properties": {
1238
+ "object": {
1239
+ "type": "string",
1240
+ "enum": [
1241
+ "template_sync_result"
1242
+ ]
1243
+ },
1244
+ "synced": {
1245
+ "type": "integer",
1246
+ "example": 12
1247
+ },
1248
+ "created": {
1249
+ "type": "integer",
1250
+ "example": 2
1251
+ },
1252
+ "updated": {
1253
+ "type": "integer",
1254
+ "example": 10
1255
+ }
1256
+ },
1257
+ "required": [
1258
+ "object",
1259
+ "synced",
1260
+ "created",
1261
+ "updated"
1262
+ ]
1263
+ },
1264
+ "request_id": {
1265
+ "type": "string"
1266
+ }
1267
+ },
1268
+ "required": [
1269
+ "data",
1270
+ "request_id"
1271
+ ]
1272
+ },
1040
1273
  "CreateWebhookSubscriptionResponse": {
1041
1274
  "type": "object",
1042
1275
  "properties": {
@@ -1810,19 +2043,292 @@
1810
2043
  "data",
1811
2044
  "request_id"
1812
2045
  ]
1813
- }
1814
- },
1815
- "parameters": {}
1816
- },
1817
- "paths": {
1818
- "/health": {
1819
- "get": {
1820
- "tags": [
1821
- "Meta"
1822
- ],
1823
- "summary": "Liveness probe",
1824
- "description": "Unauthenticated health check. Returns 200 if the API is up.",
1825
- "responses": {
2046
+ },
2047
+ "ListCustomersResponse": {
2048
+ "type": "object",
2049
+ "properties": {
2050
+ "data": {
2051
+ "type": "array",
2052
+ "items": {
2053
+ "$ref": "#/components/schemas/Customer"
2054
+ }
2055
+ },
2056
+ "has_more": {
2057
+ "type": "boolean"
2058
+ },
2059
+ "next_cursor": {
2060
+ "type": [
2061
+ "string",
2062
+ "null"
2063
+ ]
2064
+ },
2065
+ "request_id": {
2066
+ "type": "string"
2067
+ }
2068
+ },
2069
+ "required": [
2070
+ "data",
2071
+ "has_more",
2072
+ "next_cursor",
2073
+ "request_id"
2074
+ ]
2075
+ },
2076
+ "CreateCustomerResponse": {
2077
+ "type": "object",
2078
+ "properties": {
2079
+ "data": {
2080
+ "$ref": "#/components/schemas/Customer"
2081
+ },
2082
+ "request_id": {
2083
+ "type": "string"
2084
+ }
2085
+ },
2086
+ "required": [
2087
+ "data",
2088
+ "request_id"
2089
+ ]
2090
+ },
2091
+ "GetCustomerResponse": {
2092
+ "type": "object",
2093
+ "properties": {
2094
+ "data": {
2095
+ "allOf": [
2096
+ {
2097
+ "$ref": "#/components/schemas/Customer"
2098
+ },
2099
+ {
2100
+ "type": "object",
2101
+ "properties": {
2102
+ "whatsapp_accounts": {
2103
+ "type": "array",
2104
+ "items": {
2105
+ "type": "object",
2106
+ "properties": {
2107
+ "phone_number_id": {
2108
+ "type": [
2109
+ "string",
2110
+ "null"
2111
+ ]
2112
+ },
2113
+ "phone_number": {
2114
+ "type": [
2115
+ "string",
2116
+ "null"
2117
+ ]
2118
+ },
2119
+ "name": {
2120
+ "type": [
2121
+ "string",
2122
+ "null"
2123
+ ]
2124
+ },
2125
+ "status": {
2126
+ "type": "string"
2127
+ },
2128
+ "onboarded_at": {
2129
+ "type": [
2130
+ "string",
2131
+ "null"
2132
+ ],
2133
+ "format": "date-time"
2134
+ }
2135
+ },
2136
+ "required": [
2137
+ "phone_number_id",
2138
+ "phone_number",
2139
+ "name",
2140
+ "status",
2141
+ "onboarded_at"
2142
+ ]
2143
+ },
2144
+ "description": "WhatsApp accounts currently assigned to this customer."
2145
+ }
2146
+ },
2147
+ "required": [
2148
+ "whatsapp_accounts"
2149
+ ]
2150
+ }
2151
+ ]
2152
+ },
2153
+ "request_id": {
2154
+ "type": "string"
2155
+ }
2156
+ },
2157
+ "required": [
2158
+ "data",
2159
+ "request_id"
2160
+ ]
2161
+ },
2162
+ "UpdateCustomerResponse": {
2163
+ "type": "object",
2164
+ "properties": {
2165
+ "data": {
2166
+ "$ref": "#/components/schemas/Customer"
2167
+ },
2168
+ "request_id": {
2169
+ "type": "string"
2170
+ }
2171
+ },
2172
+ "required": [
2173
+ "data",
2174
+ "request_id"
2175
+ ]
2176
+ },
2177
+ "ArchiveCustomerResponse": {
2178
+ "type": "object",
2179
+ "properties": {
2180
+ "data": {
2181
+ "type": "object",
2182
+ "properties": {
2183
+ "id": {
2184
+ "type": "string"
2185
+ },
2186
+ "object": {
2187
+ "type": "string",
2188
+ "enum": [
2189
+ "customer"
2190
+ ]
2191
+ },
2192
+ "archived": {
2193
+ "type": "boolean",
2194
+ "enum": [
2195
+ true
2196
+ ]
2197
+ }
2198
+ },
2199
+ "required": [
2200
+ "id",
2201
+ "object",
2202
+ "archived"
2203
+ ]
2204
+ },
2205
+ "request_id": {
2206
+ "type": "string"
2207
+ }
2208
+ },
2209
+ "required": [
2210
+ "data",
2211
+ "request_id"
2212
+ ]
2213
+ },
2214
+ "ListCustomerSetupLinksResponse": {
2215
+ "type": "object",
2216
+ "properties": {
2217
+ "data": {
2218
+ "type": "array",
2219
+ "items": {
2220
+ "$ref": "#/components/schemas/CustomerSetupLink"
2221
+ }
2222
+ },
2223
+ "has_more": {
2224
+ "type": "boolean"
2225
+ },
2226
+ "next_cursor": {
2227
+ "type": [
2228
+ "string",
2229
+ "null"
2230
+ ]
2231
+ },
2232
+ "request_id": {
2233
+ "type": "string"
2234
+ }
2235
+ },
2236
+ "required": [
2237
+ "data",
2238
+ "has_more",
2239
+ "next_cursor",
2240
+ "request_id"
2241
+ ]
2242
+ },
2243
+ "CreateCustomerSetupLinkResponse": {
2244
+ "type": "object",
2245
+ "properties": {
2246
+ "data": {
2247
+ "$ref": "#/components/schemas/CustomerSetupLinkWithToken"
2248
+ },
2249
+ "request_id": {
2250
+ "type": "string"
2251
+ }
2252
+ },
2253
+ "required": [
2254
+ "data",
2255
+ "request_id"
2256
+ ]
2257
+ },
2258
+ "UpdateCustomerSetupLinkResponse": {
2259
+ "type": "object",
2260
+ "properties": {
2261
+ "data": {
2262
+ "$ref": "#/components/schemas/CustomerSetupLink"
2263
+ },
2264
+ "request_id": {
2265
+ "type": "string"
2266
+ }
2267
+ },
2268
+ "required": [
2269
+ "data",
2270
+ "request_id"
2271
+ ]
2272
+ },
2273
+ "RevokeCustomerSetupLinkResponse": {
2274
+ "type": "object",
2275
+ "properties": {
2276
+ "data": {
2277
+ "type": "object",
2278
+ "properties": {
2279
+ "id": {
2280
+ "type": "string"
2281
+ },
2282
+ "object": {
2283
+ "type": "string",
2284
+ "enum": [
2285
+ "customer_setup_link"
2286
+ ]
2287
+ },
2288
+ "revoked": {
2289
+ "type": "boolean",
2290
+ "enum": [
2291
+ true
2292
+ ]
2293
+ },
2294
+ "status": {
2295
+ "type": "string",
2296
+ "enum": [
2297
+ "active",
2298
+ "consumed",
2299
+ "expired",
2300
+ "revoked"
2301
+ ]
2302
+ }
2303
+ },
2304
+ "required": [
2305
+ "id",
2306
+ "object",
2307
+ "revoked",
2308
+ "status"
2309
+ ]
2310
+ },
2311
+ "request_id": {
2312
+ "type": "string"
2313
+ }
2314
+ },
2315
+ "required": [
2316
+ "data",
2317
+ "request_id"
2318
+ ]
2319
+ }
2320
+ },
2321
+ "parameters": {}
2322
+ },
2323
+ "paths": {
2324
+ "/health": {
2325
+ "get": {
2326
+ "tags": [
2327
+ "Meta"
2328
+ ],
2329
+ "summary": "Liveness probe",
2330
+ "description": "Unauthenticated health check. Returns 200 if the API is up.",
2331
+ "responses": {
1826
2332
  "200": {
1827
2333
  "description": "API is healthy",
1828
2334
  "content": {
@@ -1939,6 +2445,15 @@
1939
2445
  "required": false,
1940
2446
  "name": "status",
1941
2447
  "in": "query"
2448
+ },
2449
+ {
2450
+ "schema": {
2451
+ "type": "string",
2452
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
2453
+ },
2454
+ "required": false,
2455
+ "name": "customer_id",
2456
+ "in": "query"
1942
2457
  }
1943
2458
  ],
1944
2459
  "responses": {
@@ -2001,7 +2516,7 @@
2001
2516
  "Messages"
2002
2517
  ],
2003
2518
  "summary": "Send a WhatsApp message or mark inbound as read",
2004
- "description": "Meta-style messages endpoint. Two operations share the same path, distinguished by the request body:\n\n**Outbound send** — body has a `type` field (`text`, `image`, `document`, `video`, `audio`, `template`, `interactive`). Body shape mirrors the Meta WhatsApp Cloud API; media variants accept either `link` (hosted URL) or `id` (Meta uploaded media). The sender is the WhatsApp account identified by `phone_number_id` in the URL path; there is no `from` field in the body. Pass `Idempotency-Key` to safely retry on network failure.\n\n**Read receipt** — body has `status: \"read\"` + `message_id` (the inbound wamid from your webhook). Sends a read receipt back to the sender so the double-tick turns blue on their phone. Optional `typing_indicator: { type: \"text\" }` shows a typing bubble alongside the receipt; Meta auto-dismisses after ~25 seconds or on first outbound message.",
2519
+ "description": "Meta-style messages endpoint. Two operations share the same path, distinguished by the request body:\n\n**Outbound send** — body has a `type` field (`text`, `image`, `document`, `video`, `audio`, `template`, `interactive`). Body shape mirrors the Meta WhatsApp Cloud API; media variants accept either `link` (hosted URL) or `id` (Meta uploaded media). The sender is the WhatsApp account identified by `phone_number_id` in the URL path; there is no `from` field in the body. Pass `Idempotency-Key` to safely retry on network failure.\n\n**Read receipt** — body has `status: \"read\"` + `message_id` (the inbound wamid from your webhook). Sends a read receipt back to the sender so the double-tick turns blue on their phone. Optional `typing_indicator: { type: \"text\" }` shows a typing bubble alongside the receipt; Meta auto-dismisses after ~25 seconds or on first outbound message.\n\n**Pre-send validation** — the API performs compliance checks before queuing the send. A 422 response with `error.code` set to `marketing_opted_out` indicates the recipient has stopped marketing messages from your business (the customer did this via the WhatsApp app menu — webhook `user_preferences` notifies you of the change). `account_restricted` indicates Meta has restricted your WhatsApp account; check the account status via the dashboard. `consent_required` indicates the recipient has not opted in. `customer_suspended` indicates the operator has suspended (or archived) the customer that owns this WhatsApp account; sends are blocked until the customer is unsuspended via the dashboard. `upstream_error` indicates the WhatsApp account is disconnected. None of these are retryable until the underlying condition changes.",
2005
2520
  "security": [
2006
2521
  {
2007
2522
  "bearerAuth": []
@@ -3727,32 +4242,142 @@
3727
4242
  }
3728
4243
  }
3729
4244
  },
3730
- "/webhook_subscriptions": {
4245
+ "/{phone_number_id}/templates/sync": {
3731
4246
  "post": {
3732
4247
  "tags": [
3733
- "Webhook Subscriptions"
4248
+ "Templates"
3734
4249
  ],
3735
- "summary": "Create a webhook subscription",
3736
- "description": "Create a webhook subscription. The response carries `initial_secret` ONCE store it server-side immediately; Kirimdev cannot show it again.",
4250
+ "summary": "Sync templates from Meta",
4251
+ "description": "Pull the latest template inventory from Meta and upsert into the Kirim DB for this WhatsApp account. Idempotent call any time, returns a `{ created, updated, synced }` summary. Useful for platform integrations (multi-tenant Customers) so they don't need to wait for an operator to click \"Sync\" in the dashboard.",
3737
4252
  "security": [
3738
4253
  {
3739
4254
  "bearerAuth": []
3740
4255
  }
3741
4256
  ],
3742
- "requestBody": {
3743
- "content": {
3744
- "application/json": {
3745
- "schema": {
3746
- "type": "object",
3747
- "properties": {
3748
- "url": {
3749
- "type": "string",
3750
- "format": "uri"
3751
- },
3752
- "description": {
3753
- "type": "string",
3754
- "maxLength": 200
3755
- },
4257
+ "parameters": [
4258
+ {
4259
+ "schema": {
4260
+ "type": "string",
4261
+ "pattern": "^\\d{6,20}$",
4262
+ "example": "106540352242922",
4263
+ "description": "Meta WhatsApp Business `phone_number_id` of the connected account that should send / own this resource. Discoverable via `GET /v1/accounts` (returned as `phone_number_id` on each row)."
4264
+ },
4265
+ "required": true,
4266
+ "description": "Meta WhatsApp Business `phone_number_id` of the connected account that should send / own this resource. Discoverable via `GET /v1/accounts` (returned as `phone_number_id` on each row).",
4267
+ "name": "phone_number_id",
4268
+ "in": "path"
4269
+ }
4270
+ ],
4271
+ "responses": {
4272
+ "200": {
4273
+ "description": "Sync summary",
4274
+ "content": {
4275
+ "application/json": {
4276
+ "schema": {
4277
+ "$ref": "#/components/schemas/SyncTemplatesResponse"
4278
+ }
4279
+ }
4280
+ }
4281
+ },
4282
+ "400": {
4283
+ "description": "Validation failure",
4284
+ "content": {
4285
+ "application/json": {
4286
+ "schema": {
4287
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4288
+ }
4289
+ }
4290
+ }
4291
+ },
4292
+ "401": {
4293
+ "description": "Authentication failure",
4294
+ "content": {
4295
+ "application/json": {
4296
+ "schema": {
4297
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4298
+ }
4299
+ }
4300
+ }
4301
+ },
4302
+ "404": {
4303
+ "description": "Resource not found",
4304
+ "content": {
4305
+ "application/json": {
4306
+ "schema": {
4307
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4308
+ }
4309
+ }
4310
+ }
4311
+ },
4312
+ "422": {
4313
+ "description": "Semantic failure (e.g. idempotency key reuse)",
4314
+ "content": {
4315
+ "application/json": {
4316
+ "schema": {
4317
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4318
+ }
4319
+ }
4320
+ }
4321
+ },
4322
+ "429": {
4323
+ "description": "Rate limit exceeded",
4324
+ "content": {
4325
+ "application/json": {
4326
+ "schema": {
4327
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4328
+ }
4329
+ }
4330
+ }
4331
+ },
4332
+ "500": {
4333
+ "description": "Internal server error",
4334
+ "content": {
4335
+ "application/json": {
4336
+ "schema": {
4337
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4338
+ }
4339
+ }
4340
+ }
4341
+ },
4342
+ "502": {
4343
+ "description": "Upstream WhatsApp error",
4344
+ "content": {
4345
+ "application/json": {
4346
+ "schema": {
4347
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
4348
+ }
4349
+ }
4350
+ }
4351
+ }
4352
+ }
4353
+ }
4354
+ },
4355
+ "/webhook_subscriptions": {
4356
+ "post": {
4357
+ "tags": [
4358
+ "Webhook Subscriptions"
4359
+ ],
4360
+ "summary": "Create a webhook subscription",
4361
+ "description": "Create a webhook subscription. The response carries `initial_secret` ONCE — store it server-side immediately; Kirimdev cannot show it again.",
4362
+ "security": [
4363
+ {
4364
+ "bearerAuth": []
4365
+ }
4366
+ ],
4367
+ "requestBody": {
4368
+ "content": {
4369
+ "application/json": {
4370
+ "schema": {
4371
+ "type": "object",
4372
+ "properties": {
4373
+ "url": {
4374
+ "type": "string",
4375
+ "format": "uri"
4376
+ },
4377
+ "description": {
4378
+ "type": "string",
4379
+ "maxLength": 200
4380
+ },
3756
4381
  "events": {
3757
4382
  "type": "array",
3758
4383
  "items": {
@@ -3763,7 +4388,13 @@
3763
4388
  "conversation.assigned",
3764
4389
  "conversation.closed",
3765
4390
  "contact.created",
3766
- "contact.updated"
4391
+ "contact.updated",
4392
+ "customer.created",
4393
+ "customer.updated",
4394
+ "customer.archived",
4395
+ "customer.onboarded",
4396
+ "customer.setup_link.created",
4397
+ "customer.setup_link.consumed"
3767
4398
  ]
3768
4399
  },
3769
4400
  "minItems": 1
@@ -4071,7 +4702,13 @@
4071
4702
  "conversation.assigned",
4072
4703
  "conversation.closed",
4073
4704
  "contact.created",
4074
- "contact.updated"
4705
+ "contact.updated",
4706
+ "customer.created",
4707
+ "customer.updated",
4708
+ "customer.archived",
4709
+ "customer.onboarded",
4710
+ "customer.setup_link.created",
4711
+ "customer.setup_link.consumed"
4075
4712
  ]
4076
4713
  },
4077
4714
  "minItems": 1
@@ -7134,6 +7771,963 @@
7134
7771
  }
7135
7772
  }
7136
7773
  }
7774
+ },
7775
+ "/customers": {
7776
+ "get": {
7777
+ "tags": [
7778
+ "Customers"
7779
+ ],
7780
+ "summary": "List customers",
7781
+ "description": "List end-customers (tenant-of-tenant) attached to the organization. Each customer can own one or more WhatsApp accounts via setup links. NOTE: a customer here is NOT a WhatsApp contact — see the `/{phone_number_id}/contacts` resource for those.",
7782
+ "security": [
7783
+ {
7784
+ "bearerAuth": []
7785
+ }
7786
+ ],
7787
+ "parameters": [
7788
+ {
7789
+ "schema": {
7790
+ "type": "string",
7791
+ "enum": [
7792
+ "pending",
7793
+ "active",
7794
+ "suspended",
7795
+ "archived"
7796
+ ]
7797
+ },
7798
+ "required": false,
7799
+ "name": "status",
7800
+ "in": "query"
7801
+ },
7802
+ {
7803
+ "schema": {
7804
+ "type": "string",
7805
+ "minLength": 1,
7806
+ "maxLength": 200
7807
+ },
7808
+ "required": false,
7809
+ "name": "search",
7810
+ "in": "query"
7811
+ },
7812
+ {
7813
+ "schema": {
7814
+ "type": "string",
7815
+ "pattern": "^\\d+$"
7816
+ },
7817
+ "required": false,
7818
+ "name": "limit",
7819
+ "in": "query"
7820
+ },
7821
+ {
7822
+ "schema": {
7823
+ "type": "string"
7824
+ },
7825
+ "required": false,
7826
+ "name": "cursor",
7827
+ "in": "query"
7828
+ }
7829
+ ],
7830
+ "responses": {
7831
+ "200": {
7832
+ "description": "Customer list",
7833
+ "content": {
7834
+ "application/json": {
7835
+ "schema": {
7836
+ "$ref": "#/components/schemas/ListCustomersResponse"
7837
+ }
7838
+ }
7839
+ }
7840
+ },
7841
+ "400": {
7842
+ "description": "Validation failure",
7843
+ "content": {
7844
+ "application/json": {
7845
+ "schema": {
7846
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7847
+ }
7848
+ }
7849
+ }
7850
+ },
7851
+ "401": {
7852
+ "description": "Authentication failure",
7853
+ "content": {
7854
+ "application/json": {
7855
+ "schema": {
7856
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7857
+ }
7858
+ }
7859
+ }
7860
+ },
7861
+ "429": {
7862
+ "description": "Rate limit exceeded",
7863
+ "content": {
7864
+ "application/json": {
7865
+ "schema": {
7866
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7867
+ }
7868
+ }
7869
+ }
7870
+ },
7871
+ "500": {
7872
+ "description": "Internal server error",
7873
+ "content": {
7874
+ "application/json": {
7875
+ "schema": {
7876
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7877
+ }
7878
+ }
7879
+ }
7880
+ }
7881
+ }
7882
+ },
7883
+ "post": {
7884
+ "tags": [
7885
+ "Customers"
7886
+ ],
7887
+ "summary": "Create a customer",
7888
+ "description": "Create a new end-customer. Starts in `pending` status; transitions to `active` when the first WhatsApp account is connected via a setup link.",
7889
+ "security": [
7890
+ {
7891
+ "bearerAuth": []
7892
+ }
7893
+ ],
7894
+ "requestBody": {
7895
+ "content": {
7896
+ "application/json": {
7897
+ "schema": {
7898
+ "type": "object",
7899
+ "properties": {
7900
+ "team_id": {
7901
+ "type": "string",
7902
+ "minLength": 1,
7903
+ "maxLength": 64
7904
+ },
7905
+ "name": {
7906
+ "type": "string",
7907
+ "minLength": 1,
7908
+ "maxLength": 200
7909
+ },
7910
+ "email": {
7911
+ "type": "string",
7912
+ "maxLength": 255,
7913
+ "format": "email"
7914
+ },
7915
+ "metadata": {
7916
+ "type": "object",
7917
+ "additionalProperties": {}
7918
+ }
7919
+ },
7920
+ "required": [
7921
+ "name"
7922
+ ]
7923
+ }
7924
+ }
7925
+ }
7926
+ },
7927
+ "responses": {
7928
+ "200": {
7929
+ "description": "Customer created",
7930
+ "content": {
7931
+ "application/json": {
7932
+ "schema": {
7933
+ "$ref": "#/components/schemas/CreateCustomerResponse"
7934
+ }
7935
+ }
7936
+ }
7937
+ },
7938
+ "400": {
7939
+ "description": "Validation failure",
7940
+ "content": {
7941
+ "application/json": {
7942
+ "schema": {
7943
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7944
+ }
7945
+ }
7946
+ }
7947
+ },
7948
+ "401": {
7949
+ "description": "Authentication failure",
7950
+ "content": {
7951
+ "application/json": {
7952
+ "schema": {
7953
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7954
+ }
7955
+ }
7956
+ }
7957
+ },
7958
+ "429": {
7959
+ "description": "Rate limit exceeded",
7960
+ "content": {
7961
+ "application/json": {
7962
+ "schema": {
7963
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7964
+ }
7965
+ }
7966
+ }
7967
+ },
7968
+ "500": {
7969
+ "description": "Internal server error",
7970
+ "content": {
7971
+ "application/json": {
7972
+ "schema": {
7973
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
7974
+ }
7975
+ }
7976
+ }
7977
+ }
7978
+ }
7979
+ }
7980
+ },
7981
+ "/customers/{id}": {
7982
+ "get": {
7983
+ "tags": [
7984
+ "Customers"
7985
+ ],
7986
+ "summary": "Fetch a customer by id",
7987
+ "security": [
7988
+ {
7989
+ "bearerAuth": []
7990
+ }
7991
+ ],
7992
+ "parameters": [
7993
+ {
7994
+ "schema": {
7995
+ "type": "string",
7996
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
7997
+ },
7998
+ "required": true,
7999
+ "name": "id",
8000
+ "in": "path"
8001
+ }
8002
+ ],
8003
+ "responses": {
8004
+ "200": {
8005
+ "description": "Customer resource (includes attached WhatsApp accounts)",
8006
+ "content": {
8007
+ "application/json": {
8008
+ "schema": {
8009
+ "$ref": "#/components/schemas/GetCustomerResponse"
8010
+ }
8011
+ }
8012
+ }
8013
+ },
8014
+ "400": {
8015
+ "description": "Validation failure",
8016
+ "content": {
8017
+ "application/json": {
8018
+ "schema": {
8019
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8020
+ }
8021
+ }
8022
+ }
8023
+ },
8024
+ "401": {
8025
+ "description": "Authentication failure",
8026
+ "content": {
8027
+ "application/json": {
8028
+ "schema": {
8029
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8030
+ }
8031
+ }
8032
+ }
8033
+ },
8034
+ "404": {
8035
+ "description": "Resource not found",
8036
+ "content": {
8037
+ "application/json": {
8038
+ "schema": {
8039
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8040
+ }
8041
+ }
8042
+ }
8043
+ },
8044
+ "429": {
8045
+ "description": "Rate limit exceeded",
8046
+ "content": {
8047
+ "application/json": {
8048
+ "schema": {
8049
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8050
+ }
8051
+ }
8052
+ }
8053
+ },
8054
+ "500": {
8055
+ "description": "Internal server error",
8056
+ "content": {
8057
+ "application/json": {
8058
+ "schema": {
8059
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8060
+ }
8061
+ }
8062
+ }
8063
+ }
8064
+ }
8065
+ },
8066
+ "patch": {
8067
+ "tags": [
8068
+ "Customers"
8069
+ ],
8070
+ "summary": "Update a customer",
8071
+ "security": [
8072
+ {
8073
+ "bearerAuth": []
8074
+ }
8075
+ ],
8076
+ "parameters": [
8077
+ {
8078
+ "schema": {
8079
+ "type": "string",
8080
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
8081
+ },
8082
+ "required": true,
8083
+ "name": "id",
8084
+ "in": "path"
8085
+ }
8086
+ ],
8087
+ "requestBody": {
8088
+ "content": {
8089
+ "application/json": {
8090
+ "schema": {
8091
+ "type": "object",
8092
+ "properties": {
8093
+ "name": {
8094
+ "type": "string",
8095
+ "minLength": 1,
8096
+ "maxLength": 200
8097
+ },
8098
+ "email": {
8099
+ "type": [
8100
+ "string",
8101
+ "null"
8102
+ ],
8103
+ "maxLength": 255,
8104
+ "format": "email"
8105
+ },
8106
+ "metadata": {
8107
+ "type": [
8108
+ "object",
8109
+ "null"
8110
+ ],
8111
+ "additionalProperties": {}
8112
+ },
8113
+ "status": {
8114
+ "type": "string",
8115
+ "enum": [
8116
+ "pending",
8117
+ "active",
8118
+ "suspended"
8119
+ ]
8120
+ }
8121
+ }
8122
+ }
8123
+ }
8124
+ }
8125
+ },
8126
+ "responses": {
8127
+ "200": {
8128
+ "description": "Updated customer",
8129
+ "content": {
8130
+ "application/json": {
8131
+ "schema": {
8132
+ "$ref": "#/components/schemas/UpdateCustomerResponse"
8133
+ }
8134
+ }
8135
+ }
8136
+ },
8137
+ "400": {
8138
+ "description": "Validation failure",
8139
+ "content": {
8140
+ "application/json": {
8141
+ "schema": {
8142
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8143
+ }
8144
+ }
8145
+ }
8146
+ },
8147
+ "401": {
8148
+ "description": "Authentication failure",
8149
+ "content": {
8150
+ "application/json": {
8151
+ "schema": {
8152
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8153
+ }
8154
+ }
8155
+ }
8156
+ },
8157
+ "404": {
8158
+ "description": "Resource not found",
8159
+ "content": {
8160
+ "application/json": {
8161
+ "schema": {
8162
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8163
+ }
8164
+ }
8165
+ }
8166
+ },
8167
+ "429": {
8168
+ "description": "Rate limit exceeded",
8169
+ "content": {
8170
+ "application/json": {
8171
+ "schema": {
8172
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8173
+ }
8174
+ }
8175
+ }
8176
+ },
8177
+ "500": {
8178
+ "description": "Internal server error",
8179
+ "content": {
8180
+ "application/json": {
8181
+ "schema": {
8182
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8183
+ }
8184
+ }
8185
+ }
8186
+ }
8187
+ }
8188
+ },
8189
+ "delete": {
8190
+ "tags": [
8191
+ "Customers"
8192
+ ],
8193
+ "summary": "Archive a customer",
8194
+ "description": "Soft-archives the customer. WhatsApp accounts previously assigned remain in the database with `customer_id` unchanged — message history is never destroyed.",
8195
+ "security": [
8196
+ {
8197
+ "bearerAuth": []
8198
+ }
8199
+ ],
8200
+ "parameters": [
8201
+ {
8202
+ "schema": {
8203
+ "type": "string",
8204
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
8205
+ },
8206
+ "required": true,
8207
+ "name": "id",
8208
+ "in": "path"
8209
+ }
8210
+ ],
8211
+ "responses": {
8212
+ "200": {
8213
+ "description": "Archived",
8214
+ "content": {
8215
+ "application/json": {
8216
+ "schema": {
8217
+ "$ref": "#/components/schemas/ArchiveCustomerResponse"
8218
+ }
8219
+ }
8220
+ }
8221
+ },
8222
+ "400": {
8223
+ "description": "Validation failure",
8224
+ "content": {
8225
+ "application/json": {
8226
+ "schema": {
8227
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8228
+ }
8229
+ }
8230
+ }
8231
+ },
8232
+ "401": {
8233
+ "description": "Authentication failure",
8234
+ "content": {
8235
+ "application/json": {
8236
+ "schema": {
8237
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8238
+ }
8239
+ }
8240
+ }
8241
+ },
8242
+ "404": {
8243
+ "description": "Resource not found",
8244
+ "content": {
8245
+ "application/json": {
8246
+ "schema": {
8247
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8248
+ }
8249
+ }
8250
+ }
8251
+ },
8252
+ "429": {
8253
+ "description": "Rate limit exceeded",
8254
+ "content": {
8255
+ "application/json": {
8256
+ "schema": {
8257
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8258
+ }
8259
+ }
8260
+ }
8261
+ },
8262
+ "500": {
8263
+ "description": "Internal server error",
8264
+ "content": {
8265
+ "application/json": {
8266
+ "schema": {
8267
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8268
+ }
8269
+ }
8270
+ }
8271
+ }
8272
+ }
8273
+ }
8274
+ },
8275
+ "/customers/{id}/setup_links": {
8276
+ "get": {
8277
+ "tags": [
8278
+ "Customers"
8279
+ ],
8280
+ "summary": "List setup links for a customer",
8281
+ "description": "Returns up to the 50 most-recent setup links — token plaintext is NEVER returned here (only at create time). Optional `status` query filters to `active` / `consumed` / `expired` / `revoked`.",
8282
+ "security": [
8283
+ {
8284
+ "bearerAuth": []
8285
+ }
8286
+ ],
8287
+ "parameters": [
8288
+ {
8289
+ "schema": {
8290
+ "type": "string",
8291
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
8292
+ },
8293
+ "required": true,
8294
+ "name": "id",
8295
+ "in": "path"
8296
+ },
8297
+ {
8298
+ "schema": {
8299
+ "type": "string",
8300
+ "enum": [
8301
+ "active",
8302
+ "consumed",
8303
+ "expired",
8304
+ "revoked"
8305
+ ]
8306
+ },
8307
+ "required": false,
8308
+ "name": "status",
8309
+ "in": "query"
8310
+ }
8311
+ ],
8312
+ "responses": {
8313
+ "200": {
8314
+ "description": "Setup link list",
8315
+ "content": {
8316
+ "application/json": {
8317
+ "schema": {
8318
+ "$ref": "#/components/schemas/ListCustomerSetupLinksResponse"
8319
+ }
8320
+ }
8321
+ }
8322
+ },
8323
+ "400": {
8324
+ "description": "Validation failure",
8325
+ "content": {
8326
+ "application/json": {
8327
+ "schema": {
8328
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8329
+ }
8330
+ }
8331
+ }
8332
+ },
8333
+ "401": {
8334
+ "description": "Authentication failure",
8335
+ "content": {
8336
+ "application/json": {
8337
+ "schema": {
8338
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8339
+ }
8340
+ }
8341
+ }
8342
+ },
8343
+ "404": {
8344
+ "description": "Resource not found",
8345
+ "content": {
8346
+ "application/json": {
8347
+ "schema": {
8348
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8349
+ }
8350
+ }
8351
+ }
8352
+ },
8353
+ "429": {
8354
+ "description": "Rate limit exceeded",
8355
+ "content": {
8356
+ "application/json": {
8357
+ "schema": {
8358
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8359
+ }
8360
+ }
8361
+ }
8362
+ },
8363
+ "500": {
8364
+ "description": "Internal server error",
8365
+ "content": {
8366
+ "application/json": {
8367
+ "schema": {
8368
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8369
+ }
8370
+ }
8371
+ }
8372
+ }
8373
+ }
8374
+ },
8375
+ "post": {
8376
+ "tags": [
8377
+ "Customers"
8378
+ ],
8379
+ "summary": "Generate a setup link",
8380
+ "description": "Creates a one-time setup link the end-customer can use to complete Meta Embedded Signup. The plaintext token and full setup URL are returned EXACTLY ONCE — store them immediately.",
8381
+ "security": [
8382
+ {
8383
+ "bearerAuth": []
8384
+ }
8385
+ ],
8386
+ "parameters": [
8387
+ {
8388
+ "schema": {
8389
+ "type": "string",
8390
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
8391
+ },
8392
+ "required": true,
8393
+ "name": "id",
8394
+ "in": "path"
8395
+ }
8396
+ ],
8397
+ "requestBody": {
8398
+ "content": {
8399
+ "application/json": {
8400
+ "schema": {
8401
+ "type": "object",
8402
+ "properties": {
8403
+ "expires_in_hours": {
8404
+ "type": "integer",
8405
+ "minimum": 1,
8406
+ "maximum": 720
8407
+ },
8408
+ "success_redirect_url": {
8409
+ "type": "string",
8410
+ "maxLength": 2048,
8411
+ "format": "uri"
8412
+ },
8413
+ "failure_redirect_url": {
8414
+ "type": "string",
8415
+ "maxLength": 2048,
8416
+ "format": "uri"
8417
+ }
8418
+ }
8419
+ }
8420
+ }
8421
+ }
8422
+ },
8423
+ "responses": {
8424
+ "200": {
8425
+ "description": "Setup link created (token returned ONCE)",
8426
+ "content": {
8427
+ "application/json": {
8428
+ "schema": {
8429
+ "$ref": "#/components/schemas/CreateCustomerSetupLinkResponse"
8430
+ }
8431
+ }
8432
+ }
8433
+ },
8434
+ "400": {
8435
+ "description": "Validation failure",
8436
+ "content": {
8437
+ "application/json": {
8438
+ "schema": {
8439
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8440
+ }
8441
+ }
8442
+ }
8443
+ },
8444
+ "401": {
8445
+ "description": "Authentication failure",
8446
+ "content": {
8447
+ "application/json": {
8448
+ "schema": {
8449
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8450
+ }
8451
+ }
8452
+ }
8453
+ },
8454
+ "404": {
8455
+ "description": "Resource not found",
8456
+ "content": {
8457
+ "application/json": {
8458
+ "schema": {
8459
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8460
+ }
8461
+ }
8462
+ }
8463
+ },
8464
+ "429": {
8465
+ "description": "Rate limit exceeded",
8466
+ "content": {
8467
+ "application/json": {
8468
+ "schema": {
8469
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8470
+ }
8471
+ }
8472
+ }
8473
+ },
8474
+ "500": {
8475
+ "description": "Internal server error",
8476
+ "content": {
8477
+ "application/json": {
8478
+ "schema": {
8479
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8480
+ }
8481
+ }
8482
+ }
8483
+ }
8484
+ }
8485
+ }
8486
+ },
8487
+ "/customers/{id}/setup_links/{link_id}": {
8488
+ "patch": {
8489
+ "tags": [
8490
+ "Customers"
8491
+ ],
8492
+ "summary": "Update redirect URLs on an active setup link",
8493
+ "description": "Recover from a typo in `success_redirect_url` / `failure_redirect_url` without revoking and regenerating the link. Only works while `status = active`; pass `null` to clear a redirect.",
8494
+ "security": [
8495
+ {
8496
+ "bearerAuth": []
8497
+ }
8498
+ ],
8499
+ "parameters": [
8500
+ {
8501
+ "schema": {
8502
+ "type": "string",
8503
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
8504
+ },
8505
+ "required": true,
8506
+ "name": "id",
8507
+ "in": "path"
8508
+ },
8509
+ {
8510
+ "schema": {
8511
+ "type": "string",
8512
+ "pattern": "^csl_[0-9A-HJKMNP-TV-Z]{26}$"
8513
+ },
8514
+ "required": true,
8515
+ "name": "link_id",
8516
+ "in": "path"
8517
+ }
8518
+ ],
8519
+ "requestBody": {
8520
+ "content": {
8521
+ "application/json": {
8522
+ "schema": {
8523
+ "type": "object",
8524
+ "properties": {
8525
+ "success_redirect_url": {
8526
+ "anyOf": [
8527
+ {
8528
+ "type": "string",
8529
+ "maxLength": 2048,
8530
+ "format": "uri"
8531
+ },
8532
+ {
8533
+ "type": "null"
8534
+ }
8535
+ ]
8536
+ },
8537
+ "failure_redirect_url": {
8538
+ "anyOf": [
8539
+ {
8540
+ "type": "string",
8541
+ "maxLength": 2048,
8542
+ "format": "uri"
8543
+ },
8544
+ {
8545
+ "type": "null"
8546
+ }
8547
+ ]
8548
+ }
8549
+ }
8550
+ }
8551
+ }
8552
+ }
8553
+ },
8554
+ "responses": {
8555
+ "200": {
8556
+ "description": "Updated setup link",
8557
+ "content": {
8558
+ "application/json": {
8559
+ "schema": {
8560
+ "$ref": "#/components/schemas/UpdateCustomerSetupLinkResponse"
8561
+ }
8562
+ }
8563
+ }
8564
+ },
8565
+ "400": {
8566
+ "description": "Validation failure",
8567
+ "content": {
8568
+ "application/json": {
8569
+ "schema": {
8570
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8571
+ }
8572
+ }
8573
+ }
8574
+ },
8575
+ "401": {
8576
+ "description": "Authentication failure",
8577
+ "content": {
8578
+ "application/json": {
8579
+ "schema": {
8580
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8581
+ }
8582
+ }
8583
+ }
8584
+ },
8585
+ "404": {
8586
+ "description": "Resource not found",
8587
+ "content": {
8588
+ "application/json": {
8589
+ "schema": {
8590
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8591
+ }
8592
+ }
8593
+ }
8594
+ },
8595
+ "409": {
8596
+ "description": "Conflict (e.g. webhook subscription disabled)",
8597
+ "content": {
8598
+ "application/json": {
8599
+ "schema": {
8600
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8601
+ }
8602
+ }
8603
+ }
8604
+ },
8605
+ "429": {
8606
+ "description": "Rate limit exceeded",
8607
+ "content": {
8608
+ "application/json": {
8609
+ "schema": {
8610
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8611
+ }
8612
+ }
8613
+ }
8614
+ },
8615
+ "500": {
8616
+ "description": "Internal server error",
8617
+ "content": {
8618
+ "application/json": {
8619
+ "schema": {
8620
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8621
+ }
8622
+ }
8623
+ }
8624
+ }
8625
+ }
8626
+ },
8627
+ "delete": {
8628
+ "tags": [
8629
+ "Customers"
8630
+ ],
8631
+ "summary": "Revoke a setup link",
8632
+ "description": "Revoke a still-active link. Already-consumed or already-revoked links return `409`.",
8633
+ "security": [
8634
+ {
8635
+ "bearerAuth": []
8636
+ }
8637
+ ],
8638
+ "parameters": [
8639
+ {
8640
+ "schema": {
8641
+ "type": "string",
8642
+ "pattern": "^cus_[0-9A-HJKMNP-TV-Z]{26}$"
8643
+ },
8644
+ "required": true,
8645
+ "name": "id",
8646
+ "in": "path"
8647
+ },
8648
+ {
8649
+ "schema": {
8650
+ "type": "string",
8651
+ "pattern": "^csl_[0-9A-HJKMNP-TV-Z]{26}$"
8652
+ },
8653
+ "required": true,
8654
+ "name": "link_id",
8655
+ "in": "path"
8656
+ }
8657
+ ],
8658
+ "responses": {
8659
+ "200": {
8660
+ "description": "Revoked",
8661
+ "content": {
8662
+ "application/json": {
8663
+ "schema": {
8664
+ "$ref": "#/components/schemas/RevokeCustomerSetupLinkResponse"
8665
+ }
8666
+ }
8667
+ }
8668
+ },
8669
+ "400": {
8670
+ "description": "Validation failure",
8671
+ "content": {
8672
+ "application/json": {
8673
+ "schema": {
8674
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8675
+ }
8676
+ }
8677
+ }
8678
+ },
8679
+ "401": {
8680
+ "description": "Authentication failure",
8681
+ "content": {
8682
+ "application/json": {
8683
+ "schema": {
8684
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8685
+ }
8686
+ }
8687
+ }
8688
+ },
8689
+ "404": {
8690
+ "description": "Resource not found",
8691
+ "content": {
8692
+ "application/json": {
8693
+ "schema": {
8694
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8695
+ }
8696
+ }
8697
+ }
8698
+ },
8699
+ "409": {
8700
+ "description": "Conflict (e.g. webhook subscription disabled)",
8701
+ "content": {
8702
+ "application/json": {
8703
+ "schema": {
8704
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8705
+ }
8706
+ }
8707
+ }
8708
+ },
8709
+ "429": {
8710
+ "description": "Rate limit exceeded",
8711
+ "content": {
8712
+ "application/json": {
8713
+ "schema": {
8714
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8715
+ }
8716
+ }
8717
+ }
8718
+ },
8719
+ "500": {
8720
+ "description": "Internal server error",
8721
+ "content": {
8722
+ "application/json": {
8723
+ "schema": {
8724
+ "$ref": "#/components/schemas/ApiErrorEnvelope"
8725
+ }
8726
+ }
8727
+ }
8728
+ }
8729
+ }
8730
+ }
7137
8731
  }
7138
8732
  },
7139
8733
  "webhooks": {}