@greatwait/contracts 0.1.0-alpha.1

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.
Files changed (241) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/dist/authority.d.ts +217 -0
  4. package/dist/authority.js +261 -0
  5. package/dist/callback-ownership.d.ts +58 -0
  6. package/dist/callback-ownership.js +71 -0
  7. package/dist/callback-safety.d.ts +38 -0
  8. package/dist/callback-safety.js +403 -0
  9. package/dist/compatibility.d.ts +82 -0
  10. package/dist/compatibility.js +115 -0
  11. package/dist/delivery.d.ts +401 -0
  12. package/dist/delivery.js +311 -0
  13. package/dist/endpoints.d.ts +305 -0
  14. package/dist/endpoints.js +179 -0
  15. package/dist/events.d.ts +62 -0
  16. package/dist/events.js +38 -0
  17. package/dist/first-value-journey.d.ts +305 -0
  18. package/dist/first-value-journey.js +466 -0
  19. package/dist/forecast.d.ts +443 -0
  20. package/dist/forecast.js +729 -0
  21. package/dist/identifiers.d.ts +109 -0
  22. package/dist/identifiers.js +131 -0
  23. package/dist/identity.d.ts +196 -0
  24. package/dist/identity.js +182 -0
  25. package/dist/index.d.ts +27 -0
  26. package/dist/index.js +27 -0
  27. package/dist/mcp.d.ts +51 -0
  28. package/dist/mcp.js +56 -0
  29. package/dist/oauth.d.ts +796 -0
  30. package/dist/oauth.js +708 -0
  31. package/dist/operations.d.ts +3985 -0
  32. package/dist/operations.js +1837 -0
  33. package/dist/partition.d.ts +771 -0
  34. package/dist/partition.js +206 -0
  35. package/dist/policy.d.ts +93 -0
  36. package/dist/policy.js +180 -0
  37. package/dist/problems.d.ts +158 -0
  38. package/dist/problems.js +104 -0
  39. package/dist/protocol.d.ts +308 -0
  40. package/dist/protocol.js +515 -0
  41. package/dist/scheduling-records.d.ts +395 -0
  42. package/dist/scheduling-records.js +284 -0
  43. package/dist/scheduling.d.ts +1098 -0
  44. package/dist/scheduling.js +1116 -0
  45. package/dist/secrets.d.ts +383 -0
  46. package/dist/secrets.js +272 -0
  47. package/dist/signatures.d.ts +704 -0
  48. package/dist/signatures.js +867 -0
  49. package/dist/tenancy.d.ts +178 -0
  50. package/dist/tenancy.js +145 -0
  51. package/dist/test-sink.d.ts +986 -0
  52. package/dist/test-sink.js +755 -0
  53. package/dist/time.d.ts +45 -0
  54. package/dist/time.js +128 -0
  55. package/dist/usage.d.ts +121 -0
  56. package/dist/usage.js +200 -0
  57. package/dist/webhooks.d.ts +116 -0
  58. package/dist/webhooks.js +161 -0
  59. package/dist/workspace.d.ts +92 -0
  60. package/dist/workspace.js +59 -0
  61. package/generated/v1/callback-delivery-signature.json +467 -0
  62. package/generated/v1/callback-endpoint-verification.json +59 -0
  63. package/generated/v1/callback-receiver.json +241 -0
  64. package/generated/v1/examples/attempts.list.response.json +24 -0
  65. package/generated/v1/examples/attempts.read.response.json +20 -0
  66. package/generated/v1/examples/credentials.create.request.json +5 -0
  67. package/generated/v1/examples/credentials.create.response.json +10 -0
  68. package/generated/v1/examples/credentials.list.response.json +17 -0
  69. package/generated/v1/examples/credentials.revoke.response.json +11 -0
  70. package/generated/v1/examples/credentials.rotate.request.json +3 -0
  71. package/generated/v1/examples/credentials.rotate.response.json +22 -0
  72. package/generated/v1/examples/endpoints.create.request.json +3 -0
  73. package/generated/v1/examples/endpoints.create.response.json +16 -0
  74. package/generated/v1/examples/endpoints.disable.response.json +15 -0
  75. package/generated/v1/examples/endpoints.list.response.json +21 -0
  76. package/generated/v1/examples/endpoints.read.response.json +14 -0
  77. package/generated/v1/examples/endpoints.rotateSigningKey.request.json +3 -0
  78. package/generated/v1/examples/endpoints.rotateSigningKey.response.json +23 -0
  79. package/generated/v1/examples/endpoints.update.request.json +3 -0
  80. package/generated/v1/examples/endpoints.update.response.json +13 -0
  81. package/generated/v1/examples/endpoints.verify.response.json +15 -0
  82. package/generated/v1/examples/forecast.read.response.json +28 -0
  83. package/generated/v1/examples/forecast.windows.response.json +21 -0
  84. package/generated/v1/examples/grants.list.response.json +17 -0
  85. package/generated/v1/examples/grants.revoke.response.json +16 -0
  86. package/generated/v1/examples/meta.scaffold.response.json +5 -0
  87. package/generated/v1/examples/meta.version.response.json +5 -0
  88. package/generated/v1/examples/occurrences.list.response.json +17 -0
  89. package/generated/v1/examples/occurrences.read.response.json +15 -0
  90. package/generated/v1/examples/occurrences.redeliver.response.json +16 -0
  91. package/generated/v1/examples/projects.create.request.json +3 -0
  92. package/generated/v1/examples/projects.create.response.json +5 -0
  93. package/generated/v1/examples/projects.list.response.json +9 -0
  94. package/generated/v1/examples/schedules.archive.response.json +25 -0
  95. package/generated/v1/examples/schedules.cancel.response.json +24 -0
  96. package/generated/v1/examples/schedules.create.request.json +9 -0
  97. package/generated/v1/examples/schedules.create.response.json +25 -0
  98. package/generated/v1/examples/schedules.list.response.json +23 -0
  99. package/generated/v1/examples/schedules.pause.response.json +23 -0
  100. package/generated/v1/examples/schedules.read.response.json +25 -0
  101. package/generated/v1/examples/schedules.replace.request.json +8 -0
  102. package/generated/v1/examples/schedules.replace.response.json +25 -0
  103. package/generated/v1/examples/schedules.resume.response.json +23 -0
  104. package/generated/v1/examples/sinkdeliveries.list.response.json +19 -0
  105. package/generated/v1/examples/sinkdeliveries.read.response.json +16 -0
  106. package/generated/v1/examples/testsinks.configure.request.json +3 -0
  107. package/generated/v1/examples/testsinks.configure.response.json +13 -0
  108. package/generated/v1/examples/testsinks.create.request.json +8 -0
  109. package/generated/v1/examples/testsinks.create.response.json +13 -0
  110. package/generated/v1/examples/testsinks.delete.response.json +13 -0
  111. package/generated/v1/examples/testsinks.list.response.json +20 -0
  112. package/generated/v1/examples/testsinks.read.response.json +14 -0
  113. package/generated/v1/examples/usage.read.response.json +20 -0
  114. package/generated/v1/first-value-journey.json +436 -0
  115. package/generated/v1/manifest.json +1037 -0
  116. package/generated/v1/openapi.json +23665 -0
  117. package/generated/v1/policy-matrix.json +305 -0
  118. package/generated/v1/schemas/attempts.list.query.json +16 -0
  119. package/generated/v1/schemas/attempts.list.response.json +175 -0
  120. package/generated/v1/schemas/attempts.read.response.json +168 -0
  121. package/generated/v1/schemas/credentials.create.request.json +39 -0
  122. package/generated/v1/schemas/credentials.create.response.json +88 -0
  123. package/generated/v1/schemas/credentials.list.query.json +16 -0
  124. package/generated/v1/schemas/credentials.list.response.json +124 -0
  125. package/generated/v1/schemas/credentials.revoke.response.json +84 -0
  126. package/generated/v1/schemas/credentials.rotate.request.json +11 -0
  127. package/generated/v1/schemas/credentials.rotate.response.json +171 -0
  128. package/generated/v1/schemas/endpoints.create.request.json +12 -0
  129. package/generated/v1/schemas/endpoints.create.response.json +115 -0
  130. package/generated/v1/schemas/endpoints.disable.response-headers.json +11 -0
  131. package/generated/v1/schemas/endpoints.disable.response.json +100 -0
  132. package/generated/v1/schemas/endpoints.list.query.json +16 -0
  133. package/generated/v1/schemas/endpoints.list.response.json +146 -0
  134. package/generated/v1/schemas/endpoints.read.response-headers.json +11 -0
  135. package/generated/v1/schemas/endpoints.read.response.json +100 -0
  136. package/generated/v1/schemas/endpoints.rotateSigningKey.request-headers.json +10 -0
  137. package/generated/v1/schemas/endpoints.rotateSigningKey.request.json +11 -0
  138. package/generated/v1/schemas/endpoints.rotateSigningKey.response-headers.json +11 -0
  139. package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +118 -0
  140. package/generated/v1/schemas/endpoints.update.request-headers.json +10 -0
  141. package/generated/v1/schemas/endpoints.update.request.json +12 -0
  142. package/generated/v1/schemas/endpoints.update.response-headers.json +11 -0
  143. package/generated/v1/schemas/endpoints.update.response.json +100 -0
  144. package/generated/v1/schemas/endpoints.verify.request-headers.json +10 -0
  145. package/generated/v1/schemas/endpoints.verify.response-headers.json +11 -0
  146. package/generated/v1/schemas/endpoints.verify.response.json +100 -0
  147. package/generated/v1/schemas/forecast.read.query.json +26 -0
  148. package/generated/v1/schemas/forecast.read.response.json +100 -0
  149. package/generated/v1/schemas/forecast.windows.query.json +26 -0
  150. package/generated/v1/schemas/forecast.windows.response.json +94 -0
  151. package/generated/v1/schemas/grants.list.response.json +98 -0
  152. package/generated/v1/schemas/grants.revoke.response.json +95 -0
  153. package/generated/v1/schemas/meta.scaffold.response.json +36 -0
  154. package/generated/v1/schemas/meta.version.response.json +19 -0
  155. package/generated/v1/schemas/occurrences.list.query.json +16 -0
  156. package/generated/v1/schemas/occurrences.list.response.json +83 -0
  157. package/generated/v1/schemas/occurrences.read.response.json +76 -0
  158. package/generated/v1/schemas/occurrences.redeliver.request-headers.json +13 -0
  159. package/generated/v1/schemas/occurrences.redeliver.response-headers.json +10 -0
  160. package/generated/v1/schemas/occurrences.redeliver.response.json +168 -0
  161. package/generated/v1/schemas/projects.create.request.json +12 -0
  162. package/generated/v1/schemas/projects.create.response.json +25 -0
  163. package/generated/v1/schemas/projects.list.response.json +35 -0
  164. package/generated/v1/schemas/schedules.archive.request-headers.json +10 -0
  165. package/generated/v1/schemas/schedules.archive.response-headers.json +11 -0
  166. package/generated/v1/schemas/schedules.archive.response.json +189 -0
  167. package/generated/v1/schemas/schedules.cancel.request-headers.json +10 -0
  168. package/generated/v1/schemas/schedules.cancel.response-headers.json +11 -0
  169. package/generated/v1/schemas/schedules.cancel.response.json +189 -0
  170. package/generated/v1/schemas/schedules.create.request-headers.json +12 -0
  171. package/generated/v1/schemas/schedules.create.request.json +99 -0
  172. package/generated/v1/schemas/schedules.create.response-headers.json +15 -0
  173. package/generated/v1/schemas/schedules.create.response.json +189 -0
  174. package/generated/v1/schemas/schedules.list.query.json +16 -0
  175. package/generated/v1/schemas/schedules.list.response.json +170 -0
  176. package/generated/v1/schemas/schedules.pause.request-headers.json +10 -0
  177. package/generated/v1/schemas/schedules.pause.response-headers.json +11 -0
  178. package/generated/v1/schemas/schedules.pause.response.json +189 -0
  179. package/generated/v1/schemas/schedules.read.response-headers.json +11 -0
  180. package/generated/v1/schemas/schedules.read.response.json +189 -0
  181. package/generated/v1/schemas/schedules.replace.request-headers.json +10 -0
  182. package/generated/v1/schemas/schedules.replace.request.json +99 -0
  183. package/generated/v1/schemas/schedules.replace.response-headers.json +11 -0
  184. package/generated/v1/schemas/schedules.replace.response.json +189 -0
  185. package/generated/v1/schemas/schedules.resume.request-headers.json +10 -0
  186. package/generated/v1/schemas/schedules.resume.response-headers.json +11 -0
  187. package/generated/v1/schemas/schedules.resume.response.json +189 -0
  188. package/generated/v1/schemas/sinkdeliveries.list.query.json +16 -0
  189. package/generated/v1/schemas/sinkdeliveries.list.response.json +126 -0
  190. package/generated/v1/schemas/sinkdeliveries.read.response.json +98 -0
  191. package/generated/v1/schemas/testsinks.configure.request.json +66 -0
  192. package/generated/v1/schemas/testsinks.configure.response.json +115 -0
  193. package/generated/v1/schemas/testsinks.create.request.json +76 -0
  194. package/generated/v1/schemas/testsinks.create.response.json +115 -0
  195. package/generated/v1/schemas/testsinks.delete.response.json +115 -0
  196. package/generated/v1/schemas/testsinks.list.query.json +16 -0
  197. package/generated/v1/schemas/testsinks.list.response.json +161 -0
  198. package/generated/v1/schemas/testsinks.read.response.json +115 -0
  199. package/generated/v1/schemas/usage.read.query.json +15 -0
  200. package/generated/v1/schemas/usage.read.response.json +71 -0
  201. package/generated/v1/snippets/attempts.list.json +5 -0
  202. package/generated/v1/snippets/attempts.read.json +5 -0
  203. package/generated/v1/snippets/credentials.create.json +5 -0
  204. package/generated/v1/snippets/credentials.list.json +5 -0
  205. package/generated/v1/snippets/credentials.revoke.json +5 -0
  206. package/generated/v1/snippets/credentials.rotate.json +5 -0
  207. package/generated/v1/snippets/endpoints.create.json +5 -0
  208. package/generated/v1/snippets/endpoints.disable.json +5 -0
  209. package/generated/v1/snippets/endpoints.list.json +5 -0
  210. package/generated/v1/snippets/endpoints.read.json +5 -0
  211. package/generated/v1/snippets/endpoints.rotateSigningKey.json +5 -0
  212. package/generated/v1/snippets/endpoints.update.json +5 -0
  213. package/generated/v1/snippets/endpoints.verify.json +5 -0
  214. package/generated/v1/snippets/forecast.read.json +5 -0
  215. package/generated/v1/snippets/forecast.windows.json +5 -0
  216. package/generated/v1/snippets/grants.list.json +5 -0
  217. package/generated/v1/snippets/grants.revoke.json +5 -0
  218. package/generated/v1/snippets/meta.scaffold.json +5 -0
  219. package/generated/v1/snippets/meta.version.json +5 -0
  220. package/generated/v1/snippets/occurrences.list.json +5 -0
  221. package/generated/v1/snippets/occurrences.read.json +5 -0
  222. package/generated/v1/snippets/occurrences.redeliver.json +5 -0
  223. package/generated/v1/snippets/projects.create.json +5 -0
  224. package/generated/v1/snippets/projects.list.json +5 -0
  225. package/generated/v1/snippets/schedules.archive.json +5 -0
  226. package/generated/v1/snippets/schedules.cancel.json +5 -0
  227. package/generated/v1/snippets/schedules.create.json +5 -0
  228. package/generated/v1/snippets/schedules.list.json +5 -0
  229. package/generated/v1/snippets/schedules.pause.json +5 -0
  230. package/generated/v1/snippets/schedules.read.json +5 -0
  231. package/generated/v1/snippets/schedules.replace.json +5 -0
  232. package/generated/v1/snippets/schedules.resume.json +5 -0
  233. package/generated/v1/snippets/sinkdeliveries.list.json +5 -0
  234. package/generated/v1/snippets/sinkdeliveries.read.json +5 -0
  235. package/generated/v1/snippets/testsinks.configure.json +5 -0
  236. package/generated/v1/snippets/testsinks.create.json +5 -0
  237. package/generated/v1/snippets/testsinks.delete.json +5 -0
  238. package/generated/v1/snippets/testsinks.list.json +5 -0
  239. package/generated/v1/snippets/testsinks.read.json +5 -0
  240. package/generated/v1/snippets/usage.read.json +5 -0
  241. package/package.json +153 -0
