Develop an Oracle Eloqua app action service

Actions are steps on a campaign or program canvas that are delegated to an external system. This allows you to perform actions that you cannot do with Eloqua. Actions are analogous to the existing cloud connectors.

Actions follow the instantiation-execution model. The following sections describe action-specific details and provide the endpoints needed to develop an Action service. If you are not familiar with the general flow for the instantiation-execution model, you should read that first.

Eloqua signs all outgoing calls with OAuth 1.0a so the receiving system can validate that the call was sent by Eloqua. Refer to the OAuth 1.0a spec or OAuth 1.0 RFC for more information.

Note: If you prefer a more visual representation of the flow for Action services, see the action service flow diagram.

Create URL

Eloqua's call to the CreateURL:

POST https://example.com/awesomeapp/act/create?instance=f82d50cd-86a9-4fca-b37e-4ec9a98b0339

{}

AwesomeApp’s response is a DTO describing the fields Eloqua should transmit when the service in executed. You can include a maximum of 249 fields in your record definition. For more details, see: bulk API limits.

Note: The "Content-Type" header must be set to "application/json" for the response to the Create URL call.

Example response for contacts:

HTTP/1.1 200 application/json; charset=utf-8

{
  "recordDefinition": {
    "ContactID": "{{Contact.Id}}",
    "EmailAddress": "{{Contact.Field(C_EmailAddress)}}"
  },
  "requiresConfiguration": true
}

Example response for custom objects:

HTTP/1.1 200 application/json; charset=utf-8

{
  "recordDefinition": {
    "Email": "{{CustomObject[1].Field[4]}}"
  },
  "requiresConfiguration": true
}

requiresConfiguration is an optional Boolean parameter which tells Eloqua whether user configuration is required before the app can be used. If set to true, users will be unable to activate a campaign or program containing the unconfigured app service instance. Eloqua will display an error message.


Warning: All field names and values in Eloqua data transfer objects are case sensitive. Be sure to reproduce them exactly. For example: {{Contact.id}} would fail if the correct form is {{Contact.Id}}.

Configure URL

When a user clicks the edit button on the service instance and makes changes through the Configure URL that require an updated recordDefinition data transfer object (DTO), AwesomeApp must call out to Eloqua's cloud API PUT /actions/instances/{id} endpoint with that updated DTO:

Example request for contacts:

PUT https://secure.p03.eloqua.com/api/cloud/1.0/actions/instances/f82d50cd-86a9-4fca-b37e-4ec9a98b0339

{
    "recordDefinition":
       {
          "ContactID" : "{{Contact.Id}}",
          "EmailAddress" : "{{Contact.Field(C_EmailAddress)}}",
          "field1" : "{{Contact.Field(C_field1)}}",
          "field2" : "{{Contact.Field(C_field2)}}",
          "field3" : "{{Contact.Field(C_field3)}}"
       },
    "requiresConfiguration": false
}

Example request for custom objects:

PUT https://secure.p03.eloqua.com/api/cloud/1.0/actions/instances/f82d50cd-86a9-4fca-b37e-4ec9a98b0339

{
    "recordDefinition": {
          "Email": "{{CustomObject[1].Field[4]}}"
    },
   "requiresConfiguration": false
}

requiresConfiguration is an optional Boolean parameter which tells Eloqua whether user configuration is required before the app can be used. If set to true, users will be unable to activate a campaign or program containing the unconfigured app service instance. Eloqua will display an error message.

Use the Configure URL response to set requiresConfiguration to false when your app's configuration acceptance criteria have been met.

Note: X-Frame-Options must not be set to DENY for any configure page.

Warning: If the campaign or program is not in draft mode, attempting to set requiresConfiguration to true will result in an error.

Notification URL

Eloqua calls the Notification URL when contacts or custom objects arrive in the action step. This call transmits the requested fields in the items parameter:

POST https://example.com/awesomeapp/act/notify?instance=f82d50cd-86a9-4fca-b37e-4ec9a98b0339&asset=456

{
"offset" : 0,
"limit" : 1000,
"totalResults" : 2,
"count" : 2,
"hasMore" : false,
"items" :
[
{
"ContactID" : "1",
"EmailAddress" : "fred@example.com",
"field1" : "stuff",
"field2" : "things",
"field3" : "et cetera"
},
{
"ContactID" : "2",
"EmailAddress" : "john@example.com",
"field1" : "more stuff",
"field2" : "other things",
"field3" : "and so on"
}
]
}

Your app must respond to this call, otherwise Eloqua will think the call has timed out.

