Signal API

The Signal API is used to report signals that occur on a specific call (transaction).

Signals may be anything an organization would like to track such as sales, quotes, etc.

Response Codes

Remember to check the HTTP status code returned. This helps greatly when debugging.

Status Code Meaning
200 OK An existing signal was found and updated
201 Created A new signal was created
401 Not Authorized Invalid or missing oauth token
403 Forbidden Attempted to access an invalid resource or provided invalid data. Check the errors object in the response.
404 Not Found Provided a transaction ID that was not found, or if using call start time and other search filters, no matching call found

Request Parameters

Passed in “application/json” format.

Search Parameters

Used to find the call associated with the signal.

Required

transaction_id: The ID of the transaction (Call leg) being reported on.

or

call_record_id: The ID of the complete call being reported on.

or

start_time_t: The start time does not have to be exact since clocks will not be perfectly synchronized. We will find the closest match (in combination with duration_in_seconds, if provided). See Timestamp Formats section below for descriptions of supported timestamps.

Note: If using start_time_t to match, instead of transaction_id, one or more of the following optional parameters is highly recommended. The optional parameters are ignored when using the transaction_id:

Optional

calling_phone_number: ANI in E.164 format +country national_number; example: ‘+18885551212’.

duration_in_seconds: Length of the call. Used for finding the call that drove the sale. Like start time, duration_in_seconds does not have to be exact, we use it to find the closest match.

advertiser_id_from_network: ID from network field on advertiser; only calls within this advertiser will be considered (only allowed when reporting as network user, and advertiser must be in same network).

advertiser_campaign_id_from_network: ID from network field on advertiser campaign; only calls within this advertiser campaign will be considered (campaign must be in the organization accessed via API).

network_id: ID of the network.


Signal Parameters

Used to create the fields of a signal.

Required

name: The name describing the signal event. For reporting a sale happened on a call, “Sale” is recommended. Other examples include “Free Trial”, “2yr Subscription”, “Cancellation.” This can be used elsewhere in the system and should be a small list of values meaningful to your organization. Names are matched case-insensitively, but we will preserve and use the casing of the first time the signal name is reported.

Optional

partner_unique_id: Unique identifier, to distinguish between updating an existing signal (for example correcting a sale that was reported) versus adding a second sale to the call (for example a reservation made while on the call and then an add on item purchased later). Note: this ID only needs to be unique within the given transaction and name, so it can be as simple as “1”, “2”… or it can be a globally unique ID if desired. Defaults to empty string if not passed.

description: Free form text for providing additional details about the signal (for example: a sales order ID or a specific product being purchased or inquired about).

occurred_at_time_t: This allows batching of signal results at a later time and still capture the exact time the signal event happened. See Timestamp Formats section below for descriptions of supported timestamps. Defaults to the time of the API request if not provided.

sale_amount: Money with up to 2 decimal places (period separated). Assumed to be in the same currency as the organization that owns the signal being reported. Defaults to null if not passed. (Recommended to omit parameter if no sale occurred, instead of passing 0). Do not include formatting such as currency symbol or separators (i.e. commas).

value: True or false as to whether the signal was met or not. Defaults to true if not passed. Can be a string ‘true’ or ‘false’, or 1 (true) or 0 (false), Yes (true), or No (false). These values are not case sensitive.

custom_parameter_1 Custom parameter. Up to 255 character string.

custom_parameter_2 Custom parameter. Up to 255 character string.

custom_parameter_3 Custom parameter. Up to 255 character string.


Additional Parameters

Required

oauth_token: API token for authentication

call_in_progress: True or false as to whether the call may still be in progress. Invoca will immediately return a 201 and empty response body when this is set to true. When the call finishes, Invoca will apply the signal.

Note: call_in_progress can be passed, even when the call has already finished. However, Invoca will only check for required fields and all other errors will not be returned. It is highly recommended to use transaction_id in the search parameters. If call_start_time is used, please provide the calling_phone_number, as well as any other information you can provide, to help avoid matching with an earlier call.

Endpoint:

https://invoca.net/api/2016-02-01/transactions/signals

Examples

Example using transaction_id (of the call to associate the signal to) and providing all signal fields:

Endpoint:

https://invoca.net/api/2016-02-01/transactions/signals.json

Request Body:

