-
Team, Professional, Business, Enterprise and Software UI/UX plans
Get in touch with Sales for licensing questions.
Webhooks notify external services such as chat clients or other external APIs of events. A webhook can set a URL when a specific event takes place.
Important
File uploads only trigger the uploads:create and uploads:processing webhook events.
keys:create, keys:update, translations:create and translations:update webhook events are not triggered by file uploads or automated imports via:
There is a 30-day retention period for webhook history.
Webhook response
A webhook endpoint must return an HTTP status code in the 200–299 range within 5 seconds of receiving a callback. Other status codes and request timeouts are considered to be delivery failures. A webhook will be deactivated if delivery fails for more than 10 consecutive events. Callbacks are not repeated.
If receiving a callback, respond within the 5-second request timeout period. To ensure applications don’t accidentally trigger a timeout, defer processing until after the HTTP response has been sent.
Webhook request integrity
Each webhook request includes an X-PhraseApp-Signature header which is generated using the webhook verification token as a secret along with the data sent in the request. Verify the request origin by computing the HMAC digest of the request body and comparing it to the value in the X-PhraseApp-Signature header.
Examples:
Ruby
def verify_webhook(signatureheader)
digest = OpenSSL::Digest::Digest.new('sha256')
hmac = OpenSSL::HMAC.digest(digest, VERIFICATION_TOKEN, request.body)
hmac = Base64.encode64(hmac).strip
hmac == signatureheader
end
PHP
function verify_webhook($signatureheader){
$hmac = hash_hmac('sha256', $requestBody, $verificationToken, true);
$hmac = trim(base64_encode($hash));
return $hmac == $signatureheader;
}
The structure of each webhook payload is defined in a schema file available at https://app.phrase.com/webhook_schemas/<event_underscored_name>.json where <event_underscored_name> corresponds to the name of the webhook event with underscores.
branches:create can be accessed via https://app.phrase.com/webhook_schemas/branches_create.json
|
Event name |
Description |
|---|---|
|
|
A branch was created. |
|
|
A branch was merged. |
|
|
A comment on a translation key was added. |
|
|
A custom metadata field value has been updated in multiple keys. |
|
|
A custom metadata field value has been updated at the key level. |
|
|
A job was marked as complete. |
|
|
A job is created. |
|
|
A locale of a job was marked as completed. |
|
|
A locale of a job was reopened. |
|
|
A locale of a job was reviewed and marked as complete. |
|
|
A locale of a job was reviewed and reopened. |
|
|
A job was reopened. |
|
|
A job was started. |
|
|
A job is updated. |
|
|
Multiple keys were deleted. |
|
|
A key was created. |
|
|
A key was deleted. |
|
|
Tags were added to multiple keys. |
|
|
Tags were added to a key. |
|
|
A key was renamed or changed. |
|
|
A new language version was created in a project. |
|
|
A language version was deleted. |
|
|
A language version was changed, renamed or reconfigured. |
|
|
A project was changed or reconfigured. |
|
|
An OTA release has been created. |
|
|
An OTA release has been deleted. |
|
|
A screenshot was created. |
|
|
A screenshot was deleted. |
|
|
A screenshot was changed or renamed. |
|
|
A list of translations has been deleted. |
|
|
A list of translations has been included. |
|
|
A list of translations has been reviewed. |
|
|
A list of translations has been unreviewed. |
|
|
A list of translations has been unverified. |
|
|
A list of translations has been verified. |
|
|
A translation of a key in a certain language version was added. |
|
|
A translation of a key in a certain language version was delivered by a language service provider. |
|
|
A translation of a key in a certain language version was excluded. |
|
|
A translation of a key in a certain language version was included. |
|
|
A translation of a key in a certain language version was reviewed. |
|
|
A translation of a key in a certain language version was unreviewed. |
|
|
A translation of a key in a certain language version was unverified. |
|
|
A translation of a key in a certain language version was edited. |
|
|
A translation of a key in a certain language version was verified. |
|
|
A locale file was successfully processed. |
|
|
A locale file is being processed. |
To add a webhook, follow these steps:
-
From the page, scroll down to and click Configure.
The page opens.
-
Click Add webhook.
The window opens.
-
Provide webhook details.
-
Optionally .
-
Click Save. The specified webhook is added the list on the page.
A webhook can be deactivated from the menu of a specific webhook.
To test a webhook:
-
From the page, select a webhook and select Send Test-Notification from the menu.
A notice is presented indicated the test was successful.
Use a service such as RequestBin to capture the contents of a webhook. RequestBin provides a URL that collects request data for inspection.
A POST request is sent to the specified callback URL each time an event of the specified type occurs. The request’s POST payload is a JSON-encoded document with relevant data for the event. The attributes event, message and sent_at will always be included, along with additional attributes relevant to the event such as the user, project and branch the webhook was triggered from.
Reponse headers
HTTP requests made to the callback URL will contain several special headers.
-
X-PhraseApp-Event: The type of event that triggered the webhook. -
X-PhraseApp-Signature: The HMAC hex digest of the payload, using the hook's secret as the key.
Example:
Content-Type: application/json
X-PhraseApp-Event: translation:create
X-PhraseApp-Signature: abc123
{
"event": "translations:create",
"message": "Peter translated page.help.title in fr.",
"sent_at": "2015-01-29T09:52:53Z"
"user": {
"id": "abcd1234cdef1234abcd1234cdef1234",
"username": "joe.doe",
"name": "Joe Doe",
"email": "joe@phrase.com",
"position": "Lead Developer",
"created_at": "2015-01-28T09:52:53Z",
"updated_at": "2015-01-28T09:52:53Z"
},
"project": {
"id": "abcd1234cdef1234abcd1234cdef1234",
"name": "My Android Project",
"main_format": "xml",
"project_image_url": "http://assets.phrase.com/project.png",
"account": "account",
"created_at": "2015-01-28T09:52:53Z",
"updated_at": "2015-01-28T09:52:53Z"
},
"branch": {
"name": "branch_name"
},
"translation": {
"id": "abcd1234cdef1234abcd1234cdef1234",
"content": "My translation",
"unverified": false,
"excluded": false,
"plural_suffix": "",
"key": {
"id": "abcd1234cdef1234abcd1234cdef1234",
"name": "home.index.headline",
"plural": false
},
"locale": {
"id": "abcd1234cdef1234abcd1234cdef1234",
"name": "de",
"code": "de-DE"
},
"placeholders": [
"%{count}"
],
"created_at": "2015-01-28T09:52:53Z",
"updated_at": "2015-01-28T09:52:53Z"
}
}