REST API v2
Translations

Translations

Translation management for storefront text and multi-language support

Get system default translations

GET/rest_api/v2/translations/defaults

Returns system default translations only (no merchant overrides). Use this to compare against GET /translations and identify which values are merchant customizations vs system defaults.

Important: Also use this endpoint to look up the correct translation key before calling PUT. Many keys have internal prefixes (e.g., [[WidgetV2]], [[Checkout]]) that differ from the displayed UI text. Search by value (not key) in the response to find the exact key to use in PUT requests.

Authorizations
X-Joy-Loyalty-App-KeystringRequired
X-Joy-Loyalty-Secret-KeystringRequired
Responses
200System default translations for all supported locales
successbooleanOptional
Example: true
dataobjectOptional

System translations keyed by locale code

metaobjectOptional

Additional metadata such as counts and pagination

messagestringOptional
Example: "Operation completed successfully"
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
GET/rest_api/v2/translations/defaults
GET /rest_api/v2/translations/defaults HTTP/1.1
Host: dev-api.joy.so
X-Joy-Loyalty-App-Key: YOUR_API_KEY
X-Joy-Loyalty-Secret-Key: YOUR_API_KEY
Accept: */*
200System default translations for all supported locales
{
"success": true,
"data": {},
"meta": {},
"message": "Operation completed successfully",
"timestamp": "2023-07-28T07:27:54.123Z"
}

Get all translations

GET/rest_api/v2/translations

Returns translation config and text for ALL languages (primary + additional), merged with system defaults. Each language contains ~300+ translation key-value pairs.

Response includes config fields (primaryLanguage, detectMethod, additionalLanguages, embedContent) and dynamic language objects (en, fr, de, etc.) with translation key-value pairs.

Authorizations
X-Joy-Loyalty-App-KeystringRequired
X-Joy-Loyalty-Secret-KeystringRequired
Responses
200Full translation config and text
successbooleanOptional
Example: true
dataTranslationConfigOptional

Full translation object containing config and text for all languages. Language keys (en, fr, de...) are dynamic objects with translation key-value pairs. Mirrors the internal admin translation system.

Example: {"primaryLanguage":"en","detectMethod":"browserLanguage","additionalLanguages":[{"code":"fr","active":true}],"embedContent":["en","fr"],"en":{"Join Program":"Join Program","Redeem":"Redeem","Ways to earn":"Ways to earn"},"fr":{"Join Program":"Rejoindre le programme","Redeem":"Échanger","Ways to earn":"Façons de gagner"}}
Show properties
primaryLanguagestringOptional

Primary language code

Example: "en"
detectMethodstringOptional

How to detect customer language:

  • customerIp: By IP geolocation
  • browserLanguage: By browser language setting
  • optionalStorefrontLanguage: Use Shopify storefront language
Example: "browserLanguage"
additionalLanguagesobject[]Optional

Additional languages with active status

Show properties
codestringOptional

Language code

Example: "fr"
activebooleanOptional

Whether language is active for customers

Example: true
embedContentstring[]Optional

Languages for embedded content (FAQs, exclusive products)

Example: ["en","fr"]
metaobjectOptional

Additional metadata such as counts and pagination

messagestringOptional
Example: "Operation completed successfully"
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
GET/rest_api/v2/translations
GET /rest_api/v2/translations HTTP/1.1
Host: dev-api.joy.so
X-Joy-Loyalty-App-Key: YOUR_API_KEY
X-Joy-Loyalty-Secret-Key: YOUR_API_KEY
Accept: */*
200Full translation config and text
{
"success": true,
"data": {
"primaryLanguage": "en",
"detectMethod": "browserLanguage",
"additionalLanguages": [
{
"code": "fr",
"active": true
}
],
"embedContent": [
"en",
"fr"
],
"en": {
"Join Program": "Join Program",
"Redeem": "Redeem",
"Ways to earn": "Ways to earn"
},
"fr": {
"Join Program": "Rejoindre le programme",
"Redeem": "Échanger",
"Ways to earn": "Façons de gagner"
}
},
"meta": {},
"message": "Operation completed successfully",
"timestamp": "2023-07-28T07:27:54.123Z"
}

Update translations

PUT/rest_api/v2/translations

Updates translation config and text. Send the full translation object from the GET response with modifications applied (not partial updates).

⚠️ Key Lookup Warning: Translation keys are NOT always the same as the displayed UI text. Many keys have internal prefixes such as [[WidgetV2]], [[Checkout]], [[POS]], etc.

Example:

  • UI text: Ways to earn
  • Actual key: [[WidgetV2]]Ways to earn

