@clawpify/skills 1.0.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.
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/clawpify/SKILL.md +134 -0
- package/clawpify/references/blogs.md +385 -0
- package/clawpify/references/bulk-operations.md +386 -0
- package/clawpify/references/collections.md +71 -0
- package/clawpify/references/customers.md +141 -0
- package/clawpify/references/discounts.md +431 -0
- package/clawpify/references/draft-orders.md +495 -0
- package/clawpify/references/files.md +355 -0
- package/clawpify/references/fulfillments.md +437 -0
- package/clawpify/references/gift-cards.md +453 -0
- package/clawpify/references/inventory.md +107 -0
- package/clawpify/references/locations.md +349 -0
- package/clawpify/references/marketing.md +352 -0
- package/clawpify/references/markets.md +346 -0
- package/clawpify/references/menus.md +313 -0
- package/clawpify/references/metafields.md +461 -0
- package/clawpify/references/orders.md +164 -0
- package/clawpify/references/pages.md +308 -0
- package/clawpify/references/products.md +277 -0
- package/clawpify/references/refunds.md +401 -0
- package/clawpify/references/segments.md +319 -0
- package/clawpify/references/shipping.md +406 -0
- package/clawpify/references/shop.md +307 -0
- package/clawpify/references/subscriptions.md +429 -0
- package/clawpify/references/translations.md +270 -0
- package/clawpify/references/webhooks.md +400 -0
- package/dist/agent.d.ts +18 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +100 -0
- package/dist/auth.d.ts +34 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +58 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +236 -0
- package/dist/shopify.d.ts +29 -0
- package/dist/shopify.d.ts.map +1 -0
- package/dist/shopify.js +41 -0
- package/dist/skills.d.ts +8 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +36 -0
- package/package.json +100 -0
- package/src/agent.ts +133 -0
- package/src/auth.ts +109 -0
- package/src/index.ts +55 -0
- package/src/mcp-server.ts +190 -0
- package/src/shopify.ts +63 -0
- package/src/skills.ts +42 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# Shopify Subscriptions
|
|
2
|
+
|
|
3
|
+
Manage subscription contracts and billing via the GraphQL Admin API.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Subscriptions enable recurring orders for products. Subscription contracts define the billing schedule, products, and delivery details.
|
|
8
|
+
|
|
9
|
+
## List Subscription Contracts
|
|
10
|
+
|
|
11
|
+
```graphql
|
|
12
|
+
query ListSubscriptionContracts($first: Int!, $query: String) {
|
|
13
|
+
subscriptionContracts(first: $first, query: $query, sortKey: CREATED_AT, reverse: true) {
|
|
14
|
+
nodes {
|
|
15
|
+
id
|
|
16
|
+
status
|
|
17
|
+
createdAt
|
|
18
|
+
nextBillingDate
|
|
19
|
+
customer {
|
|
20
|
+
displayName
|
|
21
|
+
defaultEmailAddress {
|
|
22
|
+
emailAddress
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
deliveryPolicy {
|
|
26
|
+
interval
|
|
27
|
+
intervalCount
|
|
28
|
+
}
|
|
29
|
+
billingPolicy {
|
|
30
|
+
interval
|
|
31
|
+
intervalCount
|
|
32
|
+
}
|
|
33
|
+
lines(first: 5) {
|
|
34
|
+
nodes {
|
|
35
|
+
title
|
|
36
|
+
quantity
|
|
37
|
+
currentPrice {
|
|
38
|
+
amount
|
|
39
|
+
currencyCode
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
Variables: `{ "first": 10 }`
|
|
48
|
+
|
|
49
|
+
## Get Subscription Contract
|
|
50
|
+
|
|
51
|
+
```graphql
|
|
52
|
+
query GetSubscriptionContract($id: ID!) {
|
|
53
|
+
subscriptionContract(id: $id) {
|
|
54
|
+
id
|
|
55
|
+
status
|
|
56
|
+
createdAt
|
|
57
|
+
updatedAt
|
|
58
|
+
nextBillingDate
|
|
59
|
+
customer {
|
|
60
|
+
id
|
|
61
|
+
displayName
|
|
62
|
+
}
|
|
63
|
+
customerPaymentMethod {
|
|
64
|
+
id
|
|
65
|
+
instrument {
|
|
66
|
+
... on CustomerCreditCard {
|
|
67
|
+
brand
|
|
68
|
+
lastDigits
|
|
69
|
+
expiryMonth
|
|
70
|
+
expiryYear
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
deliveryPolicy {
|
|
75
|
+
interval
|
|
76
|
+
intervalCount
|
|
77
|
+
}
|
|
78
|
+
billingPolicy {
|
|
79
|
+
interval
|
|
80
|
+
intervalCount
|
|
81
|
+
minCycles
|
|
82
|
+
maxCycles
|
|
83
|
+
}
|
|
84
|
+
deliveryPrice {
|
|
85
|
+
amount
|
|
86
|
+
currencyCode
|
|
87
|
+
}
|
|
88
|
+
lines(first: 10) {
|
|
89
|
+
nodes {
|
|
90
|
+
id
|
|
91
|
+
title
|
|
92
|
+
variantId
|
|
93
|
+
quantity
|
|
94
|
+
currentPrice {
|
|
95
|
+
amount
|
|
96
|
+
currencyCode
|
|
97
|
+
}
|
|
98
|
+
sellingPlanId
|
|
99
|
+
sellingPlanName
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
orders(first: 5) {
|
|
103
|
+
nodes {
|
|
104
|
+
id
|
|
105
|
+
name
|
|
106
|
+
createdAt
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
Variables: `{ "id": "gid://shopify/SubscriptionContract/123" }`
|
|
113
|
+
|
|
114
|
+
## Get Billing Cycles
|
|
115
|
+
|
|
116
|
+
```graphql
|
|
117
|
+
query GetBillingCycles($contractId: ID!, $first: Int!) {
|
|
118
|
+
subscriptionBillingCycles(contractId: $contractId, first: $first) {
|
|
119
|
+
nodes {
|
|
120
|
+
cycleIndex
|
|
121
|
+
cycleStartAt
|
|
122
|
+
cycleEndAt
|
|
123
|
+
status
|
|
124
|
+
skipped
|
|
125
|
+
billingAttemptExpectedDate
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
Variables: `{ "contractId": "gid://shopify/SubscriptionContract/123", "first": 12 }`
|
|
131
|
+
|
|
132
|
+
## Get Specific Billing Cycle
|
|
133
|
+
|
|
134
|
+
```graphql
|
|
135
|
+
query GetBillingCycle($billingCycleInput: SubscriptionBillingCycleInput!) {
|
|
136
|
+
subscriptionBillingCycle(billingCycleInput: $billingCycleInput) {
|
|
137
|
+
cycleIndex
|
|
138
|
+
cycleStartAt
|
|
139
|
+
cycleEndAt
|
|
140
|
+
status
|
|
141
|
+
skipped
|
|
142
|
+
billingAttemptExpectedDate
|
|
143
|
+
sourceContract {
|
|
144
|
+
id
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
Variables:
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"billingCycleInput": {
|
|
153
|
+
"contractId": "gid://shopify/SubscriptionContract/123",
|
|
154
|
+
"selector": {
|
|
155
|
+
"index": 3
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## List Billing Attempts
|
|
162
|
+
|
|
163
|
+
```graphql
|
|
164
|
+
query ListBillingAttempts($first: Int!) {
|
|
165
|
+
subscriptionBillingAttempts(first: $first, sortKey: CREATED_AT, reverse: true) {
|
|
166
|
+
nodes {
|
|
167
|
+
id
|
|
168
|
+
createdAt
|
|
169
|
+
ready
|
|
170
|
+
errorMessage
|
|
171
|
+
subscriptionContract {
|
|
172
|
+
id
|
|
173
|
+
}
|
|
174
|
+
order {
|
|
175
|
+
id
|
|
176
|
+
name
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Create Subscription Draft
|
|
184
|
+
|
|
185
|
+
```graphql
|
|
186
|
+
mutation CreateSubscriptionDraft($input: SubscriptionDraftInput!) {
|
|
187
|
+
subscriptionDraftCreate(input: $input) {
|
|
188
|
+
draft {
|
|
189
|
+
id
|
|
190
|
+
}
|
|
191
|
+
userErrors {
|
|
192
|
+
field
|
|
193
|
+
message
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Update Subscription Draft
|
|
200
|
+
|
|
201
|
+
```graphql
|
|
202
|
+
mutation UpdateSubscriptionDraft($draftId: ID!, $input: SubscriptionDraftInput!) {
|
|
203
|
+
subscriptionDraftUpdate(draftId: $draftId, input: $input) {
|
|
204
|
+
draft {
|
|
205
|
+
id
|
|
206
|
+
status
|
|
207
|
+
}
|
|
208
|
+
userErrors {
|
|
209
|
+
field
|
|
210
|
+
message
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
Variables:
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"draftId": "gid://shopify/SubscriptionDraft/123",
|
|
219
|
+
"input": {
|
|
220
|
+
"deliveryPolicy": {
|
|
221
|
+
"interval": "MONTH",
|
|
222
|
+
"intervalCount": 2
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Add Line to Draft
|
|
229
|
+
|
|
230
|
+
```graphql
|
|
231
|
+
mutation AddLineToDraft($draftId: ID!, $input: SubscriptionLineInput!) {
|
|
232
|
+
subscriptionDraftLineAdd(draftId: $draftId, input: $input) {
|
|
233
|
+
draft {
|
|
234
|
+
id
|
|
235
|
+
lines(first: 10) {
|
|
236
|
+
nodes {
|
|
237
|
+
title
|
|
238
|
+
quantity
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
userErrors {
|
|
243
|
+
field
|
|
244
|
+
message
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
Variables:
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"draftId": "gid://shopify/SubscriptionDraft/123",
|
|
253
|
+
"input": {
|
|
254
|
+
"productVariantId": "gid://shopify/ProductVariant/456",
|
|
255
|
+
"quantity": 1,
|
|
256
|
+
"currentPrice": {
|
|
257
|
+
"amount": "29.99",
|
|
258
|
+
"currencyCode": "USD"
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Commit Draft (Activate)
|
|
265
|
+
|
|
266
|
+
```graphql
|
|
267
|
+
mutation CommitSubscriptionDraft($draftId: ID!) {
|
|
268
|
+
subscriptionDraftCommit(draftId: $draftId) {
|
|
269
|
+
contract {
|
|
270
|
+
id
|
|
271
|
+
status
|
|
272
|
+
}
|
|
273
|
+
userErrors {
|
|
274
|
+
field
|
|
275
|
+
message
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Pause Subscription
|
|
282
|
+
|
|
283
|
+
```graphql
|
|
284
|
+
mutation PauseSubscription($subscriptionContractId: ID!) {
|
|
285
|
+
subscriptionContractPause(subscriptionContractId: $subscriptionContractId) {
|
|
286
|
+
contract {
|
|
287
|
+
id
|
|
288
|
+
status
|
|
289
|
+
}
|
|
290
|
+
userErrors {
|
|
291
|
+
field
|
|
292
|
+
message
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Resume Subscription
|
|
299
|
+
|
|
300
|
+
```graphql
|
|
301
|
+
mutation ActivateSubscription($subscriptionContractId: ID!) {
|
|
302
|
+
subscriptionContractActivate(subscriptionContractId: $subscriptionContractId) {
|
|
303
|
+
contract {
|
|
304
|
+
id
|
|
305
|
+
status
|
|
306
|
+
}
|
|
307
|
+
userErrors {
|
|
308
|
+
field
|
|
309
|
+
message
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Cancel Subscription
|
|
316
|
+
|
|
317
|
+
```graphql
|
|
318
|
+
mutation CancelSubscription($subscriptionContractId: ID!) {
|
|
319
|
+
subscriptionContractCancel(subscriptionContractId: $subscriptionContractId) {
|
|
320
|
+
contract {
|
|
321
|
+
id
|
|
322
|
+
status
|
|
323
|
+
}
|
|
324
|
+
userErrors {
|
|
325
|
+
field
|
|
326
|
+
message
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Skip Billing Cycle
|
|
333
|
+
|
|
334
|
+
```graphql
|
|
335
|
+
mutation SkipBillingCycle($billingCycleInput: SubscriptionBillingCycleInput!) {
|
|
336
|
+
subscriptionBillingCycleSkip(billingCycleInput: $billingCycleInput) {
|
|
337
|
+
billingCycle {
|
|
338
|
+
cycleIndex
|
|
339
|
+
skipped
|
|
340
|
+
}
|
|
341
|
+
userErrors {
|
|
342
|
+
field
|
|
343
|
+
message
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
Variables:
|
|
349
|
+
```json
|
|
350
|
+
{
|
|
351
|
+
"billingCycleInput": {
|
|
352
|
+
"contractId": "gid://shopify/SubscriptionContract/123",
|
|
353
|
+
"selector": {
|
|
354
|
+
"index": 5
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Contract Status
|
|
361
|
+
|
|
362
|
+
| Status | Description |
|
|
363
|
+
|--------|-------------|
|
|
364
|
+
| `ACTIVE` | Subscription is active |
|
|
365
|
+
| `PAUSED` | Temporarily paused |
|
|
366
|
+
| `CANCELLED` | Permanently cancelled |
|
|
367
|
+
| `EXPIRED` | Reached max cycles |
|
|
368
|
+
| `FAILED` | Billing failed |
|
|
369
|
+
|
|
370
|
+
## Billing/Delivery Intervals
|
|
371
|
+
|
|
372
|
+
| Interval | Description |
|
|
373
|
+
|----------|-------------|
|
|
374
|
+
| `DAY` | Daily |
|
|
375
|
+
| `WEEK` | Weekly |
|
|
376
|
+
| `MONTH` | Monthly |
|
|
377
|
+
| `YEAR` | Yearly |
|
|
378
|
+
|
|
379
|
+
## Billing Cycle Status
|
|
380
|
+
|
|
381
|
+
| Status | Description |
|
|
382
|
+
|--------|-------------|
|
|
383
|
+
| `UNBILLED` | Not yet billed |
|
|
384
|
+
| `BILLED` | Successfully billed |
|
|
385
|
+
| `SKIPPED` | Skipped by customer/merchant |
|
|
386
|
+
|
|
387
|
+
## Add Discount to Draft
|
|
388
|
+
|
|
389
|
+
```graphql
|
|
390
|
+
mutation AddDiscountToDraft($draftId: ID!, $input: SubscriptionManualDiscountInput!) {
|
|
391
|
+
subscriptionDraftDiscountAdd(draftId: $draftId, input: $input) {
|
|
392
|
+
draft {
|
|
393
|
+
id
|
|
394
|
+
}
|
|
395
|
+
userErrors {
|
|
396
|
+
field
|
|
397
|
+
message
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
Variables:
|
|
403
|
+
```json
|
|
404
|
+
{
|
|
405
|
+
"draftId": "gid://shopify/SubscriptionDraft/123",
|
|
406
|
+
"input": {
|
|
407
|
+
"title": "Loyalty Discount",
|
|
408
|
+
"value": {
|
|
409
|
+
"percentage": 10
|
|
410
|
+
},
|
|
411
|
+
"recurringCycleLimit": 3
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## API Scopes Required
|
|
417
|
+
|
|
418
|
+
- `read_own_subscription_contracts` - Read contracts
|
|
419
|
+
- `write_own_subscription_contracts` - Manage contracts
|
|
420
|
+
- `read_customer_payment_methods` - Read payment methods
|
|
421
|
+
|
|
422
|
+
## Notes
|
|
423
|
+
|
|
424
|
+
- Subscriptions require selling plans on products
|
|
425
|
+
- Billing attempts are processed automatically
|
|
426
|
+
- Customers can manage subscriptions via customer portal
|
|
427
|
+
- Failed billing triggers retry logic
|
|
428
|
+
- Drafts must be committed to create/update contracts
|
|
429
|
+
- Skipped cycles don't charge the customer
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Shopify Translations
|
|
2
|
+
|
|
3
|
+
Manage translations for products, collections, pages, and other resources via the GraphQL Admin API.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Shopify supports translating content into multiple locales. Each translatable field has a `digest` value used to register translations.
|
|
8
|
+
|
|
9
|
+
## Get Translatable Resource
|
|
10
|
+
|
|
11
|
+
```graphql
|
|
12
|
+
query GetTranslatableResource($resourceId: ID!) {
|
|
13
|
+
translatableResource(resourceId: $resourceId) {
|
|
14
|
+
resourceId
|
|
15
|
+
translatableContent {
|
|
16
|
+
key
|
|
17
|
+
value
|
|
18
|
+
digest
|
|
19
|
+
locale
|
|
20
|
+
}
|
|
21
|
+
translations(locale: "fr") {
|
|
22
|
+
key
|
|
23
|
+
value
|
|
24
|
+
locale
|
|
25
|
+
outdated
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
Variables: `{ "resourceId": "gid://shopify/Product/123" }`
|
|
31
|
+
|
|
32
|
+
## List Translatable Resources
|
|
33
|
+
|
|
34
|
+
```graphql
|
|
35
|
+
query ListTranslatableResources($resourceType: TranslatableResourceType!, $first: Int!) {
|
|
36
|
+
translatableResources(resourceType: $resourceType, first: $first) {
|
|
37
|
+
nodes {
|
|
38
|
+
resourceId
|
|
39
|
+
translatableContent {
|
|
40
|
+
key
|
|
41
|
+
value
|
|
42
|
+
digest
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
Variables: `{ "resourceType": "PRODUCT", "first": 10 }`
|
|
49
|
+
|
|
50
|
+
## Get Resources by IDs
|
|
51
|
+
|
|
52
|
+
```graphql
|
|
53
|
+
query GetTranslatableResourcesByIds($resourceIds: [ID!]!, $first: Int!) {
|
|
54
|
+
translatableResourcesByIds(resourceIds: $resourceIds, first: $first) {
|
|
55
|
+
nodes {
|
|
56
|
+
resourceId
|
|
57
|
+
translatableContent {
|
|
58
|
+
key
|
|
59
|
+
value
|
|
60
|
+
digest
|
|
61
|
+
}
|
|
62
|
+
translations(locale: "es") {
|
|
63
|
+
key
|
|
64
|
+
value
|
|
65
|
+
outdated
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
Variables:
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"resourceIds": ["gid://shopify/Product/123", "gid://shopify/Product/456"],
|
|
75
|
+
"first": 10
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Register Translations
|
|
80
|
+
|
|
81
|
+
```graphql
|
|
82
|
+
mutation RegisterTranslations($resourceId: ID!, $translations: [TranslationInput!]!) {
|
|
83
|
+
translationsRegister(resourceId: $resourceId, translations: $translations) {
|
|
84
|
+
translations {
|
|
85
|
+
key
|
|
86
|
+
value
|
|
87
|
+
locale
|
|
88
|
+
}
|
|
89
|
+
userErrors {
|
|
90
|
+
field
|
|
91
|
+
message
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
Variables:
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"resourceId": "gid://shopify/Product/123",
|
|
100
|
+
"translations": [
|
|
101
|
+
{
|
|
102
|
+
"key": "title",
|
|
103
|
+
"value": "Chandail d'été",
|
|
104
|
+
"locale": "fr",
|
|
105
|
+
"translatableContentDigest": "abc123digest"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"key": "body_html",
|
|
109
|
+
"value": "<p>Un chandail léger parfait pour l'été.</p>",
|
|
110
|
+
"locale": "fr",
|
|
111
|
+
"translatableContentDigest": "def456digest"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Register Market-Specific Translations
|
|
118
|
+
|
|
119
|
+
```graphql
|
|
120
|
+
mutation RegisterMarketTranslations($resourceId: ID!, $translations: [TranslationInput!]!) {
|
|
121
|
+
translationsRegister(resourceId: $resourceId, translations: $translations) {
|
|
122
|
+
translations {
|
|
123
|
+
key
|
|
124
|
+
value
|
|
125
|
+
locale
|
|
126
|
+
market {
|
|
127
|
+
id
|
|
128
|
+
name
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
userErrors {
|
|
132
|
+
field
|
|
133
|
+
message
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
Variables:
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"resourceId": "gid://shopify/Product/123",
|
|
142
|
+
"translations": [
|
|
143
|
+
{
|
|
144
|
+
"key": "title",
|
|
145
|
+
"value": "Summer Jumper",
|
|
146
|
+
"locale": "en-GB",
|
|
147
|
+
"translatableContentDigest": "abc123digest",
|
|
148
|
+
"marketId": "gid://shopify/Market/456"
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Remove Translations
|
|
155
|
+
|
|
156
|
+
```graphql
|
|
157
|
+
mutation RemoveTranslations($resourceId: ID!, $translationKeys: [String!]!, $locales: [String!]!) {
|
|
158
|
+
translationsRemove(resourceId: $resourceId, translationKeys: $translationKeys, locales: $locales) {
|
|
159
|
+
translations {
|
|
160
|
+
key
|
|
161
|
+
locale
|
|
162
|
+
}
|
|
163
|
+
userErrors {
|
|
164
|
+
field
|
|
165
|
+
message
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
Variables:
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"resourceId": "gid://shopify/Product/123",
|
|
174
|
+
"translationKeys": ["title", "body_html"],
|
|
175
|
+
"locales": ["fr"]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Remove Market-Specific Translations
|
|
180
|
+
|
|
181
|
+
```graphql
|
|
182
|
+
mutation RemoveMarketTranslations($resourceId: ID!, $translationKeys: [String!]!, $locales: [String!]!, $marketIds: [ID!]) {
|
|
183
|
+
translationsRemove(resourceId: $resourceId, translationKeys: $translationKeys, locales: $locales, marketIds: $marketIds) {
|
|
184
|
+
translations {
|
|
185
|
+
key
|
|
186
|
+
locale
|
|
187
|
+
}
|
|
188
|
+
userErrors {
|
|
189
|
+
field
|
|
190
|
+
message
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Translatable Resource Types
|
|
197
|
+
|
|
198
|
+
| Type | Description |
|
|
199
|
+
|------|-------------|
|
|
200
|
+
| `PRODUCT` | Products |
|
|
201
|
+
| `PRODUCT_VARIANT` | Product variants |
|
|
202
|
+
| `COLLECTION` | Collections |
|
|
203
|
+
| `ONLINE_STORE_PAGE` | Pages |
|
|
204
|
+
| `ONLINE_STORE_BLOG` | Blogs |
|
|
205
|
+
| `ONLINE_STORE_ARTICLE` | Blog articles |
|
|
206
|
+
| `ONLINE_STORE_MENU` | Navigation menus |
|
|
207
|
+
| `EMAIL_TEMPLATE` | Email templates |
|
|
208
|
+
| `SMS_TEMPLATE` | SMS templates |
|
|
209
|
+
| `SHOP` | Shop settings |
|
|
210
|
+
| `SHOP_POLICY` | Shop policies |
|
|
211
|
+
| `LINK` | Navigation links |
|
|
212
|
+
| `METAFIELD` | Metafields |
|
|
213
|
+
| `METAOBJECT` | Metaobjects |
|
|
214
|
+
| `FILTER` | Storefront filters |
|
|
215
|
+
| `PAYMENT_GATEWAY` | Payment gateways |
|
|
216
|
+
| `DELIVERY_METHOD_DEFINITION` | Shipping methods |
|
|
217
|
+
|
|
218
|
+
## Common Translatable Keys by Resource
|
|
219
|
+
|
|
220
|
+
### Products
|
|
221
|
+
- `title` - Product title
|
|
222
|
+
- `body_html` - Product description
|
|
223
|
+
- `meta_title` - SEO title
|
|
224
|
+
- `meta_description` - SEO description
|
|
225
|
+
|
|
226
|
+
### Collections
|
|
227
|
+
- `title` - Collection title
|
|
228
|
+
- `body_html` - Collection description
|
|
229
|
+
- `meta_title` - SEO title
|
|
230
|
+
- `meta_description` - SEO description
|
|
231
|
+
|
|
232
|
+
### Pages
|
|
233
|
+
- `title` - Page title
|
|
234
|
+
- `body_html` - Page content
|
|
235
|
+
|
|
236
|
+
### Metafields
|
|
237
|
+
- `value` - Metafield value (for string types)
|
|
238
|
+
|
|
239
|
+
## Translation Workflow
|
|
240
|
+
|
|
241
|
+
1. **Get translatable content** - Query the resource to get fields and digests
|
|
242
|
+
2. **Translate content** - Prepare translations with the digest values
|
|
243
|
+
3. **Register translations** - Submit translations via mutation
|
|
244
|
+
4. **Verify** - Query to confirm translations are registered
|
|
245
|
+
|
|
246
|
+
## Get Shop Locales
|
|
247
|
+
|
|
248
|
+
```graphql
|
|
249
|
+
query GetShopLocales {
|
|
250
|
+
shopLocales(published: true) {
|
|
251
|
+
locale
|
|
252
|
+
name
|
|
253
|
+
primary
|
|
254
|
+
published
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## API Scopes Required
|
|
260
|
+
|
|
261
|
+
- `read_translations` - Read translations
|
|
262
|
+
- `write_translations` - Create, update, delete translations
|
|
263
|
+
- `read_locales` - Read shop locales
|
|
264
|
+
- `write_locales` - Manage shop locales
|
|
265
|
+
|
|
266
|
+
## Notes
|
|
267
|
+
|
|
268
|
+
- Always use the `digest` value from `translatableContent` when registering translations
|
|
269
|
+
- Translations marked as `outdated: true` need to be reviewed after the source content changed
|
|
270
|
+
- Market-specific translations override locale translations for buyers in that market
|