@sponson/adapters 0.0.0-stage → 0.5.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/LICENSE +202 -0
- package/README.md +4 -2
- package/dist/algolia.d.ts +6 -0
- package/dist/algolia.js +151 -0
- package/dist/algolia.js.map +1 -0
- package/dist/clerk.d.ts +8 -0
- package/dist/clerk.js +107 -0
- package/dist/clerk.js.map +1 -0
- package/dist/cloudflare.d.ts +25 -0
- package/dist/cloudflare.js +310 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/common.d.ts +73 -0
- package/dist/common.js +140 -0
- package/dist/common.js.map +1 -0
- package/dist/digest.d.ts +46 -0
- package/dist/digest.js +129 -0
- package/dist/digest.js.map +1 -0
- package/dist/digitalocean.d.ts +5 -0
- package/dist/digitalocean.js +243 -0
- package/dist/digitalocean.js.map +1 -0
- package/dist/http-adapter-action.d.ts +63 -0
- package/dist/http-adapter-action.js +369 -0
- package/dist/http-adapter-action.js.map +1 -0
- package/dist/http-adapter-auth.d.ts +88 -0
- package/dist/http-adapter-auth.js +437 -0
- package/dist/http-adapter-auth.js.map +1 -0
- package/dist/http-adapter-client.d.ts +51 -0
- package/dist/http-adapter-client.js +156 -0
- package/dist/http-adapter-client.js.map +1 -0
- package/dist/http-adapter-graphql.d.ts +39 -0
- package/dist/http-adapter-graphql.js +157 -0
- package/dist/http-adapter-graphql.js.map +1 -0
- package/dist/http-adapter-list.d.ts +33 -0
- package/dist/http-adapter-list.js +421 -0
- package/dist/http-adapter-list.js.map +1 -0
- package/dist/http-adapter-resource.d.ts +29 -0
- package/dist/http-adapter-resource.js +462 -0
- package/dist/http-adapter-resource.js.map +1 -0
- package/dist/http-adapter-spec.d.ts +216 -0
- package/dist/http-adapter-spec.js +660 -0
- package/dist/http-adapter-spec.js.map +1 -0
- package/dist/http-adapter.d.ts +16 -0
- package/dist/http-adapter.js +28 -0
- package/dist/http-adapter.js.map +1 -0
- package/dist/http.d.ts +179 -0
- package/dist/http.js +352 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/launchdarkly.d.ts +15 -0
- package/dist/launchdarkly.js +337 -0
- package/dist/launchdarkly.js.map +1 -0
- package/dist/manual.d.ts +13 -0
- package/dist/manual.js +201 -0
- package/dist/manual.js.map +1 -0
- package/dist/neon.d.ts +8 -0
- package/dist/neon.js +167 -0
- package/dist/neon.js.map +1 -0
- package/dist/netlify.d.ts +18 -0
- package/dist/netlify.js +436 -0
- package/dist/netlify.js.map +1 -0
- package/dist/planetscale.d.ts +10 -0
- package/dist/planetscale.js +311 -0
- package/dist/planetscale.js.map +1 -0
- package/dist/providers.d.ts +26 -0
- package/dist/providers.js +36 -0
- package/dist/providers.js.map +1 -0
- package/dist/recipes.d.ts +167 -0
- package/dist/recipes.js +246 -0
- package/dist/recipes.js.map +1 -0
- package/dist/secrets.d.ts +72 -0
- package/dist/secrets.js +476 -0
- package/dist/secrets.js.map +1 -0
- package/dist/sigv4.d.ts +56 -0
- package/dist/sigv4.js +118 -0
- package/dist/sigv4.js.map +1 -0
- package/dist/supabase.d.ts +9 -0
- package/dist/supabase.js +385 -0
- package/dist/supabase.js.map +1 -0
- package/dist/vercel.d.ts +8 -0
- package/dist/vercel.js +475 -0
- package/dist/vercel.js.map +1 -0
- package/dist/xata.d.ts +8 -0
- package/dist/xata.js +142 -0
- package/dist/xata.js.map +1 -0
- package/dist/xml.d.ts +25 -0
- package/dist/xml.js +211 -0
- package/dist/xml.js.map +1 -0
- package/package.json +58 -3
- package/recipes/amplify.yaml +147 -0
- package/recipes/auth0.yaml +178 -0
- package/recipes/azure_swa.yaml +116 -0
- package/recipes/cloud_run.yaml +97 -0
- package/recipes/cloudflare.yaml +108 -0
- package/recipes/cockroachdb.yaml +132 -0
- package/recipes/configcat.yaml +123 -0
- package/recipes/datadog.yaml +136 -0
- package/recipes/firebase.yaml +84 -0
- package/recipes/flagsmith.yaml +98 -0
- package/recipes/fly.yaml +97 -0
- package/recipes/fly_machines.yaml +67 -0
- package/recipes/gcs.yaml +102 -0
- package/recipes/github.yaml +123 -0
- package/recipes/growthbook.yaml +124 -0
- package/recipes/heroku.yaml +98 -0
- package/recipes/honeycomb.yaml +89 -0
- package/recipes/inngest.yaml +97 -0
- package/recipes/kinde.yaml +120 -0
- package/recipes/mongodb_atlas.yaml +119 -0
- package/recipes/okta.yaml +177 -0
- package/recipes/posthog.yaml +127 -0
- package/recipes/postmark.yaml +105 -0
- package/recipes/postmark_server.yaml +93 -0
- package/recipes/prisma.yaml +150 -0
- package/recipes/qstash.yaml +134 -0
- package/recipes/railway.yaml +130 -0
- package/recipes/render.yaml +103 -0
- package/recipes/resend.yaml +130 -0
- package/recipes/s3.yaml +108 -0
- package/recipes/sendgrid.yaml +165 -0
- package/recipes/sentry.yaml +158 -0
- package/recipes/split.yaml +121 -0
- package/recipes/statsig.yaml +124 -0
- package/recipes/stripe.yaml +310 -0
- package/recipes/stytch.yaml +113 -0
- package/recipes/svix.yaml +109 -0
- package/recipes/turso.yaml +98 -0
- package/recipes/unleash.yaml +149 -0
- package/recipes/upstash.yaml +130 -0
- package/recipes/vercel.yaml +116 -0
- package/recipes/workos.yaml +70 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Resend API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: resend
|
|
4
|
+
title: Resend
|
|
5
|
+
category: email
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Create API key
|
|
9
|
+
url: https://resend.com/docs/api-reference/api-keys/create-api-key
|
|
10
|
+
- title: List API keys
|
|
11
|
+
url: https://resend.com/docs/api-reference/api-keys/list-api-keys
|
|
12
|
+
- title: Delete API key
|
|
13
|
+
url: https://resend.com/docs/api-reference/api-keys/delete-api-key
|
|
14
|
+
- title: Create webhook
|
|
15
|
+
url: https://resend.com/docs/api-reference/webhooks/create-webhook
|
|
16
|
+
- title: Retrieve webhook
|
|
17
|
+
url: https://resend.com/docs/api-reference/webhooks/get-webhook
|
|
18
|
+
- title: List webhooks
|
|
19
|
+
url: https://resend.com/docs/api-reference/webhooks/list-webhooks
|
|
20
|
+
- title: Update webhook
|
|
21
|
+
url: https://resend.com/docs/api-reference/webhooks/update-webhook
|
|
22
|
+
- title: Delete webhook
|
|
23
|
+
url: https://resend.com/docs/api-reference/webhooks/delete-webhook
|
|
24
|
+
api:
|
|
25
|
+
base_url: https://api.resend.com
|
|
26
|
+
base_url_env: RESEND_API_URL
|
|
27
|
+
auth: { bearer_env: RESEND_API_KEY }
|
|
28
|
+
detect:
|
|
29
|
+
deps: [resend]
|
|
30
|
+
env: ["RESEND_*"]
|
|
31
|
+
starter:
|
|
32
|
+
- op: api_key
|
|
33
|
+
values: { name: "sponson-${ctx.env}-${ctx.scope}" }
|
|
34
|
+
assumptions:
|
|
35
|
+
- id: RS1
|
|
36
|
+
verified: true
|
|
37
|
+
text: "`POST /api-keys` creates an API key from `name` (at most 50 characters), `permission` (`full_access` or `sending_access`) and `domain_id` (with `sending_access` only), answering `{ id, token }`; requests carry `Authorization: Bearer <key>`."
|
|
38
|
+
source: https://resend.com/docs/api-reference/api-keys/create-api-key
|
|
39
|
+
- id: RS2
|
|
40
|
+
verified: true
|
|
41
|
+
text: "`GET /api-keys` answers `{ object: list, has_more, data: [{ id, name, created_at, last_used_at }] }`, every key when no `limit` is sent, and never the token: the token is shown only in the create answer, so it is a once-only output."
|
|
42
|
+
source: https://resend.com/docs/api-reference/api-keys/list-api-keys
|
|
43
|
+
- id: RS3
|
|
44
|
+
verified: true
|
|
45
|
+
text: "`DELETE /api-keys/{api_key_id}` removes a key; there is no endpoint to read or change one key, so its permission and domain are sent on create and never compared."
|
|
46
|
+
source: https://resend.com/docs/api-reference/api-keys/delete-api-key
|
|
47
|
+
- id: RS4
|
|
48
|
+
verified: true
|
|
49
|
+
text: "`POST /webhooks` creates a webhook from `endpoint` and `events` (both required), answering `{ object, id, signing_secret }`."
|
|
50
|
+
source: https://resend.com/docs/api-reference/webhooks/create-webhook
|
|
51
|
+
- id: RS5
|
|
52
|
+
verified: true
|
|
53
|
+
text: "`GET /webhooks/{webhook_id}` answers the webhook with `status` (`enabled`/`disabled`), `endpoint`, `events` and `signing_secret`: the secret stays readable, so it is an ordinary sensitive output."
|
|
54
|
+
source: https://resend.com/docs/api-reference/webhooks/get-webhook
|
|
55
|
+
- id: RS6
|
|
56
|
+
verified: true
|
|
57
|
+
text: "`GET /webhooks` answers `{ object: list, has_more, data: [{ id, created_at, status, endpoint, events }] }`, every webhook when no `limit` is sent."
|
|
58
|
+
source: https://resend.com/docs/api-reference/webhooks/list-webhooks
|
|
59
|
+
- id: RS7
|
|
60
|
+
verified: true
|
|
61
|
+
text: "`PATCH /webhooks/{webhook_id}` changes `endpoint`, `events` and `status`; `DELETE` on the same path removes the webhook."
|
|
62
|
+
source: https://resend.com/docs/api-reference/webhooks/update-webhook
|
|
63
|
+
- id: RS8
|
|
64
|
+
verified: false
|
|
65
|
+
text: "Key names and webhook endpoints are not unique in Resend: the recipe takes the name (keys) and the endpoint URL (webhooks) as the identity, and refuses (PARAM_INVALID) when two match, so give each environment its own name and URL."
|
|
66
|
+
- id: RS9
|
|
67
|
+
verified: false
|
|
68
|
+
text: "Creating a key or a webhook needs a `full_access` key; a deleted object answers 404."
|
|
69
|
+
ops:
|
|
70
|
+
api_key:
|
|
71
|
+
kind: resource
|
|
72
|
+
title: API key
|
|
73
|
+
summary: "A restricted API key per environment, such as `sponson-preview-pr-42` allowed only to send from one domain. Its token is a once-only output: pass it to the app's environment line in the same run (`{ from: <line>.token }`); later runs keep what that line holds, and `apply --recreate <line>` issues a new one. Only its existence is compared for drift: Resend shows no permission or domain for a key."
|
|
74
|
+
covers: [resend-key-webhook]
|
|
75
|
+
params:
|
|
76
|
+
name:
|
|
77
|
+
type: string
|
|
78
|
+
required: true
|
|
79
|
+
pattern: "^.{1,50}$"
|
|
80
|
+
description: The key's name, unique among the account's keys (RS8); its identity.
|
|
81
|
+
example: "sponson-${ctx.env}-${ctx.scope}"
|
|
82
|
+
permission:
|
|
83
|
+
type: string
|
|
84
|
+
default: sending_access
|
|
85
|
+
enum: [full_access, sending_access]
|
|
86
|
+
description: What the key may do.
|
|
87
|
+
domain_id:
|
|
88
|
+
type: string
|
|
89
|
+
description: With `sending_access`, the only domain the key may send from.
|
|
90
|
+
http:
|
|
91
|
+
find:
|
|
92
|
+
path: /api-keys
|
|
93
|
+
list_path: /data
|
|
94
|
+
match: { name: { param: name } }
|
|
95
|
+
create:
|
|
96
|
+
path: /api-keys
|
|
97
|
+
body: { permission: { param: permission }, domain_id: { param: domain_id } }
|
|
98
|
+
delete: { path: "/api-keys/{id}" }
|
|
99
|
+
outputs:
|
|
100
|
+
token: { path: /token, sensitive: true, once: true }
|
|
101
|
+
webhook:
|
|
102
|
+
kind: resource
|
|
103
|
+
title: Webhook
|
|
104
|
+
summary: "A webhook delivering an environment's email events to its URL, such as the preview's `/api/resend` handler. Located by its endpoint URL; a console edit of its events is drift (its enabled/disabled status is left to the console: the create request takes none). Its signing secret is a sensitive output, readable on every run."
|
|
105
|
+
covers: [resend-key-webhook]
|
|
106
|
+
params:
|
|
107
|
+
endpoint:
|
|
108
|
+
type: string
|
|
109
|
+
required: true
|
|
110
|
+
pattern: "^https://\\S+$"
|
|
111
|
+
description: The URL events are delivered to; its identity (RS8).
|
|
112
|
+
example: "https://${ctx.scope}.preview.example.com/api/resend"
|
|
113
|
+
events:
|
|
114
|
+
type: list
|
|
115
|
+
required: true
|
|
116
|
+
description: The event types to deliver, such as `email.delivered` and `email.bounced`.
|
|
117
|
+
example: [email.delivered, email.bounced]
|
|
118
|
+
http:
|
|
119
|
+
find:
|
|
120
|
+
path: /webhooks
|
|
121
|
+
list_path: /data
|
|
122
|
+
match: { endpoint: { param: endpoint } }
|
|
123
|
+
read: { path: "/webhooks/{id}" }
|
|
124
|
+
create: { path: /webhooks }
|
|
125
|
+
update: { method: PATCH, path: "/webhooks/{id}" }
|
|
126
|
+
delete: { path: "/webhooks/{id}" }
|
|
127
|
+
fields:
|
|
128
|
+
events: { param: events }
|
|
129
|
+
outputs:
|
|
130
|
+
signing_secret: { path: /signing_secret, sensitive: true }
|
package/recipes/s3.yaml
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# S3 API recipes (Amazon S3, and Cloudflare R2 through its S3-compatible endpoint): XML documents, every request
|
|
3
|
+
# signed with AWS Signature Version 4. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
4
|
+
provider: s3
|
|
5
|
+
title: Amazon S3 / Cloudflare R2 (S3 API)
|
|
6
|
+
category: cors
|
|
7
|
+
verified_on: "2026-10-11"
|
|
8
|
+
docs:
|
|
9
|
+
- title: PutBucketCors
|
|
10
|
+
url: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html
|
|
11
|
+
- title: GetBucketCors
|
|
12
|
+
url: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketCors.html
|
|
13
|
+
- title: DeleteBucketCors
|
|
14
|
+
url: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketCors.html
|
|
15
|
+
- title: R2 S3 API compatibility
|
|
16
|
+
url: https://developers.cloudflare.com/r2/api/s3/api/
|
|
17
|
+
base_url_example: https://assets.s3.us-east-1.amazonaws.com
|
|
18
|
+
api:
|
|
19
|
+
base_url_env: S3_API_URL
|
|
20
|
+
encoding: xml
|
|
21
|
+
auth:
|
|
22
|
+
aws_sigv4: { region: us-east-1, service: s3, access_key_id_env: AWS_ACCESS_KEY_ID, secret_access_key_env: AWS_SECRET_ACCESS_KEY }
|
|
23
|
+
detect:
|
|
24
|
+
deps: ["@aws-sdk/client-s3"]
|
|
25
|
+
starter:
|
|
26
|
+
- op: bucket_cors
|
|
27
|
+
preview_url: origin
|
|
28
|
+
values: { rule_id: "sponson-${ctx.scope}" }
|
|
29
|
+
where:
|
|
30
|
+
base_url: "the bucket's endpoint: `https://<bucket>.s3.<region>.amazonaws.com`, or R2's `https://<account id>.r2.cloudflarestorage.com/<bucket>`"
|
|
31
|
+
assumptions:
|
|
32
|
+
- id: SS1
|
|
33
|
+
verified: true
|
|
34
|
+
text: "`PUT /?cors` on the bucket's endpoint replaces its whole CORS configuration with a `CORSConfiguration` document of up to 100 `CORSRule`s (each `ID`, `AllowedOrigin`s, `AllowedMethod`s, `AllowedHeader`s, `ExposeHeader`s, `MaxAgeSeconds`) and requires `Content-MD5`, which the SigV4 signer adds for `s3`."
|
|
35
|
+
source: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html
|
|
36
|
+
- id: SS2
|
|
37
|
+
verified: true
|
|
38
|
+
text: "`GET /?cors` answers the configuration as XML."
|
|
39
|
+
source: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketCors.html
|
|
40
|
+
- id: SS3
|
|
41
|
+
verified: true
|
|
42
|
+
text: "`DELETE /?cors` removes the configuration (the way to leave a bucket with no rule)."
|
|
43
|
+
source: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketCors.html
|
|
44
|
+
- id: SS4
|
|
45
|
+
verified: true
|
|
46
|
+
text: "R2 implements PutBucketCors, GetBucketCors and DeleteBucketCors at `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`; its SigV4 region is `auto`, and `us-east-1` is accepted as an alias, so the recipe's region works for R2 unchanged."
|
|
47
|
+
source: https://developers.cloudflare.com/r2/api/s3/api/
|
|
48
|
+
- id: SS5
|
|
49
|
+
verified: false
|
|
50
|
+
text: "A bucket without a CORS configuration answers 404 `NoSuchCORSConfiguration` (read as an empty list, `parent.if_missing: empty`), and an empty configuration is refused as `MalformedXML` (so the last rule is removed with DELETE, `parent.when_empty: delete`)."
|
|
51
|
+
- id: SS6
|
|
52
|
+
verified: false
|
|
53
|
+
text: "R2 accepts path-style requests (`https://<ACCOUNT_ID>.r2.cloudflarestorage.com/<bucket>/?cors`), so its base URL names the bucket in the path."
|
|
54
|
+
- id: SS7
|
|
55
|
+
verified: false
|
|
56
|
+
text: "S3 answers a rule's elements as they were written; a rule's `ID` identifies it among the bucket's rules (IDs are not required to be unique by S3, so other writers must not reuse the recipe's)."
|
|
57
|
+
ops:
|
|
58
|
+
bucket_cors:
|
|
59
|
+
kind: list_item
|
|
60
|
+
title: CORS rule of a bucket
|
|
61
|
+
summary: "A CORS rule of an S3 or R2 bucket allowing the preview's origin, identified by its `ID` (such as `sponson-pr-42`); every other rule is left as it is. The base URL names the bucket: `https://<bucket>.s3.<region>.amazonaws.com` (set `auth.aws_sigv4.region` to the bucket's region), or `https://<account>.r2.cloudflarestorage.com/<bucket>` for R2. A console edit of the rule is drift; destroy removes only this rule (the whole configuration when it was the last one)."
|
|
62
|
+
covers: [s3-r2-cors]
|
|
63
|
+
params:
|
|
64
|
+
rule_id:
|
|
65
|
+
type: string
|
|
66
|
+
required: true
|
|
67
|
+
pattern: "^.{1,255}$"
|
|
68
|
+
description: The rule's `ID`, at most 255 characters; its identity (SS7).
|
|
69
|
+
example: "sponson-${ctx.scope}"
|
|
70
|
+
origin:
|
|
71
|
+
type: string
|
|
72
|
+
required: true
|
|
73
|
+
pattern: "^(https?://\\S+|\\*)$"
|
|
74
|
+
description: The origin allowed (the preview's URL, without a path).
|
|
75
|
+
example: "https://${ctx.scope}.preview.example.app"
|
|
76
|
+
methods:
|
|
77
|
+
type: list
|
|
78
|
+
default: [GET]
|
|
79
|
+
description: "The methods allowed: `GET`, `PUT`, `POST`, `DELETE`, `HEAD`."
|
|
80
|
+
allowed_headers:
|
|
81
|
+
type: list
|
|
82
|
+
description: "Request headers a preflight may ask for (`*` for any); absent: none."
|
|
83
|
+
expose_headers:
|
|
84
|
+
type: list
|
|
85
|
+
description: Response headers the browser may read; absent, none.
|
|
86
|
+
max_age_seconds:
|
|
87
|
+
type: string
|
|
88
|
+
default: "3000"
|
|
89
|
+
pattern: "^[0-9]+$"
|
|
90
|
+
description: How long a preflight answer may be cached, in seconds (a string, as XML carries it).
|
|
91
|
+
http:
|
|
92
|
+
parent: { path: "/?cors", method: PUT, if_missing: empty, when_empty: delete }
|
|
93
|
+
list_path: /CORSConfiguration/CORSRule
|
|
94
|
+
key_field: ID
|
|
95
|
+
item:
|
|
96
|
+
AllowedHeader: { param: allowed_headers }
|
|
97
|
+
AllowedMethod: { param: methods }
|
|
98
|
+
AllowedOrigin: { param: origin }
|
|
99
|
+
ExposeHeader: { param: expose_headers }
|
|
100
|
+
ID: { param: rule_id }
|
|
101
|
+
MaxAgeSeconds: { param: max_age_seconds }
|
|
102
|
+
sim:
|
|
103
|
+
provider: aws
|
|
104
|
+
base_path: /aws/s3/assets
|
|
105
|
+
seed: { buckets: { assets: { cors: null } } }
|
|
106
|
+
present: /buckets/assets/cors/0
|
|
107
|
+
drift:
|
|
108
|
+
missing: { s3.assets.cors: "remove:sponson-pr-42" }
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Twilio SendGrid v3 API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: sendgrid
|
|
4
|
+
title: SendGrid
|
|
5
|
+
category: email
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Create an Event Webhook
|
|
9
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/create-an-event-webhook
|
|
10
|
+
- title: Get all Event Webhooks
|
|
11
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/get-all-event-webhooks
|
|
12
|
+
- title: Get an Event Webhook
|
|
13
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/get-an-event-webhook
|
|
14
|
+
- title: Update an Event Webhook
|
|
15
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/update-an-event-webhook
|
|
16
|
+
- title: Delete an Event Webhook
|
|
17
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/delete-an-event-webhook
|
|
18
|
+
- title: Create a parse setting
|
|
19
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/settings-inbound-parse/create-a-parse-setting
|
|
20
|
+
- title: Retrieve a specific parse setting
|
|
21
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/settings-inbound-parse/retrieve-a-specific-parse-setting
|
|
22
|
+
- title: Update a parse setting
|
|
23
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/settings-inbound-parse/update-a-parse-setting
|
|
24
|
+
- title: Delete a parse setting
|
|
25
|
+
url: https://www.twilio.com/docs/sendgrid/api-reference/settings-inbound-parse/delete-a-parse-setting
|
|
26
|
+
api:
|
|
27
|
+
base_url: https://api.sendgrid.com
|
|
28
|
+
base_url_env: SENDGRID_API_URL
|
|
29
|
+
auth: { bearer_env: SENDGRID_API_KEY }
|
|
30
|
+
detect:
|
|
31
|
+
deps: ["@sendgrid/"]
|
|
32
|
+
env: ["SENDGRID_*"]
|
|
33
|
+
starter:
|
|
34
|
+
- op: event_webhook
|
|
35
|
+
where:
|
|
36
|
+
url: "the preview's event handler: its URL plus the handler's path (a `{ from }` reference cannot carry a path)"
|
|
37
|
+
assumptions:
|
|
38
|
+
- id: SG1
|
|
39
|
+
verified: true
|
|
40
|
+
text: "`POST /v3/user/webhooks/event/settings` creates an Event Webhook from `url` (required), `enabled`, one boolean per event type (`processed`, `delivered`, `dropped`, `deferred`, `bounce`, `open`, `click`, `spam_report`, `unsubscribe`, `group_unsubscribe`, `group_resubscribe`) and `friendly_name`, answering 201 with the webhook and its string `id`; requests carry the API key as `Authorization: Bearer`. EU regional subusers use `https://api.eu.sendgrid.com`."
|
|
41
|
+
source: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/create-an-event-webhook
|
|
42
|
+
- id: SG2
|
|
43
|
+
verified: true
|
|
44
|
+
text: "Each URL can be used by only one Event Webhook (a second create answers 400 naming the existing id), so the URL identifies the webhook; the number of webhooks is limited by the plan (400 beyond it)."
|
|
45
|
+
source: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/create-an-event-webhook
|
|
46
|
+
- id: SG3
|
|
47
|
+
verified: true
|
|
48
|
+
text: "`GET /v3/user/webhooks/event/settings/all` answers `{ max_allowed, webhooks: [...] }` with every webhook's settings and `id`."
|
|
49
|
+
source: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/get-all-event-webhooks
|
|
50
|
+
- id: SG4
|
|
51
|
+
verified: true
|
|
52
|
+
text: "`PATCH /v3/user/webhooks/event/settings/{id}` requires `url` and updates the fields sent; `DELETE` on the same path answers 204, and 404 for an unknown id. Without an id these paths act on the oldest webhook, which the recipe never does (its paths always carry the id)."
|
|
53
|
+
source: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/update-an-event-webhook
|
|
54
|
+
- id: SG5
|
|
55
|
+
verified: true
|
|
56
|
+
text: "Signature verification and its public key are set through a separate endpoint and are not part of the webhook's create or update; this recipe does not manage them."
|
|
57
|
+
source: https://www.twilio.com/docs/sendgrid/api-reference/webhooks/create-an-event-webhook
|
|
58
|
+
- id: SG6
|
|
59
|
+
verified: true
|
|
60
|
+
text: "`POST /v3/user/webhooks/parse/settings` creates an Inbound Parse setting from `url`, `hostname`, `spam_check` and `send_raw`, answering 201 with those four fields bare; `GET`, `PATCH` and `DELETE` (204) `/v3/user/webhooks/parse/settings/{hostname}` read, update and remove it. The hostname must be on a domain authenticated in SendGrid, with an MX record pointing at SendGrid."
|
|
61
|
+
source: https://www.twilio.com/docs/sendgrid/api-reference/settings-inbound-parse/create-a-parse-setting
|
|
62
|
+
- id: SG7
|
|
63
|
+
verified: false
|
|
64
|
+
text: "A PATCH that leaves out an event flag keeps its current value (the documentation's examples send only `url`); the recipe sends every flag it compares anyway."
|
|
65
|
+
- id: SG8
|
|
66
|
+
verified: false
|
|
67
|
+
text: "A parse setting for a hostname that exists already is refused with an error status (not documented which); the next run then finds it by its hostname."
|
|
68
|
+
ops:
|
|
69
|
+
event_webhook:
|
|
70
|
+
kind: resource
|
|
71
|
+
title: Event Webhook
|
|
72
|
+
summary: An Event Webhook delivering an environment's email events to its URL, such as the preview's `/api/sendgrid/events` handler. Located by its URL (unique in SendGrid); a console edit of its enabled flag, an event flag or its friendly name is drift.
|
|
73
|
+
covers: [sendgrid-webhook]
|
|
74
|
+
params:
|
|
75
|
+
url:
|
|
76
|
+
type: string
|
|
77
|
+
required: true
|
|
78
|
+
pattern: "^https?://\\S+$"
|
|
79
|
+
description: The URL events are posted to; its identity (SG2).
|
|
80
|
+
example: "https://${ctx.scope}.preview.example.com/api/sendgrid/events"
|
|
81
|
+
enabled:
|
|
82
|
+
type: boolean
|
|
83
|
+
default: true
|
|
84
|
+
description: Whether events are posted.
|
|
85
|
+
friendly_name:
|
|
86
|
+
type: string
|
|
87
|
+
description: A label for the webhook (not unique).
|
|
88
|
+
example: "sponson ${ctx.env} ${ctx.scope}"
|
|
89
|
+
processed: { type: boolean, default: false, description: Post `processed` events. }
|
|
90
|
+
delivered: { type: boolean, default: true, description: Post `delivered` events. }
|
|
91
|
+
dropped: { type: boolean, default: true, description: Post `dropped` events. }
|
|
92
|
+
deferred: { type: boolean, default: false, description: Post `deferred` events. }
|
|
93
|
+
bounce: { type: boolean, default: true, description: Post `bounce` events. }
|
|
94
|
+
open: { type: boolean, default: false, description: Post `open` events. }
|
|
95
|
+
click: { type: boolean, default: false, description: Post `click` events. }
|
|
96
|
+
spam_report: { type: boolean, default: true, description: Post `spam_report` events. }
|
|
97
|
+
unsubscribe: { type: boolean, default: false, description: Post `unsubscribe` events. }
|
|
98
|
+
group_unsubscribe: { type: boolean, default: false, description: Post `group_unsubscribe` events. }
|
|
99
|
+
group_resubscribe: { type: boolean, default: false, description: Post `group_resubscribe` events. }
|
|
100
|
+
http:
|
|
101
|
+
find:
|
|
102
|
+
path: /v3/user/webhooks/event/settings/all
|
|
103
|
+
list_path: /webhooks
|
|
104
|
+
match: { url: { param: url } }
|
|
105
|
+
create: { path: /v3/user/webhooks/event/settings }
|
|
106
|
+
update:
|
|
107
|
+
method: PATCH
|
|
108
|
+
path: "/v3/user/webhooks/event/settings/{id}"
|
|
109
|
+
body: { url: { param: url } }
|
|
110
|
+
delete: { path: "/v3/user/webhooks/event/settings/{id}" }
|
|
111
|
+
fields:
|
|
112
|
+
enabled: { param: enabled }
|
|
113
|
+
friendly_name: { param: friendly_name }
|
|
114
|
+
processed: { param: processed }
|
|
115
|
+
delivered: { param: delivered }
|
|
116
|
+
dropped: { param: dropped }
|
|
117
|
+
deferred: { param: deferred }
|
|
118
|
+
bounce: { param: bounce }
|
|
119
|
+
open: { param: open }
|
|
120
|
+
click: { param: click }
|
|
121
|
+
spam_report: { param: spam_report }
|
|
122
|
+
unsubscribe: { param: unsubscribe }
|
|
123
|
+
group_unsubscribe: { param: group_unsubscribe }
|
|
124
|
+
group_resubscribe: { param: group_resubscribe }
|
|
125
|
+
parse_setting:
|
|
126
|
+
kind: resource
|
|
127
|
+
title: Inbound Parse setting
|
|
128
|
+
summary: An Inbound Parse host per environment, such as `pr-42.parse.example.com`, posting the mail it receives to the environment's URL. Named by its hostname; a console edit of its URL, spam check or raw flag is drift. The hostname's domain must be authenticated in SendGrid and its MX record point at SendGrid (a wildcard record serves every environment).
|
|
129
|
+
covers: [sendgrid-webhook]
|
|
130
|
+
params:
|
|
131
|
+
hostname:
|
|
132
|
+
type: string
|
|
133
|
+
required: true
|
|
134
|
+
pattern: "^[a-z0-9.-]+$"
|
|
135
|
+
description: The host mail is received for, lower-case; its identity.
|
|
136
|
+
example: "${ctx.scope}.parse.example.com"
|
|
137
|
+
url:
|
|
138
|
+
type: string
|
|
139
|
+
required: true
|
|
140
|
+
pattern: "^https?://\\S+$"
|
|
141
|
+
description: The URL parsed mail is posted to.
|
|
142
|
+
example: "https://${ctx.scope}.preview.example.com/api/sendgrid/inbound"
|
|
143
|
+
spam_check:
|
|
144
|
+
type: boolean
|
|
145
|
+
default: false
|
|
146
|
+
description: Check mail for spam before posting it.
|
|
147
|
+
send_raw:
|
|
148
|
+
type: boolean
|
|
149
|
+
default: false
|
|
150
|
+
description: Post the original MIME message.
|
|
151
|
+
http:
|
|
152
|
+
read: { path: "/v3/user/webhooks/parse/settings/{hostname}" }
|
|
153
|
+
create:
|
|
154
|
+
path: /v3/user/webhooks/parse/settings
|
|
155
|
+
body: { hostname: { param: hostname } }
|
|
156
|
+
update: { method: PATCH }
|
|
157
|
+
id_path: /hostname
|
|
158
|
+
fields:
|
|
159
|
+
url: { param: url }
|
|
160
|
+
spam_check: { param: spam_check }
|
|
161
|
+
send_raw: { param: send_raw }
|
|
162
|
+
sim:
|
|
163
|
+
id_from: hostname
|
|
164
|
+
live:
|
|
165
|
+
params: { hostname: SPONSON_LIVE_SENDGRID_PARSE_HOSTNAME }
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Sentry Web API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: sentry
|
|
4
|
+
title: Sentry
|
|
5
|
+
category: observability
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Create a New Release for an Organization
|
|
9
|
+
url: https://docs.sentry.io/api/releases/create-a-new-release-for-an-organization/
|
|
10
|
+
- title: Retrieve an Organization's Release
|
|
11
|
+
url: https://docs.sentry.io/api/releases/retrieve-an-organizations-release/
|
|
12
|
+
- title: Update an Organization's Release
|
|
13
|
+
url: https://docs.sentry.io/api/releases/update-an-organizations-release/
|
|
14
|
+
- title: Delete an Organization's Release
|
|
15
|
+
url: https://docs.sentry.io/api/releases/delete-an-organizations-release/
|
|
16
|
+
- title: Create a Deploy
|
|
17
|
+
url: https://docs.sentry.io/api/releases/create-a-deploy/
|
|
18
|
+
- title: List a Release's Deploys
|
|
19
|
+
url: https://docs.sentry.io/api/releases/list-a-releases-deploys/
|
|
20
|
+
- title: Release Management (sentry-cli)
|
|
21
|
+
url: https://docs.sentry.io/cli/releases/
|
|
22
|
+
api:
|
|
23
|
+
base_url: https://sentry.io/api/0
|
|
24
|
+
base_url_env: SENTRY_API_URL
|
|
25
|
+
auth: { bearer_env: SENTRY_AUTH_TOKEN }
|
|
26
|
+
detect:
|
|
27
|
+
deps: ["@sentry/"]
|
|
28
|
+
env: ["SENTRY_*"]
|
|
29
|
+
files: [sentry.client.config.ts, sentry.client.config.js, sentry.server.config.ts, sentry.server.config.js, sentry.properties, .sentryclirc]
|
|
30
|
+
starter:
|
|
31
|
+
- op: release
|
|
32
|
+
values: { version: "app@${ctx.git.sha}" }
|
|
33
|
+
where:
|
|
34
|
+
organization: "Sentry → Settings → Organization Settings → Organization Slug"
|
|
35
|
+
project: "Sentry → Settings → Projects: the project's slug"
|
|
36
|
+
assumptions:
|
|
37
|
+
- id: SE1
|
|
38
|
+
verified: true
|
|
39
|
+
text: "`POST /api/0/organizations/{organization_id_or_slug}/releases/` creates a release from `version` and `projects` (both required), `ref`, `url`, `dateReleased` and commit data, with a bearer token holding `project:releases`, `project:write`, `project:admin` or `org:ci`; it answers 201 (or 208)."
|
|
40
|
+
source: https://docs.sentry.io/api/releases/create-a-new-release-for-an-organization/
|
|
41
|
+
- id: SE2
|
|
42
|
+
verified: true
|
|
43
|
+
text: "A version is one release across the organization's projects, and `GET /api/0/organizations/{org}/releases/{version}/` answers it (404 when there is none), so the version names the release."
|
|
44
|
+
source: https://docs.sentry.io/api/releases/retrieve-an-organizations-release/
|
|
45
|
+
- id: SE3
|
|
46
|
+
verified: true
|
|
47
|
+
text: "`PUT /api/0/organizations/{org}/releases/{version}/` updates `ref`, `url`, `dateReleased` and commit data (the documentation says an omitted `dateReleased` is the current time), and answers the release."
|
|
48
|
+
source: https://docs.sentry.io/api/releases/update-an-organizations-release/
|
|
49
|
+
- id: SE4
|
|
50
|
+
verified: true
|
|
51
|
+
text: "`DELETE /api/0/organizations/{org}/releases/{version}/` permanently removes a release and its files (`project:releases` or `project:admin`). The recipe keeps releases on destroy: one version is shared by every environment it is deployed to."
|
|
52
|
+
source: https://docs.sentry.io/api/releases/delete-an-organizations-release/
|
|
53
|
+
- id: SE5
|
|
54
|
+
verified: true
|
|
55
|
+
text: "`POST /api/0/organizations/{org}/releases/{version}/deploys/` records a deploy of the release from `environment` (required), `name`, `url`, `dateStarted`, `dateFinished` (default now) and `projects` (default: all of the release's)."
|
|
56
|
+
source: https://docs.sentry.io/api/releases/create-a-deploy/
|
|
57
|
+
- id: SE6
|
|
58
|
+
verified: true
|
|
59
|
+
text: "`GET /api/0/organizations/{org}/releases/{version}/deploys/` lists the release's deploys; deploys cannot be deleted, so the deploy op never deletes (`destroy: never`)."
|
|
60
|
+
source: https://docs.sentry.io/cli/releases/
|
|
61
|
+
- id: SE7
|
|
62
|
+
verified: true
|
|
63
|
+
text: "The release's `dateReleased` defaults to the current time on create, so a release this recipe creates is finalized at once."
|
|
64
|
+
source: https://docs.sentry.io/api/releases/create-a-new-release-for-an-organization/
|
|
65
|
+
- id: SE8
|
|
66
|
+
verified: false
|
|
67
|
+
text: "A create for a version that exists answers 208 with the existing release (not an error), so a release another tool made (sentry-cli in the build) is taken over without a second write; the recipe keeps it on destroy either way."
|
|
68
|
+
- id: SE9
|
|
69
|
+
verified: false
|
|
70
|
+
text: "The deploy list answers a bare array of `{ id, environment, name, url, dateStarted, dateFinished }` with string ids, all of a release's deploys on the first page; `environment` and `name` together identify the deploy this recipe recorded."
|
|
71
|
+
- id: SE10
|
|
72
|
+
verified: false
|
|
73
|
+
text: "Release `url` is answered as sent (null when unset); organizations hosted in another region (`de.sentry.io`) or self-hosted Sentry set `base_url` in the provider block."
|
|
74
|
+
ops:
|
|
75
|
+
release:
|
|
76
|
+
kind: resource
|
|
77
|
+
title: Release
|
|
78
|
+
summary: "A release for the commit, such as `app@${ctx.git.sha}`, in the given projects, finalized when created (SE7). Named by its version; a console edit of its URL is drift. Kept on destroy (shared history: preview and production deploy the same version); `destroy: delete` on the line removes it."
|
|
79
|
+
covers: [sentry-release]
|
|
80
|
+
destroy: keep
|
|
81
|
+
params:
|
|
82
|
+
organization:
|
|
83
|
+
type: string
|
|
84
|
+
required: true
|
|
85
|
+
description: The organization's slug or id.
|
|
86
|
+
example: acme
|
|
87
|
+
version:
|
|
88
|
+
type: string
|
|
89
|
+
required: true
|
|
90
|
+
pattern: "^[^/\\s]+$"
|
|
91
|
+
description: The release's version (no slashes or whitespace), such as `app@<sha>`.
|
|
92
|
+
example: "app@${ctx.git.sha}"
|
|
93
|
+
project:
|
|
94
|
+
type: string
|
|
95
|
+
required: true
|
|
96
|
+
description: The slug of the project the release belongs to (a release of several projects is a hand-written `http` line).
|
|
97
|
+
example: web
|
|
98
|
+
url:
|
|
99
|
+
type: string
|
|
100
|
+
description: A link for the release (its commit or build).
|
|
101
|
+
example: "https://github.com/acme/app/commit/${ctx.git.sha}"
|
|
102
|
+
ref:
|
|
103
|
+
type: string
|
|
104
|
+
description: A commit reference, sent on create.
|
|
105
|
+
http:
|
|
106
|
+
read: { path: "/organizations/{organization}/releases/{version}/" }
|
|
107
|
+
create:
|
|
108
|
+
path: "/organizations/{organization}/releases/"
|
|
109
|
+
body: { version: { param: version }, projects: [{ param: project }], ref: { param: ref } }
|
|
110
|
+
update: { method: PUT }
|
|
111
|
+
id_path: /version
|
|
112
|
+
fields:
|
|
113
|
+
url: { param: url }
|
|
114
|
+
sim:
|
|
115
|
+
id_from: version
|
|
116
|
+
live:
|
|
117
|
+
params: { organization: SPONSON_LIVE_SENTRY_ORG, project: SPONSON_LIVE_SENTRY_PROJECT }
|
|
118
|
+
deploy:
|
|
119
|
+
kind: resource
|
|
120
|
+
title: Deploy of a release to an environment
|
|
121
|
+
summary: "The record that a release was deployed to an environment (`preview`, named for the scope), which Sentry shows on the release and uses for deploy notifications. Located by environment and name among the release's deploys. Sentry has no way to change or delete a deploy, so nothing is compared for drift and destroy leaves it (`destroy: never`)."
|
|
122
|
+
covers: [sentry-release]
|
|
123
|
+
destroy: never
|
|
124
|
+
params:
|
|
125
|
+
organization:
|
|
126
|
+
type: string
|
|
127
|
+
required: true
|
|
128
|
+
description: The organization's slug or id.
|
|
129
|
+
example: acme
|
|
130
|
+
version:
|
|
131
|
+
type: string
|
|
132
|
+
required: true
|
|
133
|
+
pattern: "^[^/\\s]+$"
|
|
134
|
+
description: "The deployed release's version; the release must exist (`{ from: <release line>.id }` orders the lines)."
|
|
135
|
+
example: "app@${ctx.git.sha}"
|
|
136
|
+
environment:
|
|
137
|
+
type: string
|
|
138
|
+
required: true
|
|
139
|
+
description: The environment deployed to.
|
|
140
|
+
example: "${ctx.env}"
|
|
141
|
+
name:
|
|
142
|
+
type: string
|
|
143
|
+
required: true
|
|
144
|
+
description: The deploy's name, which with the environment identifies it among the release's deploys.
|
|
145
|
+
example: "sponson-${ctx.scope}"
|
|
146
|
+
url:
|
|
147
|
+
type: string
|
|
148
|
+
description: A link to the deployment (the preview URL), sent on create.
|
|
149
|
+
http:
|
|
150
|
+
find:
|
|
151
|
+
path: "/organizations/{organization}/releases/{version}/deploys/"
|
|
152
|
+
match: { environment: { param: environment }, name: { param: name } }
|
|
153
|
+
create:
|
|
154
|
+
path: "/organizations/{organization}/releases/{version}/deploys/"
|
|
155
|
+
body: { url: { param: url } }
|
|
156
|
+
delete: { path: "/organizations/{organization}/releases/{version}/deploys/{id}/" }
|
|
157
|
+
live:
|
|
158
|
+
params: { organization: SPONSON_LIVE_SENTRY_ORG, version: SPONSON_LIVE_SENTRY_VERSION }
|