{
  "search": {
    "transaction_id": "00000000-00000001"
  },
  "signal": {
    "name": "sale",
    "partner_unique_id": "1",
    "description": "1 year contract",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "100.00",
    "value": "true",
    "custom_parameter_1": "12345",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

Response Code: 201

Response Body:

{
  "signal": {
    "transaction_id": "00000000-0000000A",
    "corrects_transaction_id": null,
    "name": "sale",
    "partner_unique_id": "1",
    "description": "1 year contract",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "100.0",
    "value": "true",
    "custom_parameter_1": "12345",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

Example using start_time_t, all optional search fields, and all signal fields:

Endpoint:

https://invoca.net/api/2016-02-01/transactions/signals.json

Request Body:

{
  "search": {
    "start_time_t": "1440607313",
    "calling_phone_number": "1234567890",
    "duration_in_seconds": "60",
    "advertiser_id_from_network": "1",
    "advertiser_campaign_id_from_network": "2",
    "network_id": "3"
  },
  "signal": {
    "name": "sale",
    "partner_unique_id": "1",
    "description": "1 year contract",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "100.00",
    "value": "true"
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

Response Code: 201

Response Body:

{
  "signal": {
    "transaction_id": "00000000-0000000A",
    "corrects_transaction_id": null,
    "name": "sale",
    "partner_unique_id": "1",
    "description": "1 year contract",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "100.0",
    "value": "true"
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

Examples

Example using transaction_id and providing all signal fields:

Endpoint:

https://invoca.net/api/2016-02-01/transactions/signals.json

Request Body:

{
  "search": {
    "transaction_id": "00000000-00000001"
  },
  "signal": {
    "name": "sale",
    "partner_unique_id": "1",
    "description": "Updated description and sale amount",
    "sale_amount": "200.00"
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

When an update occurs, a 200 status code is returned, otherwise the response body looks the same as a create.

Response Code: 200

Response Body:

{
  "signal": {
    "transaction_id": "00000000-0000000B",
    "corrects_transaction_id": "00000000-0000000A",
    "name": "sale",
    "partner_unique_id": "1",
    "description": "Updated description and sale amount",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "200.0",
    "value": "true",
    "custom_parameter_1": "",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

Note: It’s necessary to use the transaction_id of the transaction (call leg) that the signal was originally reported on. The name and partner_unique_id must also match the signal being updated.

Endpoint:

https://invoca.net/api/2016-02-01/transactions/<transaction_id>/signals

Examples

Example using transaction_id (of the call to associate the signal to) and providing all signal fields:

Endpoint:

https://invoca.net/api/2016-02-01/transactions/00000000-00000001/signals.json

Request Body:

{
  "signal": {
    "name": "sale",
    "partner_unique_id": "1",
    "description": "1 year contract",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "100.00",
    "value": "true",
    "custom_parameter_1": "12345",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

Response Code: 201

Response Body:

{
  "signal": {
    "transaction_id": "00000000-0000000A",
    "corrects_transaction_id": null,
    "name": "sale",
    "partner_unique_id": "1",
    "description": "1 year contract",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "100.0",
    "value": "true",
    "custom_parameter_1": "12345",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

Examples

Example using transaction_id and providing all signal fields:

Endpoint:

https://invoca.net/api/2016-02-01/transactions/00000000-00000001/signals.json

Request Body:

{
  "signal": {
    "name": "sale",
    "partner_unique_id": "1",
    "description": "Updated description and sale amount",
    "sale_amount": "200.00"
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

When an update occurs, a 200 status code is returned, otherwise the response body looks the same as a create.

Response Code: 200

Response Body:

{
  "signal": {
    "transaction_id": "00000000-0000000B",
    "corrects_transaction_id": "00000000-0000000A",
    "name": "sale",
    "partner_unique_id": "1",
    "description": "Updated description and sale amount",
    "occurred_at_time_t": "1440607313",
    "sale_amount": "200.0",
    "value": "true",
    "custom_parameter_1": "",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

Note: It’s necessary to use the transaction_id of the transaction (call leg) that the signal was originally reported on. The name and partner_unique_id must also match the signal being updated.

Timestamp Formats

The following formats are supported for both start_time_t and occurred_at_time_t.

All examples below correspond to a date time of 11 April 2016 at 1 PM Pacific Time.

Epoch: 10 digit timestamp in UTC seconds since 1/1/70, also known as Unix time_t. UTC milliseconds since 1/1/70 (which is the default in Javascript) are also supported, i.e. a 13 digit start time.

Example (10 digits): 1460404800

Example (13 digits): 1460404800000

Compressed: 17 digit timestamp always parsed in UTC.

Format: YYYYMMDDHHMMSSsss

Example: 20160411130000000

ISO 8601: Timestamp with +/- UTC offset or Z to indicate time is in UTC. Milliseconds are optional.

Format: YYYY/MM/DDTHH:MM:SS.sss+hh:mm

Example (UTC offset of +3 hours): 2016/04/11T23:00:00.000+03:00

Example (UTC offset of -7 hours): 2016/04/11T13:00:00.000-07:00

Example (UTC): 2016/04/11T20:00:00.000Z

Example (no milliseconds): 2016/04/11T13:00:00-07:00

Excel Compatible: Timestamp parsed in the timezone of the oauth token’s associated network. Milliseconds are optional.

Format: YYYY/MM/DD HH:MM:SS.sss AM/PM

Example: 2016/04/11 13:00:00.000 PM

Example (no milliseconds): 2016/04/11 13:00:00 PM

Note: The file upload user interface includes a timezone dropdown feature, which allows users to select which timezone this format is parsed in. Use the following to format Excel date cells: yyyy/mm/dd hh:mm:ss.000 AM/PM.

Example POST Request Using cURL

You can send call results to Invoca servers in the form of an HTTP POST or PUT. cURL is recommended because it is simple and preinstalled on most machines. Below is an example of a cURL request:

curl -k -H "Content-Type: application/json" -X POST -d '{"search": {"transaction_id": "00000000-00000001"},"signal": {"name": "sale","partner_unique_id": "1","description": "1 year contract","occurred_at_time_t": "1440607313","sale_amount": "100.00","value": "true"},"oauth_token": <YOUR OAUTH TOKEN>}'  https://invoca.net/api/<API_VERSION>/transactions/signals.json

Errors

The Signal API clearly identifies errors when a request cannot be processed.

Validation Errors

If invalid parameters are passed an error will be returned with a 403 response code. For example, if a transaction_id or start_time_t are not passed in the request, the following error will be returned.

Response (403 Forbidden):

{
  "errors": {
    "class": "RecordInvalid",
    "invalid_data": "Validation failed: transaction_id or start_time_t must be present"
  }
}

Record Not Found Error

If no record is found for the search parameters that are passed in the request an error will be returned with a 404 response code. For example, if a call cannot be found for the search parameters passed, the following error will be returned.

Response (404 Not Found):

{
  "errors": {
    "class": "RecordNotFound",
    "invalid_data": "No call found. Please refer to the documentation."
  }
}

Permission Errors

If you do not have access to the Signal API, the following error will be returned with a 403 response code.

Response (403 Forbidden):

{
  "errors": {
    "class": "UnauthorizedOperation",
    "invalid_data": "You do not have permissions to perform the requested operation."
  }
}

Authorization Errors

If you do not have access to the advertiser_id_from_network, advertiser_campaign_id_from_network, or the network_id an error will be returned with a 403 response code. For example, if you pass an advertiser_id_from_network that you do not have access to, the following error will be returned.

Response (403 Forbidden):

{
  "errors": {
    "class": "UnauthorizedAdvertiser",
    "invalid_data": "You do not have access to this advertiser"
  }
}

Updates and Idempotency

Signal are considered unique by a combination of name and partner_unique_id. For example, if you make two requests with the same name and partner_unique_id, the other params in the second request will update the original signal’s fields

Therefore, if you make two requests with the same params, the signal will not be updated nor will a new one be made. It is safe then to re-post API requests without fear of duplicate data.

If you change the partner_unique_id, a second signal of the same name will be associated with the transaction.


Example of creating two signals (on a single call) then updating one

HTTP POST Parameters - first request (creates first signal):

{
  "search": {
    "transaction_id": "00000000-00000001"
  },
  "signal": {
    "name": "Quote",
    "partner_unique_id": "1",
    "description": "Honda Accord 2015"
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

Response (201 Created):

{
  "signal": {
    "transaction_id": "00000000-0000000A",
    "corrects_transaction_id": null,
    "name": "Quote",
    "partner_unique_id": "1",
    "description": "Honda Accord 2015",
    "occurred_at_time_t": "1440607999",
    "value": "true"
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

HTTP POST Parameters - second request (creates another signal):

{
  "search": {
    "transaction_id": "00000000-00000001"
  },
  "signal": {
    "name": "Quote",
    "partner_unique_id": "2",
    "description": "Toyota Camry 2015"
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

Response (201 Created):

{
  "signal": {
    "transaction_id": "00000000-0000000B",
    "corrects_transaction_id": null,
    "name": "Quote",
    "partner_unique_id": "2",
    "description": "Toyota Camry 2015",
    "occurred_at_time_t": "1440607800",
    "value": "true",
    "custom_parameter_1": "",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

HTTP POST Parameters - third request (updates first request):

{
  "search": {
    "transaction_id": "00000000-00000001"
  },
  "signal": {
    "name": "Quote",
    "partner_unique_id": "1",
    "description": "Honda Civic 2012"
  },
  "oauth_token": "<YOUR OAUTH TOKEN>"
}

Response (200 OK):

{
  "signal": {
    "transaction_id": "00000000-0000000C",
    "corrects_transaction_id": "00000000-0000000A",
    "name": "Quote",
    "partner_unique_id": "1",
    "description": "Honda Civic 2012",
    "occurred_at_time_t": "1440607999",
    "value": "true",
    "custom_parameter_1": "",
    "custom_parameter_2": "",
    "custom_parameter_3": ""
  },
  "call": {
    "transaction_id": "00000000-00000001",
    "start_time_t": "1435993200"
  }
}

Note: even though this third request was an update to the first and will appear in reports as updating the first signal, a new signal transaction ID is returned. This is because a correction has been made to the first signal, and this new transaction ID is what will appear in webhooks and the Transactions API.