@@ -0,0 +1,436 @@
1
+ {
2
+ "contractVersion": "2026-08-22",
3
+ "prerequisites": [
4
+ {
5
+ "action": "Accept your Greatwait invitation, sign in, and create a project in the dashboard.",
6
+ "because": "projects.create accepts only a signed-in member, so a project is created by a person rather than by an API credential.",
7
+ "id": "project",
8
+ "title": "A project"
9
+ },
10
+ {
11
+ "action": "In that project, create an API credential and copy the secret it shows once.",
12
+ "because": "credentials.create accepts only a signed-in member: a credential that could mint another credential would make revoking one meaningless.",
13
+ "id": "credential",
14
+ "title": "An API credential"
15
+ },
16
+ {
17
+ "action": "Have an HTTPS URL of your own that answers POST with a 2xx status, and can be reached from the public internet.",
18
+ "because": "Greatwait delivers your callback to an address you control. It does not offer a shared receiver to try, and it will not send your payload to a third-party inspection service on your behalf.",
19
+ "id": "receiver",
20
+ "title": "An HTTPS receiver you control"
21
+ }
22
+ ],
23
+ "steps": [
24
+ {
25
+ "capture": [],
26
+ "key": "check-service",
27
+ "method": "GET",
28
+ "observe": "The service name and the environment you meant to work in. If the environment is not the one you expect, stop and fix GREATWAIT_API_URL before creating anything.",
29
+ "operationId": "meta.version",
30
+ "path": "/__greatwait/version",
31
+ "purpose": "Confirms the origin you are pointed at is a Greatwait API and says which environment it serves. It needs no credential, so it separates 'wrong URL' from 'wrong key'.",
32
+ "recovery": [
33
+ {
34
+ "nextMove": "Something answered, but not this service. Check GREATWAIT_API_URL — a 404 here comes from a proxy in front of the API rather than from the API, so it carries no problem document to read.",
35
+ "when": "unexpected-answer"
36
+ },
37
+ {
38
+ "nextMove": "The origin did not answer. Check the hostname and that you can reach it from this network before going further.",
39
+ "when": "no-response"
40
+ }
41
+ ],
42
+ "problems": ["rate_limited", "service_unavailable"],
43
+ "scopes": [],
44
+ "successStatus": 200,
45
+ "title": "Check which service and environment you reached",
46
+ "variables": []
47
+ },
48
+ {
49
+ "capture": [],
50
+ "key": "check-credential",
51
+ "method": "GET",
52
+ "observe": "An empty page on a new project, or your existing schedules. Either way the credential is accepted and carries the scopes this journey needs.",
53
+ "operationId": "schedules.list",
54
+ "path": "/v1/schedules",
55
+ "purpose": "Proves the credential works and is bound to the project you think it is, before you create anything with it. A credential names exactly one project, and this is the cheapest call that says so.",
56
+ "query": {
57
+ "limit": "1"
58
+ },
59
+ "recovery": [
60
+ {
61
+ "nextMove": "No credential reached the service. Export GREATWAIT_API_KEY in this shell and try again.",
62
+ "when": "authentication_required"
63
+ },
64
+ {
65
+ "nextMove": "The credential was revoked. Create a new one in the dashboard; a revoked credential never comes back.",
66
+ "when": "credential_revoked"
67
+ },
68
+ {
69
+ "nextMove": "The credential expired. Rotate it in the dashboard and export the new secret.",
70
+ "when": "credential_expired"
71
+ },
72
+ {
73
+ "nextMove": "The credential is missing schedules:read. Create one with the scopes this journey needs rather than widening this one.",
74
+ "when": "scope_missing"
75
+ }
76
+ ],
77
+ "problems": [
78
+ "authentication_required",
79
+ "credential_expired",
80
+ "credential_revoked",
81
+ "invalid_request",
82
+ "rate_limited",
83
+ "scope_missing",
84
+ "service_unavailable"
85
+ ],
86
+ "scopes": ["schedules:read"],
87
+ "successStatus": 200,
88
+ "title": "Check the credential",
89
+ "variables": []
90
+ },
91
+ {
92
+ "capture": [
93
+ {
94
+ "from": "id",
95
+ "kind": "body",
96
+ "secret": false,
97
+ "variable": "GREATWAIT_ENDPOINTID"
98
+ },
99
+ {
100
+ "from": "secret",
101
+ "kind": "body",
102
+ "secret": true,
103
+ "variable": "GREATWAIT_ENDPOINT_SECRET"
104
+ }
105
+ ],
106
+ "key": "create-destination",
107
+ "method": "POST",
108
+ "observe": "An endpoint identifier, and a signing secret returned by this call and by no other. Store the secret now: reading the endpoint back later will not show it again.",
109
+ "operationId": "endpoints.create",
110
+ "path": "/v1/endpoints",
111
+ "purpose": "Registers the address every occurrence of this schedule is delivered to, and mints the per-endpoint signing key your receiver verifies callbacks with.",
112
+ "recovery": [
113
+ {
114
+ "nextMove": "The URL was refused. It must be HTTPS on port 443, carry no credentials or fragment, and resolve to a public address — a localhost or private-range host cannot be reached from the service.",
115
+ "when": "invalid_request"
116
+ },
117
+ {
118
+ "nextMove": "This project is at its destination ceiling. Disable a destination you no longer deliver to; disabled ones still count, because they stay readable for audit.",
119
+ "when": "plan_limit_reached"
120
+ }
121
+ ],
122
+ "request": {
123
+ "url": "{{GREATWAIT_RECEIVER_URL}}"
124
+ },
125
+ "problems": [
126
+ "authentication_required",
127
+ "credential_expired",
128
+ "credential_revoked",
129
+ "invalid_request",
130
+ "plan_limit_reached",
131
+ "rate_limited",
132
+ "scope_missing",
133
+ "service_unavailable"
134
+ ],
135
+ "scopes": ["endpoints:write"],
136
+ "successStatus": 201,
137
+ "title": "Create the destination",
138
+ "variables": ["GREATWAIT_RECEIVER_URL"]
139
+ },
140
+ {
141
+ "capture": [
142
+ {
143
+ "from": "schedule.id",
144
+ "kind": "body",
145
+ "secret": false,
146
+ "variable": "GREATWAIT_SCHEDULEID"
147
+ },
148
+ {
149
+ "from": "occurrence.id",
150
+ "kind": "body",
151
+ "secret": false,
152
+ "variable": "GREATWAIT_OCCURRENCEID"
153
+ }
154
+ ],
155
+ "key": "create-one-shot",
156
+ "method": "POST",
157
+ "observe": "A schedule whose recurrence kind is `at`, and its first occurrence in state `planned` with the instant your delay resolved to.",
158
+ "operationId": "schedules.create",
159
+ "path": "/v1/schedules",
160
+ "purpose": "Creates the one-shot. The delay is converted to an absolute instant when the request is accepted, so the schedule reads back the same afterwards however it was expressed.",
161
+ "recovery": [
162
+ {
163
+ "nextMove": "This deployment requires a destination to answer its ownership challenge before anything is delivered there, and yours has not. Answer the challenge with the secret the create call returned, then create the schedule.",
164
+ "when": "endpoint_unverified"
165
+ },
166
+ {
167
+ "nextMove": "The endpoint identifier is not one this credential's project can deliver to — it belongs to another project, or it has been disabled. Disabling is terminal, so create a new destination rather than trying to re-enable that one.",
168
+ "when": "not_found"
169
+ },
170
+ {
171
+ "nextMove": "The same idempotency key was used for a different request. Use a new key, or send the byte-identical body the key was first used with.",
172
+ "when": "idempotency_key_reused"
173
+ },
174
+ {
175
+ "nextMove": "Give exactly one of at, delaySeconds, everySeconds and cron, and make sure the endpoint identifier is one this credential's project owns.",
176
+ "when": "invalid_request"
177
+ },
178
+ {
179
+ "nextMove": "This organization is at a plan ceiling — live schedules, distinct partition keys, or payload size. Nothing was created; reduce the payload or archive a schedule and retry.",
180
+ "when": "plan_limit_reached"
181
+ },
182
+ {
183
+ "nextMove": "The service could not accept the schedule right now. This is safe to retry with the same idempotency key, which is what the key is for.",
184
+ "when": "service_unavailable"
185
+ }
186
+ ],
187
+ "request": {
188
+ "data": {
189
+ "greeting": "first value"
190
+ },
191
+ "delaySeconds": 30,
192
+ "endpoint": "{{GREATWAIT_ENDPOINTID}}"
193
+ },
194
+ "requestHeaders": {
195
+ "Idempotency-Key": "{{GREATWAIT_IDEMPOTENCY_KEY}}"
196
+ },
197
+ "problems": [
198
+ "authentication_required",
199
+ "credential_expired",
200
+ "credential_revoked",
201
+ "endpoint_unverified",
202
+ "idempotency_key_reused",
203
+ "invalid_request",
204
+ "not_found",
205
+ "plan_limit_reached",
206
+ "rate_limited",
207
+ "scope_missing",
208
+ "service_unavailable"
209
+ ],
210
+ "scopes": ["schedules:write"],
211
+ "successStatus": 201,
212
+ "title": "Create the one-shot",
213
+ "variables": ["GREATWAIT_ENDPOINTID", "GREATWAIT_IDEMPOTENCY_KEY"]
214
+ },
215
+ {
216
+ "capture": [
217
+ {
218
+ "from": "Idempotency-Replayed",
219
+ "kind": "header",
220
+ "secret": false,
221
+ "variable": "GREATWAIT_REPLAYED"
222
+ },
223
+ {
224
+ "from": "schedule.id",
225
+ "kind": "body",
226
+ "secret": false,
227
+ "variable": "GREATWAIT_REPLAYED_SCHEDULEID"
228
+ }
229
+ ],
230
+ "key": "replay-one-shot",
231
+ "method": "POST",
232
+ "observe": "The identical schedule identifier and an `Idempotency-Replayed: true` response header. Nothing was created the second time, and no second callback will be delivered.",
233
+ "operationId": "schedules.create",
234
+ "path": "/v1/schedules",
235
+ "purpose": "Repeats the previous call byte for byte, with the same key. This is the retry a network failure would have made for you, and it is the reason a create is safe to retry at all.",
236
+ "recovery": [
237
+ {
238
+ "nextMove": "The body differed from the first call. A replay must be byte-identical; a changed body with a used key is a conflict rather than a second write.",
239
+ "when": "idempotency_key_reused"
240
+ }
241
+ ],
242
+ "request": {
243
+ "data": {
244
+ "greeting": "first value"
245
+ },
246
+ "delaySeconds": 30,
247
+ "endpoint": "{{GREATWAIT_ENDPOINTID}}"
248
+ },
249
+ "requestHeaders": {
250
+ "Idempotency-Key": "{{GREATWAIT_IDEMPOTENCY_KEY}}"
251
+ },
252
+ "problems": [
253
+ "authentication_required",
254
+ "credential_expired",
255
+ "credential_revoked",
256
+ "endpoint_unverified",
257
+ "idempotency_key_reused",
258
+ "invalid_request",
259
+ "not_found",
260
+ "plan_limit_reached",
261
+ "rate_limited",
262
+ "scope_missing",
263
+ "service_unavailable"
264
+ ],
265
+ "scopes": ["schedules:write"],
266
+ "successStatus": 201,
267
+ "title": "Retry it safely",
268
+ "variables": ["GREATWAIT_ENDPOINTID", "GREATWAIT_IDEMPOTENCY_KEY"]
269
+ },
270
+ {
271
+ "capture": [],
272
+ "key": "read-schedule",
273
+ "method": "GET",
274
+ "observe": "The same schedule, with a strong ETag in the response. Send that value back in `If-Match` to make a later pause, replace or cancel conditional on nothing having changed in between.",
275
+ "operationId": "schedules.read",
276
+ "path": "/v1/schedules/{scheduleId}",
277
+ "purpose": "Reads the schedule back from the partition that owns it, which is also where the version you need for a conditional write comes from.",
278
+ "recovery": [
279
+ {
280
+ "nextMove": "A schedule in another organization, project or environment answers not_found rather than a refusal. Check that this credential belongs to the project that created it.",
281
+ "when": "not_found"
282
+ }
283
+ ],
284
+ "problems": [
285
+ "authentication_required",
286
+ "credential_expired",
287
+ "credential_revoked",
288
+ "invalid_request",
289
+ "not_found",
290
+ "rate_limited",
291
+ "scope_missing",
292
+ "service_unavailable"
293
+ ],
294
+ "scopes": ["schedules:read"],
295
+ "successStatus": 200,
296
+ "title": "Read the schedule back",
297
+ "variables": ["GREATWAIT_SCHEDULEID"]
298
+ },
299
+ {
300
+ "capture": [],
301
+ "key": "await-occurrence",
302
+ "method": "GET",
303
+ "observe": "The occurrence reaching `succeeded`. `terminal_failed` is also a settled answer, and the attempt in the next step says why.",
304
+ "operationId": "occurrences.read",
305
+ "path": "/v1/schedules/{scheduleId}/occurrences/{occurrenceId}",
306
+ "poll": {
307
+ "describe": "Poll until the occurrence reaches a terminal state, or until the deadline passes.",
308
+ "intervalSeconds": 5,
309
+ "timeoutSeconds": 180
310
+ },
311
+ "purpose": "Waits for the occurrence to settle. Delivery is at-least-once and a failing attempt is retried, so the state moves through `due` and `dispatching` before it settles.",
312
+ "recovery": [
313
+ {
314
+ "nextMove": "The occurrence never settled inside the deadline. It is not lost: read it again later, and read its attempts to see how far delivery got.",
315
+ "when": "not-settled"
316
+ }
317
+ ],
318
+ "problems": [
319
+ "authentication_required",
320
+ "credential_expired",
321
+ "credential_revoked",
322
+ "invalid_request",
323
+ "not_found",
324
+ "rate_limited",
325
+ "scope_missing",
326
+ "service_unavailable"
327
+ ],
328
+ "scopes": ["occurrences:read"],
329
+ "successStatus": 200,
330
+ "title": "Wait for the occurrence to settle",
331
+ "variables": ["GREATWAIT_SCHEDULEID", "GREATWAIT_OCCURRENCEID"]
332
+ },
333
+ {
334
+ "capture": [],
335
+ "key": "read-attempt",
336
+ "method": "GET",
337
+ "observe": "At least one attempt. `state: succeeded` with the status your receiver returned is first value: the callback was made, your receiver answered, and the outcome is recorded.",
338
+ "operationId": "attempts.list",
339
+ "path": "/v1/schedules/{scheduleId}/occurrences/{occurrenceId}/attempts",
340
+ "purpose": "Reads the immutable delivery history. This is the point the journey exists for — the customer-readable outcome of a real call to their own address.",
341
+ "recovery": [
342
+ {
343
+ "nextMove": "The attempt failed. Read `diagnostic` and `remediation`: they name the classified cause and the next action, and `failureSnippet` carries what your receiver said.",
344
+ "when": "attempt-failed"
345
+ },
346
+ {
347
+ "nextMove": "Nothing reached your receiver. Confirm the URL answers a POST from the public internet, and that it is not behind an allowlist Greatwait is not on.",
348
+ "when": "receiver-unreachable"
349
+ }
350
+ ],
351
+ "problems": [
352
+ "authentication_required",
353
+ "credential_expired",
354
+ "credential_revoked",
355
+ "invalid_request",
356
+ "not_found",
357
+ "rate_limited",
358
+ "scope_missing",
359
+ "service_unavailable"
360
+ ],
361
+ "scopes": ["occurrences:read"],
362
+ "successStatus": 200,
363
+ "title": "Read the delivery attempt",
364
+ "variables": ["GREATWAIT_SCHEDULEID", "GREATWAIT_OCCURRENCEID"]
365
+ },
366
+ {
367
+ "capture": [],
368
+ "key": "clean-up",
369
+ "method": "DELETE",
370
+ "observe": "The endpoint in status `disabled`. Nothing further is delivered to it, and it stays readable so the attempts above keep their context.",
371
+ "operationId": "endpoints.disable",
372
+ "path": "/v1/endpoints/{endpointId}",
373
+ "purpose": "Stops delivery to the destination you registered for this walkthrough. Disabling is terminal and deliberate: it leaves the history intact rather than deleting evidence of what happened.",
374
+ "recovery": [
375
+ {
376
+ "nextMove": "Already gone, or never in this project. Nothing to clean up.",
377
+ "when": "not_found"
378
+ }
379
+ ],
380
+ "problems": [
381
+ "authentication_required",
382
+ "credential_expired",
383
+ "credential_revoked",
384
+ "invalid_request",
385
+ "not_found",
386
+ "rate_limited",
387
+ "scope_missing",
388
+ "service_unavailable"
389
+ ],
390
+ "scopes": ["endpoints:write"],
391
+ "successStatus": 200,
392
+ "title": "Clean up",
393
+ "variables": ["GREATWAIT_ENDPOINTID"]
394
+ }
395
+ ],
396
+ "tools": [
397
+ {
398
+ "name": "curl",
399
+ "version": "8.3.0"
400
+ },
401
+ {
402
+ "name": "jq",
403
+ "version": "1.6"
404
+ }
405
+ ],
406
+ "variables": [
407
+ {
408
+ "detail": "The API origin for the environment you are working against, with no trailing slash.",
409
+ "name": "GREATWAIT_API_URL",
410
+ "placeholder": "https://api.greatwait.dev",
411
+ "secret": false,
412
+ "title": "API origin"
413
+ },
414
+ {
415
+ "detail": "The API credential secret, shown once when you created it. Export it in your shell; do not paste it into a command, a URL, or a file you commit.",
416
+ "name": "GREATWAIT_API_KEY",
417
+ "placeholder": "<the credential secret, shown once at creation>",
418
+ "secret": true,
419
+ "title": "API credential"
420
+ },
421
+ {
422
+ "detail": "Your own HTTPS receiver. Every callback in this journey is delivered here and nowhere else.",
423
+ "name": "GREATWAIT_RECEIVER_URL",
424
+ "placeholder": "https://receiver.example.com/greatwait",
425
+ "secret": false,
426
+ "title": "Receiver URL"
427
+ },
428
+ {
429
+ "detail": "A value you choose, at least 16 printable ASCII characters, that makes the create call safe to retry. Use a fresh one for each schedule you mean to create; these quickstarts generate one if you do not set it.",
430
+ "name": "GREATWAIT_IDEMPOTENCY_KEY",
431
+ "placeholder": "first-value-0000000000000000",
432
+ "secret": false,
433
+ "title": "Idempotency key"
434
+ }
435
+ ]
436
+ }