diff --git a/README.md b/README.md index 20d175d..a7b226b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,3 @@ - - - **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* @@ -53,6 +50,17 @@ - [Lightroom APIs](#lightroom-apis) - [General Workflow](#general-workflow-2) - [How to use the Lightroom API's](#how-to-use-the-lightroom-apis) +- [Using Webhooks through Adobe I/O Events](#using-webhooks-through-adobe-io-events) + - [Registering your application to our Event Provider](#registering-your-application-to-our-event-provider) + - [Prerequisites needed to use the Event Provider](#prerequisites-needed-to-use-the-event-provider) + - [Registering the Webhook](#registering-the-webhook) + - [Triggering an Event from the API's](#triggering-an-event-from-the-apis) + - [Example 1: /documentManifest (Retrieving a PSD manifest from the Photoshop API)](#example-1-documentmanifest-retrieving-a-psd-manifest-from-the-photoshop-api) + - [Step 1: Initiate a job to retrieve a PSD's JSON manifest](#step-1-initiate-a-job-to-retrieve-a-psds-json-manifest-1) + - [Step 2: Receive the Job's status on the Webhook application when the job is complete](#step-2-receive-the-jobs-status-on-the-webhook-application-when-the-job-is-complete) + - [Example 2: /autoTone (Auto tone an image through the Lightroom API)](#example-2-autotone-auto-tone-an-image-through-the-lightroom-api) + - [Step 1: Initiate a job to auto tone an image](#step-1-initiate-a-job-to-auto-tone-an-image) + - [Step 2: Receive the Job's status on the Webhook application when the job is complete](#step-2-receive-the-jobs-status-on-the-webhook-application-when-the-job-is-complete-1) @@ -935,3 +943,210 @@ The typical workflow involves making an API POST call to the endpoint https://im ## How to use the Lightroom API's The API's are documented at [https://github.com/AdobeDocs/lightroom-api-docs](https://github.com/AdobeDocs/lightroom-api-docs/) + +# Using Webhooks through Adobe I/O Events +Adobe I/O Events offers the possibility to build an event-driven application, based on events originating from Photoshop and Lightroom API's. To start listening for events, your application needs to register a webhook URL, specifying the Event Types to receive. Whenever a matching event gets triggered, your application is notified through an HTTP POST request to the webhook URL. +The Event Provider for Photoshop and Lightroom API's is `Imaging API Events`. +This event provider has two event types: +1. `Photoshop API events` +2. `Lightroom API events` + +As the names indicate, these event types represent events triggered by the individual APIs. +## Registering your application to our Event Provider +### Prerequisites needed to use the Event Provider +1. Only supported for a `Service Integration`: To learn how to create a Service Integration, please refer to [this](https://github.com/AdobeDocs/photoshop-api-docs#service-token-workflow-adobe-etla-users) section of the document. +2. Make sure that the integration is created under your own Organization Role in https://console.adobe.io and this will ensure that you have a unique `Organization ID`. A typical ID would look something like this: `ABCDEF123B6CCB7B0A495E2E@AdobeOrg` and can be found in the overview section of the details of the integration. +3. Create a Webhook application. [This](https://www.adobe.io/apis/experienceplatform/events/docs.html#!adobedocs/adobeio-events/master/intro/webhook_docs_intro.md#your-first-webhook) page gives all the details of what the skeleton of a basic application would look like. You can find a sample NodeJS application [here](https://github.com/AdobeDocs/photoshop-api-docs/tree/master/sample_code/webhook-sample-app) + +### Registering the Webhook +Once the above prerequisites are met, you can now proceed to register the webhook to the service integration. The steps to do that can be found [here](https://www.adobe.io/apis/experienceplatform/events/docs.html#!adobedocs/adobeio-events/master/intro/webhook_docs_intro.md#registering-the-webhook). +After the webhook has been successfully registered, you will start to receive the events for any submitted job that either succeeded or failed, from the Event Types selected. This eliminates the need for your application to poll for the status of the job using the jobID. +## Triggering an Event from the API's +In order to start receiving the events in your Webhook Application, the additional thing that needs to be done is to pass in your IMS ORG ID in a header: `x-gw-ims-org-id: `, when you make an API call to initiate a job. Please have a look at the examples below that demonstrates the usage of the new header and a sample event received for that job. +### Example 1: /documentManifest (Retrieving a PSD manifest from the Photoshop API) + +#### Step 1: Initiate a job to retrieve a PSD's JSON manifest + +The `/documentManifest` api can take one or more input PSD's to generate JSON manifest files from. The JSON manifest is the tree representation of all of the layer objects contained in the PSD document. Using Example.psd, with the use case of a document stored in Adobe's Creative Cloud, a typical curl call might look like this: + +```shell +curl -X POST \ + https://image.adobe.io/pie/psdService/documentManifest \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' \ + -H 'x-api-key: ' \ + -H 'x-gw-ims-org-id: ' \ + -d '{ + "inputs": [ + { + "href":"", + "storage":"external" + } + ] +}' +``` + +This initiates an asynchronous job and returns a response containing the href to poll for job status and the JSON manifest. +```json +{ + "_links": { + "self": { + "href": "https://image.adobe.io/pie/psdService/status/63c6e812-6cb8-43de-8a60-3681a9ec6feb" + } + } +} +``` +#### Step 2: Receive the Job's status on the Webhook application when the job is complete +The value in the key `body` inside the event JSON contains the result of the job. Here is a sample event received from the job initiated above: +```json +{ + "event_id": "b412a90e-8bc0-4f0d-931e-9e9b8d24993d", + "event": { + "header": { + "msgType": "JOB_COMPLETION_STATUS", + "msgId": "8afa1a46-2733-406c-a646-e1c1acdee333", + "imsOrgId": "", + "eventCode": "photoshop-job-status", + "_pipelineMeta": { + "pipelineMessageId": "1586288145511:631472:VA7_A1:142:0" + }, + "_smarts": { + "definitionId": "3ee6c9056a9d72fc40e09ddf5fdbb0af752e8e49", + "runningSmartId": "psmart-yw6wosjksniuuathenny" + }, + "_adobeio": { + "imsOrgId": "", + "providerMetadata": "di_event_code", + "eventCode": "photoshop-job-status" + } + }, + "body": { + "jobId": "63c6e812-6cb8-43de-8a60-3681a9ec6feb", + "outputs": [ + { + "status": "succeeded", + "layers": [ + { + "id": 2, + "index": 0, + "type": "layer", + "name": "Layer", + "locked": false, + "visible": true, + "bounds": { + "top": 0, + "left": 0, + "width": 100, + "height": 100 + }, + "blendOptions": { + "opacity": 100, + "mode": "normal" + } + } + ], + "document": { + "name": "test.psd", + "width": 1000, + "height": 1000, + "bitDepth": 8, + "imageMode": "rgb", + "photoshopBuild": "Adobe Creative Imaging Service" + } + } + ], + "_links":{ + "self":{ + "href":"https://image.adobe.io/pie/psdService/status/8ec6e4f5-b580-41ac-b693-a72f150fec59" + } + } + } + } +} +``` +### Example 2: /autoTone (Auto tone an image through the Lightroom API) + +#### Step 1: Initiate a job to auto tone an image +```shell +curl -X POST \ + https://image.adobe.io/lrService/autoTone \ + -H "Authorization: Bearer $token" \ + -H "Content-Type: application/json" \ + -H "x-api-key: " \ + -H 'x-gw-ims-org-id: ' \ + -d '{ + "inputs": { + "href": "", + "storage": "external" + }, + "outputs": [ + { + "href": "", + "type": "", + "storage": "external", + "overwrite": + } + ] +}' +``` + +This initiates an asynchronous job and returns a request body containing the href to poll for job status. + +```json +{ + "_links": { + "self": { + "href": "https://image.adobe.io/lrService/status/eb4a9211-eb8a-4e88-b853-b9c08ba47427" + } + } +} +``` +#### Step 2: Receive the Job's status on the Webhook application when the job is complete +The value in the key `body` inside the event JSON contains the result of the job. Here is a sample event received from the job initiated above: +```json +{ + "event_id": "7b59cc70-88d7-4895-b204-87f5350a0cce", + "event": { + "header": { + "msgType": "JOB_COMPLETION_STATUS", + "msgId": "eb4a9211-eb8a-4e88-b853-b9c08ba47427", + "imsOrgId": "", + "eventCode": "lightroom-job-status", + "_pipelineMeta": { + "pipelineMessageId": "1586290300876:944289:VA7_A1:149:0" + }, + "_smarts": { + "definitionId": "3ee6c9056a9d72fc40e09ddf5fdbb0af752e8e49", + "runningSmartId": "psmart-yw6wosjksniuuathenny" + }, + "_adobeio": { + "imsOrgId": "", + "providerMetadata": "di_event_code", + "eventCode": "lightroom-job-status" + } + }, + "body": { + "jobId": "eb4a9211-eb8a-4e88-b853-b9c08ba47427", + "outputs": [ + { + "input": "", + "status": "succeeded", + "_links": { + "self": [ + { + "href": "", + "storage": "external" + } + ] + } + } + ], + "_links": { + "self": { + "href": "https://image.adobe.io/lrService/status/eb4a9211-eb8a-4e88-b853-b9c08ba47427" + } + } + } + } +} +``` diff --git a/sample_code/webhook-sample-app/README.md b/sample_code/webhook-sample-app/README.md new file mode 100644 index 0000000..aba560f --- /dev/null +++ b/sample_code/webhook-sample-app/README.md @@ -0,0 +1,10 @@ +# Install Node.js packages +```bash +npm install http express body-parser +``` +# Usage +Now, run the app: + +```bash +node app.js +``` diff --git a/sample_code/webhook-sample-app/app.js b/sample_code/webhook-sample-app/app.js new file mode 100644 index 0000000..863a5f4 --- /dev/null +++ b/sample_code/webhook-sample-app/app.js @@ -0,0 +1,22 @@ +const HTTP = require('http'); +const express = require('express'); +const bodyParser = require('body-parser'); + +let app = express(); +app.use(bodyParser.json({ limit: '10mb' })); + +app.get('/', function(req, res) { + res.end(req.query.challenge); +}); + +app.post('/', function(req, res) { + console.log(JSON.stringify(req.body, null, 2)); + res.end(); +}); + +let startServer = function() { + HTTP.createServer(app).listen(8888); + console.log( { "events-server": "started" }); +} + +startServer();