Before calling PUT to update a specific text:

  1. ALWAYS call GET /translations/defaults first
  2. Search by VALUE (not key) to find the correct key — filter entries where value matches the target text
  3. Use the exact key found in step 2 for the PUT request

Sending a PUT with a non-existent key will return success: true but will have no visible effect on the storefront.

Workflow: GET /translations/defaults → find correct key by value → GET /translations → modify keys → PUT /translations with entire object.

Behavior:

  1. Diffs request vs system defaults — only stores overrides in Firestore
  2. If primaryLanguage or its content changed — auto-translates ALL additional languages via Google Translate API
  3. If embedContent changed — triggers background jobs for FAQs and exclusive products
  4. Publishes metafield sync to Shopify

Idempotent: GET → PUT unchanged = no side effects (diff produces empty result).

CRITICAL — PUT REPLACES, does NOT merge: Sending only a subset of keys will DELETE all other existing merchant customizations. You MUST send the complete object from GET with your modifications applied.

Data loss example:

  • Existing customs: {en: {"A": "custom A", "B": "custom B"}}
  • PUT with: {en: {"C": "custom C"}} (partial)
  • Result: {en: {"C": "custom C"}} — A and B are permanently lost

Correct workflow:

  1. GET /translations — get current full state (all keys)
  2. GET /translations/defaults — get system defaults
  3. Find the correct key by searching defaults by VALUE
  4. Modify the key in the full GET response
  5. PUT /translations — send the entire modified object back
Authorizations
X-Joy-Loyalty-App-KeystringRequired
X-Joy-Loyalty-Secret-KeystringRequired
Request body
primaryLanguagestringOptional

Primary language code

Example: "en"
detectMethodstringOptional

How to detect customer language:

  • customerIp: By IP geolocation
  • browserLanguage: By browser language setting
  • optionalStorefrontLanguage: Use Shopify storefront language
Example: "browserLanguage"
additionalLanguagesobject[]Optional

Additional languages with active status

Show properties
codestringOptional

Language code

Example: "fr"
activebooleanOptional

Whether language is active for customers

Example: true
embedContentstring[]Optional

Languages for embedded content (FAQs, exclusive products)

Example: ["en","fr"]
Responses
200Save succeeded
successbooleanOptional
Example: true
dataobjectOptional
Show properties
updatedbooleanOptional
Example: true
metaobjectOptional

Additional metadata such as counts and pagination

messagestringOptional
Example: "Operation completed successfully"
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
500Firestore save failed (e.g., undefined values in data)
successbooleanOptional
Example: false
errorobjectOptional
Show properties
messagestringOptional
Example: "Resource not found"
codestringOptional
Example: "NOT_FOUND"
statusCodeintegerOptional
Example: 404
detailsobjectOptional
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
PUT/rest_api/v2/translations
PUT /rest_api/v2/translations HTTP/1.1
Host: dev-api.joy.so
X-Joy-Loyalty-App-Key: YOUR_API_KEY
X-Joy-Loyalty-Secret-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 66
{
"primaryLanguage": "en",
"detectMethod": "browserLanguage"
}
200Save succeeded
{
"success": true,
"data": {
"updated": true
},
"meta": {},
"message": "Operation completed successfully",
"timestamp": "2023-07-28T07:27:54.123Z"
}

Add a new language

POST/rest_api/v2/translations/languages

Adds a new language and auto-translates all text (~300+ keys) from the primary language using Google Translate API. Also auto-translates program titles and milestone descriptions.

Returns the full translation object with the new language included.

Authorizations
X-Joy-Loyalty-App-KeystringRequired
X-Joy-Loyalty-Secret-KeystringRequired
Request body
primaryLanguagestringRequired

Source language code to translate from

Example: "en"
additionalLanguagestringRequired

Target language code to add

Example: "fr"
Responses
201Language added with auto-translated text
successbooleanOptional
Example: true
dataTranslationConfigOptional

Full translation object containing config and text for all languages. Language keys (en, fr, de...) are dynamic objects with translation key-value pairs. Mirrors the internal admin translation system.

Example: {"primaryLanguage":"en","detectMethod":"browserLanguage","additionalLanguages":[{"code":"fr","active":true}],"embedContent":["en","fr"],"en":{"Join Program":"Join Program","Redeem":"Redeem","Ways to earn":"Ways to earn"},"fr":{"Join Program":"Rejoindre le programme","Redeem":"Échanger","Ways to earn":"Façons de gagner"}}
Show properties
primaryLanguagestringOptional

Primary language code

Example: "en"
detectMethodstringOptional

How to detect customer language:

  • customerIp: By IP geolocation
  • browserLanguage: By browser language setting
  • optionalStorefrontLanguage: Use Shopify storefront language
Example: "browserLanguage"
additionalLanguagesobject[]Optional

