The following documentation covers Smartling callbacks. To learn about Smartling webhooks, which are a specific type of callback, see the Smartling Webhooks Overview. Although the terms are sometimes used interchangeably, it's important to understand the differences between them.
- Use callbacks when an API request starts a process that takes time, and you need to be notified once that process is finished. For example, when a source file is uploaded to Smartling via API and you want to be notified when the file upload process has been completed.
- Use webhooks when you want to receive automatic notifications for recurring events in a consistent format. For example, when you want to be notified each time a translation job is completed in a project.
A callback is a function or endpoint you provide to a system so it can notify you when a specific action is complete. It is usually one-time and tied to a particular request. Callbacks can be used to notify you of certain events. For example, you might ask a system, "Tell me when this task is finished". Once the task is complete, the system sends a callback to your specified URL with the result.
For instance, when you upload a file via API and give a callback URL, Smartling can send an HTTP request, or "callback," to the specified URL once the associated event or action has been completed.
This process is illustrated below:
Callbacks can be used to trigger automated actions in your integration, such as downloading completed translations.
Note: If your Smartling project uses string sharing, publishing one file will trigger callbacks for all files sharing those strings once all strings in a shared file are completed for a locale.
Handling callbacks
To use callbacks, you must make an internet-accessible web server available to receive and handle them. When your callback-handling server receives a valid callback request, it should respond with an HTTP status code in the 2xx range to indicate that the callback was received successfully. If a valid 2xx response is not received, Smartling will retry the callback up to 10 times. See more details on retries below.
Below are some additional recommendations for handling callbacks:
- Consider restricting access to your callback-handling server to the IP addresses of the Smartling callback service (contact Smartling Support for the list of IP addresses).
- Keep the callback handler lightweight to ensure it responds quickly. In other words, avoid putting business logic directly inside the request handler.
- Use HTTPS for improved security.
- Consider using signed requests (see below) to authenticate incoming callback requests.
- Don’t rely solely on callbacks to monitor the status of your translations. Instead supplement them with appropriate status polling.
Testing callbacks
A number of websites, such as https://webhook.site and https://requestbin.com, provide free URLs that can be used to test callbacks. Simply create a URL on one of these sites, then configure your callback to send requests to it. These sites allow you to see the details of the requests sent by the callback service.
In addition, the Ngrok service (https://ngrok.com/) allows you to tunnel callback requests to a non-publicly accessible server, enabling you to test your callback-handling code before making it public.
Callback request structure
Depending on the type of callback, either GET or POST requests may be sent. Below is an example of a GET request URL used with a Files API callback:
https://webhook.site/1e2d7a5d-94d5-4919-847e-b7bea01693bd?locale=fr-FR&publishStatus=published&fileUri=strings-1-5.txt&ts=1620744030201Note that the Smartling project ID is not included in this URL. If you need additional information such as the project ID, you can include it as part of the callback URL when configuring the callback.
Below is an example of a POST callback request body from a Jobs API callback:
{
"type": "job.completed",
"translationJobUid": "es3yo3lb8ykj",
"ts": "1644919715512"
}
Below is an example of a POST callback request body from a Strings API callback:
{
"projectId": "7d964bd0d",
"hashcode": "7467e4ace11b903446003bb5a7c10e4a",
"localeId": "fr-FR",
"type": "string.localeCompleted",
"publishStatus": "published",
"translations": [
{
"translation": "Un exemple",
"pluralForm": null,
"modifiedDate": "2021-05-11T15:20:06Z"
}
],
"ts": "1620746412599"
}
Additional examples are included below.
You can use the testing websites mentioned above to examine the details of different types of callback requests.
Signed callback requests
Signed callbacks provide greater assurance that incoming callback requests were sent by Smartling and were not tampered with. The process relies on a shared secret held by both the Smartling callback service and your callback handler: Smartling uses the shared secret to generate a signature of the request and includes the signature in a request header; when your callback handler receives the request, it follows the same process using its copy of the shared secret to validate that the result is the same. The process is described in more detail below.
Signing Procedure
Below is the signing procedure for GET requests:
- Generate a timestamp (in milliseconds since January 1st, 1970 at UTC), and add it as an additional parameter
tsin the request URL - Generate a raw binary HMAC-SHA1 signature of the full request URL using the shared secret
- Base64-encode the resulting signature and add it to a request header named
X-Smartling-Signature.
Below is the signing procedure for POST requests:
- Generate a timestamp (in milliseconds since January 1st, 1970 at UTC), and add it as an additional node ts in the request body JSON
- ‘Flatten’ the JSON structure. For example, for strings-api
POSTcallbacks, this involves moving the contents of thetranslationsnode to the top level, changing the key names into the formtranslations[0].key. See example below. - Sort the JSON content alphabetically by key
- Generate a string from the JSON structure in the form
key1=val1|key2=val2|key3=val3 - Generate a raw binary HMAC-SHA1 signature for this string using the shared secret
- Base64-encode the resulting signature and add it to a request header named
X-Smartling-Signature.
As an example of steps 2, 3, and 4 in the above process, the following POST body:
{
"projectId": "7d964bd0d",
"hashcode": "7467e4ace11b903446003bb5a7c10e4a",
"localeId": "fr-FR",
"type": "string.localeCompleted",
"publishStatus": "published",
"translations": [
{
"translation": "Un exemple",
"pluralForm": null,
"modifiedDate": "2021-05-11T15:20:06Z"
}
],
"ts": "1620746412599"
}
is normalized into this string:
hashcode=7467e4ace11b903446003bb5a7c10e4a|localeId=fr-FR|projectId=7d964bd0d|publishStatus=published|translations[0].modifiedDate=2021-05-11T15:20:06Z|translations[0].pluralForm=null|translations[0].translation=Un exemple|ts=1620746412599|type=string.localeCompletedwhich is then signed using the shared secret.
Note that the callback testing websites mentioned above sometimes display request parameters in a different order than they were received. This can result in the wrong signature being generated when testing.
Enabling signed requests
Contact your Smartling CSM to enable signed callbacks for your account. You will need to provide a shared secret in the form of a random string of ASCII characters (ideally with length > 12).
Configuring callbacks
Callbacks are configured via API call. For example, when you upload a file for translation, you can pass the URL to be used for the callback sent when the file is translated. The available callbacks, along with the methods of configuration, are listed below:
Files
| Callback event | Description | Where configured |
| File published |
Invoked when all the authorized content in a file reaches the Published workflow step in a locale. Separate callbacks are sent for each locale. Method: GET |
The callbackUrl parameter of the Upload file endpoint, the Add file to batch endpoint, or the Upload file to a batch endpoint. |
| File prepublished |
Invoked when all the authorized content in a file reaches the Published workflow step, or is prepublished, in a particular locale. Separate callbacks are sent per locale. For details on prepublishing, see Prepublish Translations. This callback is not available by default—it must be enabled by your CSM. Method: GET |
Uses the same configuration as the File published event above. |
| File upload completed |
Invoked when the upload of the file completes. This callback is disabled by default. To enable it for your project, please contact your Customer Success Manager. Method: GET |
Uses the same configuration as the File published event above. |
Jobs
| Callback event | Description | Where configured |
| Job completed |
Invoked when all the authorized content in a job, for all locales, reaches the Published step of the workflow. Method: GET or POST |
The callbackUrl and callbackMethod parameters of the Create job endpoint. |
| Job cancelled |
Invoked when a job is cancelled. Method: GET or POST |
Uses the same configuration as the Job completed event above. |
Strings
| Callback event | Description | Where configured |
| String published |
Invoked when a string translation reaches the Published workflow step in a locale. Separate callbacks are sent per locale. Method: GET or POST |
The callbackUrl and callbackMethod parameters of each string being added via the Add strings endpoint. |
| String prepublished |
Invoked when a string translation reaches the Published workflow step, or is prepublished, in a locale. Separate callbacks are sent per locale. For details on prepublishing, see Prepublish Translations. This callback is not available by default—it must be enabled by your CSM. Method: GET or POST |
Uses the same configuration as String published above. |
Issues
| Callback event | Description | Where configured |
| Various issue-related events. |
Invoked when certain issue-related events occur. Details of the supported events, and the structure of the callback requests can be found at Receive issue webhooks For more information on issues, see Using issues. Method: POST |
Issue webhooks can be enabled via Set up issue webhooks and disabled via Delete issue webhook settings. Please note that these are legacy webhooks, separate from the latest webhooks support. |
Sample callbacks
Below are some examples of callback request GET query strings and POST bodies. You can use the callback testing websites mentioned above to see the exact requests sent for your integration.
File published (GET)
?locale=ru-RU&publishStatus=published&fileUri=example.properties&ts=1542138000086File prepublished (GET)
?locale=ru-RU&publishStatus=prepublished&fileUri=example.properties&ts=1542138300048Job completed (GET)
https://callback.handler.com?type=job.completed&translationJobUid=xm5rj2kmxtaj&ts=1644920029445Job completed (POST)
{
"type": "job.completed",
"translationJobUid": "es3yo3lb8ykj",
"ts": "1644919715512"
}
Job cancelled (GET)
?type=job.cancelled&translationJobUid=vacryeniyvlkString published (POST)
{
"projectId": "cef4c4151",
"hashcode": "493c3a41b5e4648e26f6bbfb94d12341",
"localeId": "fr-FR",
"type": "string.localeCompleted",
"publishStatus":"published",
"translations": [
{
"translation": "bonjour",
"pluralForm": null,
"modifiedDate": "2021-03-19T17:32:54Z"
}
]
}
String prepublished (POST)
{
"projectId": "cef4c4151",
"hashcode": "493c3a41b5e4648e26f6bbfb94d12341",
"localeId": "fr-FR",
"type": "string.localeCompleted",
"publishStatus": "prepublished",
"translations": [
{
"translation": "bonjour",
"pluralForm": null,
"modifiedDate": "2021-03-19T17:32:54Z"
}
]
}
Retries and backoff
Failed deliveries are retried using deterministic exponential backoff, with a total of 10 attempts (including the initial delivery).
Backoff schedule
The following schedule applies to jobs, files, and strings-related callbacks.
Interval: 60,000ms (60 seconds / 1 minute)
| Attempt | Retry Count | Delay Formula | Delay (ms) | Delay (readable) | Cumulative Time |
| 1 | 0 | 2^0 × 60000 | 60,000 | 1 minute | 1m |
| 2 | 1 | 2^1 × 60000 | 120,000 | 2 minutes | 3m |
| 3 | 2 | 2^2 × 60000 | 240,000 | 4 minutes | 7m |
| 4 | 3 | 2^3 × 60000 | 480,000 | 8 minutes | 15m |
| 5 | 4 | 2^4 × 60000 | 960,000 | 16 minutes | 31m |
| 6 | 5 | 2^5 × 60000 | 1,920,000 | 32 minutes | 1h 3m |
| 7 | 6 | 2^6 × 60000 | 3,840,000 | 1h 4m | 2h 7m |
| 8 | 7 | 2^7 × 60000 | 7,680,000 | 2h 8m | 4h 15m |
| 9 | 8 | 2^8 × 60000 | 15,360,000 | 4h 16m | 8h 31m |