Note: The amount of records in the items parameter is dependent on the Records per Notification option during service registration. If you prefer to retrieve records using a separate export, see Retrieving app records using the bulk API for instructions.

Important: If AwesomeApp's Action service is configured to automatically set a contact or custom object record's status to complete, contacts and custom object records will move to the next step in the canvas after a successful response from the app to the notification URL call. Each batch, delivered through a call to the notification URL, of contacts or custom object records in a step will only remain in the workflow for a maximum of 90 days. Attempts to operate on them (set the status to complete or errored) after 90 days will fail, resulting in the records being stuck in the step, and requiring manual intervention to move them along in the flow. Each batch of records sent through a call to the notification URL has an ExecutionId, available as a template parameter, that identifies a unique batch.

If the action service is not configured to automatically set the status to complete, AwesomeApp should return a 204 response. This indicates that the response will be asynchronous. AwesomeApp should then create an import to Eloqua using the Bulk API where AwesomeApp specifies a sync action: either complete or errored.

Bulk API contact import

  1. Create the bulk import definition, setting the status to complete to import data.

    If there is no data to import, and you only need to update a record's status, you can update a record's status without performing an import by creating a contact sync action definition.

    When importing, the destination field refers to the action service's instance. In this example, the instance GUID is f82d50cd-86a9-4fca-b37e-4ec9a98b0339:

    Warning: When referencing service instances, you must transmit the GUID without dashes. The bulk API will error if you transmit the GUID with the dashes.

    Create a contact import definition where the sync action sets the record's status, where the instance ID is f82d50cd-86a9-4fca-b37e4ec9a98b0339 and execution ID is 12345:

    POST https://secure.p03.eloqua.com/api/bulk/2.0/contacts/imports
    {
    "name" : "AwesomeApp Action Response Bulk Import",
    "updateRule" : "always",
    "fields" : {
    "emailAddress" : "{{Contact.Field(C_EmailAddress)}}"
    },
    "syncActions" : [
    {
    "destination" : "{{ActionInstance(f82d50cd86a94fcab37e4ec9a98b0339).Execution[12345]}}",
    "action" : "setStatus",
    "status" : "complete"
    }
    ],
    "identifierFieldName" : "emailAddress"
    }

    Eloqua's response will be a 201 created response that includes a uri parameter, which you can use to identify the import:

    {
    "name" : "AwesomeApp Action Response Bulk Import",
    "updateRule" : "always",
    "fields" : {
    "emailAddress" : "{{Contact.Field(C_EmailAddress)}}"
    },
    "identifierFieldName" : "emailAddress",
    "syncActions" : [
    {
    "destination" : "{{ActionInstance(f82d50cd86a94fcab37e4ec9a98b0339).Execution[12345]}}",
    "action" : "setStatus",
    "status" : "complete"
    }
    ],
    "isSyncTriggeredOnImport" : false,
    "isUpdatingMultipleMatchedRecords" : false,
    "uri" : "/contacts/imports/6",
    "createdBy" : "DocsExample",
    "createdAt" : "2014-03-06T13:59:00.6600046Z",
    "updatedBy" : "DocsExample",
    "updatedAt" : "2014-03-06T13:59:00.6600046Z"
    }
  2. Send Eloqua the import data using the uri:

    POST https://secure.p03.eloqua.com/api/bulk/2.0/contacts/imports/6/data
    [
    {
    "emailAddress" : "fred@example.com"
    },
    {
    "emailAddress" : "sylvie@example.com"
    }
    ]
  3. Synchronize the data for import:

    AwesomeApp's request:

    POST https://secure.p03.eloqua.com/api/bulk/2.0/syncs
    {
    "syncedInstanceURI":"/contacts/imports/6"
    }

    Eloqua's response:

    201 Created

    {
    "syncedInstanceURI" : "/contacts/imports/6",
    "status" : "pending",
    "createdAt" : "2014-01-01T13:59:07.1375620Z",
    "createdBy" : "DocsExample",
    "uri" : "/syncs/6"
    }
  4. You can then use the sync's URI (/syncs/6) to check the status of the sync:

    GET https://secure.p03.eloqua.com/api/bulk/2.0/sync/6

    For a full description of the sync status codes, see: bulk API sync status codes

    When the sync is complete, Eloqua's response will resemble:

    200 OK

    {
    "syncedInstanceURI" : "/contacts/imports/6",
    "syncStartedAt" : "2014-01-01T13:59:07.1375620Z",
    "syncEndedAt" : "2014-01-01T13:59:14.1375620Z",
    "status" : "success",
    "createdAt" : "2014-01-01T13:59:07.1375620Z",
    "createdBy" : "DocsExample",
    "uri" : "/syncs/6"
    }