Additional languages with active status

Show properties
codestringOptional

Language code

Example: "fr"
activebooleanOptional

Whether language is active for customers

Example: true
embedContentstring[]Optional

Languages for embedded content (FAQs, exclusive products)

Example: ["en","fr"]
metaobjectOptional

Additional metadata such as counts and pagination

messagestringOptional
Example: "Operation completed successfully"
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
400Invalid or unsupported locale
successbooleanOptional
Example: false
errorobjectOptional
Show properties
messagestringOptional
Example: "Resource not found"
codestringOptional
Example: "NOT_FOUND"
statusCodeintegerOptional
Example: 404
detailsobjectOptional
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
POST/rest_api/v2/translations/languages
POST /rest_api/v2/translations/languages HTTP/1.1
Host: dev-api.joy.so
X-Joy-Loyalty-App-Key: YOUR_API_KEY
X-Joy-Loyalty-Secret-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 59
{
"primaryLanguage": "en",
"additionalLanguage": "fr"
}
201Language added with auto-translated text
{
"success": true,
"data": {
"primaryLanguage": "en",
"detectMethod": "browserLanguage",
"additionalLanguages": [
{
"code": "fr",
"active": true
}
],
"embedContent": [
"en",
"fr"
],
"en": {
"Join Program": "Join Program",
"Redeem": "Redeem",
"Ways to earn": "Ways to earn"
},
"fr": {
"Join Program": "Rejoindre le programme",
"Redeem": "Échanger",
"Ways to earn": "Façons de gagner"
}
},
"meta": {},
"message": "Operation completed successfully",
"timestamp": "2023-07-28T07:27:54.123Z"
}

Remove a language

DELETE/rest_api/v2/translations/languages/{locale}

Removes a language. Clears all translation data for that locale and removes it from the additionalLanguages array. Publishes metafield sync after removal.

Authorizations
X-Joy-Loyalty-App-KeystringRequired
X-Joy-Loyalty-Secret-KeystringRequired
Parameters
localepath · stringRequired

Language code to remove

Responses
200Language removed
successbooleanOptional
Example: true
404No translation document found for shop
successbooleanOptional
Example: false
errorobjectOptional
Show properties
messagestringOptional
Example: "Resource not found"
codestringOptional
Example: "NOT_FOUND"
statusCodeintegerOptional
Example: 404
detailsobjectOptional
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
DELETE/rest_api/v2/translations/languages/{locale}
DELETE /rest_api/v2/translations/languages/{locale} HTTP/1.1
Host: dev-api.joy.so
X-Joy-Loyalty-App-Key: YOUR_API_KEY
X-Joy-Loyalty-Secret-Key: YOUR_API_KEY
Accept: */*
200Language removed
{
"success": true
}

Update FAQ translations

PUT/rest_api/v2/translations/faqs

Updates FAQ translations separately from main translations. Each language has an array of FAQ items (title, content, orderBy). Triggers a background job to process FAQ translation updates and sync to Shopify metafields.

Authorizations
X-Joy-Loyalty-App-KeystringRequired
X-Joy-Loyalty-Secret-KeystringRequired
Request body
translateFaqsobjectRequired

FAQ translations keyed by language code

Example: {"en":[{"title":"How does it work?","content":"Earn points on every purchase...","orderBy":0}],"fr":[{"title":"Comment ça marche?","content":"Gagnez des points à chaque achat...","orderBy":0}]}
Responses
200FAQ translations updated
successbooleanOptional
Example: true
400Missing translateFaqs field
successbooleanOptional
Example: false
errorobjectOptional
Show properties
messagestringOptional
Example: "Resource not found"
codestringOptional
Example: "NOT_FOUND"
statusCodeintegerOptional
Example: 404
detailsobjectOptional
timestampstring · date-timeOptional
Example: "2023-07-28T07:27:54.123Z"
PUT/rest_api/v2/translations/faqs
PUT /rest_api/v2/translations/faqs HTTP/1.1
Host: dev-api.joy.so
X-Joy-Loyalty-App-Key: YOUR_API_KEY
X-Joy-Loyalty-Secret-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 331
{
"translateFaqs": {
"en": [
{
"title": "How does it work?",
"content": "Earn points on every purchase...",
"orderBy": 0
}
],
"fr": [
{
"title": "Comment ça marche?",
"content": "Gagnez des points à chaque achat...",
"orderBy": 0
}
]
}
}
200FAQ translations updated
{
"success": true
}
Product
Install AppWebsiteBook a Demo
Developers
JavaScript SDKREST API v2Webhook API
Company
Avada GroupHelp CenterContact
© 2026 Joy Loyalty by Avada Group. All rights reserved.