Learn more: Bulk API imports.

Bulk API custom object import

  1. Create the bulk import definition, setting the status to complete to import data.

    If there is no data to import, and you only need to update a record's status, you can update a record's status without performing an import by creating a custom object sync action definition.

    When importing, the destination field refers to the action service's instance - in this example, the instance GUID is f82d50cd-86a9-4fca-b37e-4ec9a98b0339:

    Warning: When referencing service instances, you must transmit the GUID without dashes. The bulk API will error if you transmit the GUID with the dashes.

    Create a custom object import definition where the sync action sets the record's status, where the instance ID is f82d50cd-86a9-4fca-b37e4ec9a98b0339 and execution ID is 12345:

    POST https://secure.p03.eloqua.com/api/bulk/2.0/customObjects/9/imports
    {
    "name" : "AwesomeApp Action Response Bulk Import",
    "updateRule" : "always",
    "fields" : {
    "email" : "{{CustomObject[9].Field[58]}}"
    },
    "syncActions" : [
    {
    "destination" : "{{ActionInstance(f82d50cd86a94fcab37e4ec9a98b0339).Execution[12345]}}",
    "action" : "setStatus",
    "status" : "complete"
    }
    ],
    "identifierFieldName" : "email"
    }

    Eloqua's response will be a 201 created response that includes a uri parameter, which you can use to identify the import:

    HTTP/1.1 201 Created

    {
    "name" : "AwesomeApp Action Response Bulk Import",
    "updateRule" : "always",
    "fields" : {
    "email" : "{{CustomObject[9].Field[58]}}"
    },
    "identifierFieldName" : "email",
    "syncActions" : [
    {
    "destination" : "{{ActionInstance(f82d50cd86a94fcab37e4ec9a98b0339).Execution[12345]}}",
    "action" : "setStatus",
    "status" : "complete"
    }
    ],
    "isSyncTriggeredOnImport" : false,
    "isUpdatingMultipleMatchedRecords" : false,
    "uri" : "/customObjects/imports/9",
    "createdBy" : "DocsExample",
    "createdAt" : "2014-03-06T13:59:00.6600046Z",
    "updatedBy" : "DocsExample",
    "updatedAt" : "2014-03-06T13:59:00.6600046Z"
    }
  2. Send Eloqua the data for import as a using the uri:

    POST https://secure.p03.eloqua.com/api/bulk/2.0/customObjects/imports/9/data
    [
    {
    "email" : "fred@example.com"
    },
    {
    "email" : "sylvie@example.com"
    }
    ]
  3. Synchronize the data for import:

    AwesomeApp request

    POST https://secure.p03.eloqua.com/api/bulk/2.0/syncs
    {
    "syncedInstanceURI":"/customObjects/imports/9"
    }

    Eloqua's response:

    201 Created

    {
    "syncedInstanceURI" : "/customObjects/imports/9",
    "status" : "pending",
    "createdAt" : "2014-01-01T13:59:07.1375620Z",
    "createdBy" : "DocsExample",
    "uri" : "/syncs/9"
    }
  4. You can then use the sync's uri (/syncs/9) to check the status of the sync:

    GET https://secure.p03.eloqua.com/api/bulk/2.0/sync/9

    For a full description of the sync status codes, see: bulk API status codes

    When the sync is complete, Eloqua's response will resemble:

    200 OK

    {
    "syncedInstanceURI" : "/customObjects/imports/9",
    "syncStartedAt" : "2014-01-01T13:59:07.1375620Z",
    "syncEndedAt" : "2014-01-01T13:59:14.1375620Z",
    "status" : "success",
    "createdAt" : "2014-01-01T13:59:07.1375620Z",
    "createdBy" : "DocsExample",
    "uri" : "/syncs/9"
    }

Learn more: Bulk API imports.

Delete URL

The delete URL is a templated URL pointing to an endpoint for deleting an instance of your service.

The delete URL uses an HTTP DELETE request and there is no content sent in the request body. All common URL template parameters are available (the same as with a create URL). On success, this endpoint should return a 200-level response.

An example delete URL would look something like:

https://www.someurl.com/delete/{appId}/{installId}/{instanceId}/{userName}/{siteName}/{siteId}

Note: Delete calls are not sent in real time, but are done in a batch once daily.

Learn more

Service descriptions

Service level URL template parameters

App developer reference