API Endpoint

Gleanview's API has a non-REST approach and is available at https://api.gleanview.com/integration
All interactions with the API should be done by sending GET or POST requests to this URL using the following parameter:
  • request – a JSON string representing a request object, that comprises the entire payload of the client's request.

* All mentions of request in this document refer to this parameter (rather than the HTTP request), unless otherwise is explicitly specified.
* The use of POST requests is strongly recommended when sending more than 500 characters to the server.

GET Example:

curl "https://api.gleanview.com/integration?request={...}" -X GET --globoff

POST Example:

curl https://api.gleanview.com/integration -X POST --globoff -d "request={...}"

* Please note, that the values you are passing in the request should be properly escaped according to JSON format (no further escaping is neccessary, however),
and all date/time values must be given in a conventional format, showing time in the UTC timezone.
The preferable date/time format is the standard MySQL 24-hour date/time string, for example: 2019-09-05 23:01:09
Consistently, this is the format, in which the API returns date/time values. They are in UTC timezone as well (they are not converted to the user's timezone).

Authorization

Every API call should contain the client's API key. Otherwise, error code 403 is returned. A client is issued only one API key, it is generated upon registration, using a random hash algorithm, and stored in GleanView, however, there is currently no user interface to allow our clients to download the key off of our website. Therefore, you can get your API key manually by writing an e-mail to support@gleanview.com.

API key usage example

- GET:

curl "https://api.gleanview.com/integration?request={\"credentials\":{\"api-key\":\"YOUR_API_KEY\"}}" -X GET --globoff

- POST:

curl https://api.gleanview.com/integration -X POST --globoff -d "request={\"credentials\":{\"api-key\":\"YOUR_API_KEY\"}}"
Rate Limit

For security and performance reasons, each API key is limited to a certain number of requests per second (rate limit). Each request (regardless of its outcome) counts against this number, and whenever the limit is exceeded (if it happens within one second of the first request), error code 429 is returned. A new request can then be send after a full second has passed since the first request in the chain, that exceeded the limit. It is, however, recommended, that a one second delay should be issued by the client application, before attempting another request.

Our starter API rate limit is 2 op/s. Customers can request a rate limit increase upon demand, through contacting our support, as long as good practices are observed by the API client application developers, and our recommendations are taken into account. However, even after an increase, at this time, customer rate limit cannot exceed 10. This is due to technical limitations in our back-end. To avoid having your application affected by these factors, please make sure you consolidate your subsequent logical requests into the request queue, so that they are served within just one HTTPS request.

Creating a Request Queue

The request should always contain a property named "queue". Its value should be of array type, with at least one element. Each element represents a single operation, such as record creation, update etc. This way, one API call can yield one or more results, depending on the element count in the array (queue size). Result elements will be given in the same order the request queue elements were received.

Queue example

- GET:

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{},{}, ...]}" -X GET --globoff

- POST:

curl https://api.gleanview.com/integration -X POST --globoff -d "request={...,\"queue\":[{},{}, ...]}"


Queue elements have similar structure, conforming to the following definition:


{
	"module":"module-name", // Name of the module to interact with,
	"id":"record-id", // ID value of the record (for simple filtering)
	"related-module":"related-module-name",// Name of a related module (if related records are checked)
	"related-id":"related-record-id", // ID value of the related record (if related records are checked)
	"function":"function-name", // Name of the function to invoke
	"field-list":["id","name"], // List of fields to return (in case of fetching a single item or multiple items)
	"filter":{}, // Filter conditions (in case of fetching multiple items)
	"record-data":{}, // Item's data (in case of creating or updating objects)
	"options":{
		"limit":25, // How many items to retrieve (in case of fetching multiple items)
		"offset":1, // Which item order number to start with (in case of fetching multiple items)
		"order":"name"||"!name", // Data column to order by (in case of fetching multiple items, prefixed with "!" if the order is descending)
		"count-flag":false, // Flag for getting the count of results, rather than result records (always use this, if all you need is record count, do NOT fetch records and count them on your side)
		"deduplicate-flag":false, // Flag for deduplication of results (used in some edge cases)
		"multiple-flag":false, // Flag to allow updating multiple records when executing "update-record" (by default, only the first record matching the filter conditions is updated)
		"date-sort-flag":false, // Flag to simplify the record ordering by Date Created
		"group-flag":false, // Flag to group the result records by ID (if related records are checked)
		"merge-flag":false, // Flag to merge new data into the existing record (if one is found) when executing "create-record" (only supported by product module)
		"skip-stats-flag":false, // Flag to skip automatic stats update (product module only)
		"mode":"..." // This value is module-specific and affects the behavior of the function being called
	},
	"related-module-list":[] // List of related modules
}
		

* These are all the supported properties inside a request queue element. Usually, you will only need a few of them. Some of them (for ex.: limit and count-flag are mutually exclusive.

Available Modules

*  columns marked as flag hold an integer value of 0 or 1 (or NULL, which is generally treated as 0).
*  columns marked as read-only are not available for update/replace operations.
*  columns marked as write-only are only available for update/replace operations.
*  columns marked as auto have their values auto-generated on record update or in other cases, according to GV's business logic. Generally, you should not write values into these fields.
*  columns marked as lookup hold an integer value, according to the column's Lookup Schema, defined in GV's code. For details on a specific column, please contact support.
*  columns marked as json hold a JSON-formatted string (or NULL, which is treated as "{}" or "[]").
*  columns marked as orig[...] hold the initial value of the field, specified in the square brackets; the value is stored upon record creation, and never updated afterwards; these columns must be treated as read-only.
*  domain_id columns hold string values, that are deterministic hash representations of normalized (lowercase, trimmed, rid of "www") domain strings.
*  tag_list columns hold a comma-separated list of integers (tag IDs), that must be wrapped with commas: ,1,2,3, for query efficiency purposes.
*  columns prefixed with "phone_" hold one of the following formats: +19991112222 (number without extension), +19991112222x1234 (number with extension); can also hold NULL or freely-formatted prone numbers (even invalid ones), however only the first two formats are useful for search and matching purposes.

[alias: us]
  • id (string, read-only)
  • user_type_id (int, read-only) - role ID
  • sort_order (int, auto)
  • inactive (int, flag)
  • terminated (int, flag)
  • first_name (string)
  • last_name (string)
  • title (string)
  • department (string)
  • description (string)
  • phone_home (string)
  • phone_mobile (string)
  • phone_work (string)
  • phone_other (string)
  • phone_fax (string)
  • address_street (string, read-only)
  • address_city (string, read-only)
  • address_state (string, read-only)
  • address_country (string, read-only)
  • address_postalcode (string, read-only)
  • email (string, read-only)
  • email_verified (int, flag, auto)
  • email_verification_hash (string, auto)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • settings (string, json, read-only)
  • avatar_file_id (string, read-only)
[alias: ac]
  • id (string, read-only)
  • parent_id (string)
  • child_count (int, auto)
  • name (string)
  • manual (int, flag, auto) - manually created account
  • imported (int, flag, auto) - imported from file
  • stage (string)
  • stage_original (string, orig[stage])
  • type (string)
  • annual_revenue_range_id (int, lookup)
  • employee_count_range_id (int, lookup)
  • sic_code (int)
  • naics_code (int)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • user_id (string)
  • original_user_id (string, orig[user_id])
  • domain_id (string)
  • lead_type (int)
  • price_list_id (string)
  • linked_contact_id_list (string, json) - array of IDs of linked contacts
  • phone_fax (string)
  • phone_office (string)
  • phone_alternate (string)
  • billing_address_street (string)
  • billing_address_city (string)
  • billing_address_state (string)
  • billing_address_postalcode (string)
  • billing_address_country (string)
  • shipping_address_street (string)
  • shipping_address_city (string)
  • shipping_address_state (string)
  • shipping_address_postalcode (string)
  • shipping_address_country (string)
  • website (string) - company website URL
  • source (string)
  • medium (string)
  • device_id (int, lookup)
  • search_term (string)
  • order_count (int, auto) - sold opportunity count
  • order_total_amount (float, auto) - total opportunities amount
  • date_qualified (date-time, auto) - date of stage was set Qualified
  • date_processed (date-time, auto) - date when account was processed through Assignment Rules
  • do_not_process (int, flag) - skip process account through Assignment Rules
  • do_not_notify (int, flag) - do not send Assignment Notification
  • linkedin (string)
  • facebook (string)
  • twitter (string)
  • instagram (string)
  • youtube (string)
  • founded_year (string)
  • document_list (string, json) - array of file descriptors
  • description (string)
  • tag_list (string)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix

[alias: co]
  • id (string, read-only)
  • account_id (string)
  • original_user_id (string) - contact's "Created By" user ID
  • type (string)
  • email (string)
  • email2 (string)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • primary (int, flag, auto) - primary contact for the account
  • unsubscribed (int, flag, auto)
  • title (string)
  • salutation (string)
  • first_name (string)
  • last_name (string)
  • manual (int, flag) - manually created contact
  • imported (int, flag) - imported from file
  • phone_home (string)
  • phone_mobile (string)
  • phone_work (string)
  • phone_other (string)
  • phone_fax (string)
  • department (string)
  • description (string)
  • do_not_call (int, flag)
  • job_function (string)
  • job_level (string)
  • primary_address_street (string)
  • primary_address_city (string)
  • primary_address_state (string)
  • primary_address_postalcode (string)
  • primary_address_country (string)
  • alt_address_street (string)
  • alt_address_city (string)
  • alt_address_state (string)
  • alt_address_postalcode (string)
  • alt_address_country (string)
  • birthday (date-time)
  • last_sale_date (date-time)
  • linkedin (string)
  • facebook (string)
  • twitter (string)
  • instagram (string)
  • website (string)
  • document_list (string, json) - array of file descriptors
  • tag_list (string)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix

[alias: op]
  • id (string, read-only)
  • user_id (string)
  • original_user_id (string, orig[user_id])
  • name (string)
  • type (string)
  • account_id (string)
  • expected_close_date (string)
  • date_closed (string, auto)
  • stage (string)
  • date_sales_stage_changed (date-time, auto)
  • amount (float)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • description (string)
  • budget_range (string)
  • next_step (string)
  • probability (float, auto)
  • shipping_address_street (string)
  • shipping_address_city (string)
  • shipping_address_state (string)
  • shipping_address_postalcode (string)
  • shipping_address_country (string)
  • lead_type (string)
  • is_web_order (int, flag, auto)
  • source (string)
  • medium (string)
  • device_id (int, lookup)
  • search_term (string)
  • document_list (string, json) - array of file descriptors
  • tag_list (string)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix

[alias: op_co]
This module is read-only
  • id (string, read-only)
  • opportunity_id (string, read-only)
  • contact_id (string, read-only)
  • primary (int, flag, read-only) - primary contact for the opportunity
[alias: pj]
  • id (string, read-only)
  • account_id (string)
  • opportunity_id (string)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • name (string)
  • type (string)
  • user_id (string)
  • original_user_id (string, orig[user_id])
  • document_list (string, json) - array of file descriptors
  • tag_list (string)
  • status (string)
  • comment (string)
  • due_date (date-time)
  • next_ship_date (date-time)
  • vendor_list (string, json)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix

[alias: qu]
  • id (string, read-only)
  • user_id (string)
  • original_user_id (string, orig[user_id])
  • quote_number (int) - autoincrement; can be specified manually upon creation
  • custom (int, flag)
  • external_id (string) - external quote ID, used for external quoting systems, for more info ask support
  • opportunity_id (string)
  • account_id (string)
  • email_id (string)
  • quote_template_id (string, read-only)
  • web_order_id (string, read-only)
  • currency_id (string)
  • price_list_id (string)
  • exchange_rate (float)
  • sold (int, flag)
  • name (string)
  • stage (string)
  • description (string)
  • amount (float)
  • payment_amount (float)
  • payment_total_amount (float)
  • additional_discount (float)
  • payment_amount_type_id (int, lookup)
  • variable_data (string, json)
  • proposal_status_id (int, lookup)
  • payment_status_id (int, lookup)
  • signature_list (string, json, read-only)
  • activity_list (string, json, read-only)
  • notification_subject (string, read-only)
  • notification_text (string, read-only)
  • payment_message_text (string)
  • url (string)
  • shipping_address_name (string)
  • shipping_address_street (string)
  • shipping_address_city (string)
  • shipping_address_state (string)
  • shipping_address_postalcode (string)
  • shipping_address_country (string)
  • shipping_matching_type (int)
  • shipping_matches_billing (int, flag)
  • billing_address_name (string)
  • billing_address_street (string)
  • billing_address_city (string)
  • billing_address_state (string)
  • billing_address_postalcode (string)
  • billing_address_country (string)
  • billing_matching_type (int)
  • tag_list (string)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • payee_id (string, read-only)
  • expire_date (date-time)
  • date_payment (date-time, auto)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix
  • products (array) 
    *On update, when this field is present in the request, existing line items are dropped from the target proposal in favor of this field's contents
    • force_values (int, flag, write-only)
    • - if set to "1", item-level price/cost (on the quote table) override their counterparts from the product level
    • name (string)
    • model (string)
    • description (string)
    • comment (string)
    • note (string)
    • table_name (string, read-only)
    • section_name (string, read-only)
    • price (float)
    • cost (float)
    • quantity (float)
    • discount (float)
    • line_total (float, read-only)
    • options (string, read-only)
  • subtotals (array, read-only) 
    • key (string)
    • name (string)
    • amount (float)
[alias: ev]
  • id (string, read-only)
  • user_id (string)
  • bean (string) - connected object type, can be one of the listed values 
    • [NULL] - the event is not connected to any objects
    • account
    • opportunity
    • project
    • quote
  • bean_id (string) - ID of the connected object (if any)
  • contact_id (string)
  • name (string)
  • date_start (date-time)
  • duration (int) - event duration in seconds
  • description (string)
  • color (string) - can be one of the predefined colors 
    • green
    • red
    • pink
    • orange
    • yellow
    • blue
    • gray
    • purple
[alias: fs]
  • id (string, read-only)
  • visitor_id (string)
  • visit_id (string)
  • form_fill_id (string)
  • domain_id (string)
  • account_id (string)
  • contact_id (string)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • salutation (string)
  • first_name (string)
  • last_name (string)
  • company_name (string)
  • email (string)
  • email2 (string)
  • lead_type (string)
  • budget_range (string)
  • title (string)
  • department (string)
  • description (string)
  • was_modified (int, flag)
  • phone_home (string)
  • phone_mobile (string)
  • phone_work (string)
  • phone_other (string)
  • phone_fax (string)
  • primary_address_street (string)
  • primary_address_city (string)
  • primary_address_state (string)
  • primary_address_postalcode (string)
  • primary_address_country (string)
  • alt_address_street (string)
  • alt_address_city (string)
  • alt_address_state (string)
  • alt_address_postalcode (string)
  • alt_address_country (string)
  • account_type (string)
  • website (string)
  • source (string)
  • medium (string)
  • device_id (int)
  • search_term (string)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix

  • id (string, read-only)
  • activity_type_id (int, lookup, read-only)
  • location_id (string)
  • visitor_id (string)
  • account_id (string)
  • contact_id (string)
  • bean_id (string, read-only)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • id (string, read-only)
  • form_id (string)
  • url (string)
  • data (string, json) - raw form submission data
  • id (string, read-only)
  • email_id (string)
  • user_id (string)
  • campaign_id (string)
  • subject (string)
  • from (string)
  • to (string)
  • cc (string)
  • bcc (string)
  • email_body_id (string, auto)
  • email_attachment_id_list (string, json) - array of file IDs
  • message (string)
  • provider_spam_checked (int, flag)
  • status_message (string)
  • external_id (string)
  • provider_id (string)
  • extra_data (string, json) - email varibles
  • debug (string)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • date_unsubscribed (date-time, auto)
  • date_removed (date-time, auto)
  • date_opened (date-time, auto)
  • date_clicked (date-time, auto)
  • timestamp_milliseconds_status_updated (bigint, auto)
  • success (int, flag)
  • id (date-time)
  • synced (int, flag)
  • call_disposition (string)
  • phone_number (string)
  • user_id (string)
  • description (string)
  • date_held (date-time)
  • duration (int) - call duration in seconds
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • id (string, read-only)
  • user_id (string)
  • bean (string) - associated record type
  • bean_id (string) - associated record ID
  • subject (string)
  • text (string)
  • document_list (string, json) - array of file descriptors
  • id (string, read-only)
  • name (string)
  • manufacturer_id (string)
  • manufacturer (string) - supplier name
  • product_status_id (int, lookup)
  • product_type_id (int, lookup, read-only)
  • model (string, unique)
  • description (string)
  • stock (float)
  • minimum_quantity (float)
  • image_url (string) - link to product image; if multiple product images exist, URLs will be separated by spaces; when updating an existing product record, this field will retain its original value, plus any new image URLs provided in the request
  • pricing (array)  - list of pricing that is applied to the product
    • currency_id (int)
    • currency_code (string) - optional, currency abbreviation (ex.: USD, EUR, etc.), if currency_id field is not set
    • price_calculation_method_id (string, lookup, read-only)
    • price_calculation_method (string, auto)
      *When creating/updating product pricing, this field can take one of the following values:
      • fixed_price
      • editable_price
      • cost_plus_markup
      • cost_plus_margin
    • price_formula (string, read-only)
    • price (float)
    • cost (float)
  • date_entered (date-time, auto)
  • date_modified (date-time, auto)
  • Any custom fields you've defined in GV will appear here with "custom_" prefix

  • id (string, read-only)
  • name (string)
  • user_id_modified (string, read-only)
  • default_date_start (date-time)
  • default_date_end (date-time)
  • products (array) 
    *When using this field in filter, use t1 for alias:
    {"filter":[{"field":"model","operator":"=","value":"MyProductModel","alias":"t1"},... *When using this field's sub-keys in field-list, set array as value for this field:
    {"field-list":{"products":["model","currency_code"],... *Sub-keys product_id and model are interchangeable, so are currency_id and currency_code
    *mode option can be used in update-record (or create-record in combination with merge-flag); possible values are add, overwrite, add-update-price, overwrite-update-price - this options affects how products are inserted into a price list
    • id (string, read-only)
    • date_start (date-time)
    • date_end (date-time)
    • product_id (string)
    • model (string)
    • currency_id (int)
    • currency_code (string)
    • price (float)
Available Functions

This function returns the object data.

Request (GET)

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"account\",\"function\":\"get-record\",\"id\":\"aa012a04-927e-11e9-8eb2-0800274f2cef\"}]}" -X GET --globoff

Request (POST)

curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"account\",\"function\":\"get-record\",\"id\":\"aa012a04-927e-11e9-8eb2-0800274f2cef\"}]}"

Response:


[
  {
      "code": 200,
      "message": "OK\n\nDEBUG MESSAGE:\n\n---\nSELECT t0.*\nFROM `account` t0\nWHERE t0.`id`='aa012a04-927e-11e9-8eb2-0800274f2cef'\nLIMIT 1",
      "data": {
          "id": "aa012a04-927e-11e9-8eb2-0800274f2cef",
          "parent_id": null,
          "child_count": null,
          "name": "SomeAcc",
          "manual": null,
          "imported": 1,
          "disable_email_sync_flag": null,
          "stage": "Lead",
          "stage_original": "Lead",
          "type": null,
          "annual_revenue": null,
          "employee_count": null,
          ...
        }
      }
  ]
				

This function returns a list of records

Request (GET)

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":"account",\"function\":\"get-records\"}]}" -X GET --globoff

Request (POST)

curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":"account",\"function\":\"get-records\"}]}"

Response:


[
  {
      "code": 200,
      "message": "OK\n\nDEBUG MESSAGE:\n\n---\nSELECT t0.*\nFROM `account` t0\nLIMIT 1000",
      "data": [
          {
              "id": "00037bab-a930-11e7-b23e-06ff23b88cf0",
              "parent_id": null,
              "child_count": 2,
              "name": "Designer And Cad",
              "manual": null,
              "imported": 1,
              "disable_email_sync_flag": null,
              "stage": "Lead",
              "stage_original": "Lead",
              ...
            },
            {
              "id": "000852c6-6c74-11e8-8f6a-0800274f2cef",
              "parent_id": null,
              "child_count": null,
              "name": "Camper Corral (Sister Store Bus Supply)",
              "manual": null,
              "imported": 1,
              "disable_email_sync_flag": null,
              "stage": "Lead",
              "stage_original": "Lead",
              ...
            }
      ]
                
Not supported by modules: user, opportunity_contact, form_submission, activity, form_fill, email_history, call, note

This function creates a record. This function doesn't work properly with activities such as call, note, email_history, form_fill. To create activity records, you need to use the store function instead.
Some modules have deduplication rules that prevent duplicate records from being created; if the data in the request queue element matches an existing record, an error [code 500] is thrown. If you want the system to update existing records instead of throwing these errors, set option merge-flag to "true". (supported by product module only)

Request (GET)

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"account\",\"function\":\"create-record\",\"record-data\":{\"name\":\"new awesome account\"}}]}" -X GET --globoff

Request (POST)

curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"account\",\"function\":\"create-record\",\"record-data\":{\"name\":\"new awesome account\"}}]}"

Response:


	[
		{
			"code": 200,
			"message": "OK",
			"data": {
				"inserted_count": 1,
				"inserted_id": "9eaba24b-9fdc-11e9-8f0c-0800274f2cef"
			}
		}
	]
			
Not supported by module: opportunity_contact

This function updates record(s) using filter or id to select which record(s) to update.

Request 1 (GET)

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"account\",\"function\":\"update-record\",\"filter\":{\"type\":\"test\"},\"record-data\":{\"name\":\"new updated account 1\"}}]}" -X GET --globoff

Request 1 (POST)

curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"account\",\"function\":\"update-record\",\"filter\":{\"type\":\"test\"},\"record-data\":{\"name\":\"new updated account 1\"}}]}"

Response 1:


				[
				{
				"code": 200,
				"message": "OK",
				"data": {
				"updated_count": 58
				}
				}
				]
			

Request 2 (GET)

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"account\",\"function\":\"update-record\",\"id\":\"9eaba24b-9fdc-11e9-8f0c-0800274f2cef\",\"record-data\":{\"name\":\"new updated account 2\"}}]}" -X GET --globoff

Request 2 (POST)

curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"account\",\"function\":\"update-record\",\"id\":\"9eaba24b-9fdc-11e9-8f0c-0800274f2cef\",\"record-data\":{\"name\":\"new updated account 2\"}}]}"

Response 2:


				[
				{
				"code": 200,
				"message": "OK",
				"data": {
				"updated_count": 1
				}
				}
				]
			
Not supported by modules: user, opportunity_contact, quote, event, form_submission, activity, form_fill, email_history, call, note, product

This function creates or updates record(s), based on filter or id property. If existing records are found to match the criteria, then, if multiple-flag is set to true or 1, all of the records found are updated, otherwise the API would only update the first record.

Request (GET)

curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"account\",\"function\":\"replace-record\",\"id\":\"9eaba24b-9fdc-11e9-8f0c-0800274f2c11\",\"record-data\":{\"name\":\"new or existing account\"}}]}" -X GET --globoff

Request (POST)

curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"account\",\"function\":\"replace-record\",\"id\":\"9eaba24b-9fdc-11e9-8f0c-0800274f2c11\",\"record-data\":{\"name\":\"new or existing account\"}}]}"

Response:


				[
				{
				"code": 200,
				"message": "OK",
				"data": {
				"updated_count": 0,
				"inserted_count": 1
				}
				}
				]
			
Supported only by modules: form_fill, email_history, call, note

There is special logic for saving activities such as call, note, email_history, form_fill. This function creates records with additional logic involved. The data properties vary between object types:

  • call:

    • direction - incoming or outgoing
    • phone_number - preferably in the format mentioned in the previous section
    • user_id - ID of the GV user the call should log under
    • description - plain text
    • date - date and time when the call was started
    • duration - in seconds
    • disposition - the outcome of the call (possible values are defined in "Call Disposition" dropdown in Company Settings)

    Sample request (GET)

    curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"call\",\"function\":\"store\",\"record-data\":{\"direction\":\"outgoing\",\"phone_number\":\"+19991112222\",\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\",\"date\":\"2019-08-01 12:00:05\",\"duration\":92}}]}" -X GET --globoff

    Sample request (POST)

    curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"call\",\"function\":\"store\",\"record-data\":{\"direction\":\"outgoing\",\"phone_number\":\"+19991112222\",\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\",\"date\":\"2019-08-01 12:00:05\",\"duration\":92}}]}"
  • note:

    • subject - plain text
    • text - plain text or HTML
    • date - date and time when the note was taken
    • contact_id - ID of the GV contact the note should log under
    • user_id - ID of the GV user the note should log under

    Sample request (GET, without attachments)

    curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"note\",\"function\":\"store\",\"record-data\":{\"subject\":\"Test Note\",\"text\":\"Test Content\",\"date\":\"2019-08-05 16:55:00\",\"contact_id\":\"f79384b7-be05-00e0-f556-00e7a5aefe20\",\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\"}}]}" -X GET --globoff

    Sample request (POST, without attachments)

    curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"note\",\"function\":\"store\",\"record-data\":{\"subject\":\"Test Note\",\"text\":\"Test Content\",\"date\":\"2019-08-05 16:55:00\",\"contact_id\":\"f79384b7-be05-00e0-f556-00e7a5aefe20\",\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\"}}]}"

    Sample request (POST, with attachments)

    curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"note\",\"function\":\"store\",\"record-data\":{\"subject\":\"Test Note\",\"text\":\"Test Content\",\"date\":\"2019-08-05 16:55:00\",\"contact_id\":\"f79384b7-be05-00e0-f556-00e7a5aefe20\",\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\"}}]}" -F file1=@/.../file1.pdf -F file2=@/.../file2.csv
  • email_history:

    • user_id - ID of the GV user the e-mail history record should log under
    • direction - incoming or outgoing
    • subject - plain text
    • from - e-mail address
    • to - e-mail address
    • cc - e-mail address
    • bcc - e-mail address
    • body_html - plain text
    • body_text - HTML or plain text
    • date - date and time when the e-mail was sent or received by the user's mailbox provider
    • external_id - unique ID of the e-mail letter, issued by the user's mailbox provider, preferably prefixed with the shorthand of the provider name; this field is mandatory to avoid duplicate records

    Sample request (GET, without attachments)

    curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"email_history\",\"function\":\"store\",\"record-data\":{\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\",\"direction\":\"outgoing\",\"subject\":\"Test Email\",\"from\":\"person1@company1.com\",\"to\":\"person2@company2.com\",\"body_html\":\"Test <strong>HTML</strong> e-mail body\",\"body_text\":\"Test plain text e-mail body\",\"date\":\"2019-08-05 16:55:00\",\"external_id\":\"gmail-0010245\"}}]}" -X GET --globoff

    Sample request (POST, without attachments)

    curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"email_history\",\"function\":\"store\",\"record-data\":{\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\",\"direction\":\"outgoing\",\"subject\":\"Test Email\",\"from\":\"person1@company1.com\",\"to\":\"person2@company2.com\",\"body_html\":\"Test <strong>HTML</strong> e-mail body\",\"body_text\":\"Test plain text e-mail body\",\"date\":\"2019-08-05 16:55:00\",\"external_id\":\"gmail-0010245\"}}]}"

    Sample request (POST, with attachments)

    curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"email_history\",\"function\":\"store\",\"record-data\":{\"user_id\":\"c29383b6-be05-11e9-b356-0ae4ceaafe20\",\"direction\":\"outgoing\",\"subject\":\"Test Email\",\"from\":\"person1@company1.com\",\"to\":\"person2@company2.com\",\"body_html\":\"Test <strong>HTML</strong> e-mail body\",\"body_text\":\"Test plain text e-mail body\",\"date\":\"2019-08-05 16:55:00\",\"external_id\":\"gmail-0010245\"}}]}" -F file1=@/.../file1.pdf -F file2=@/.../file2.csv
  • form_fill:

    • form_id - ID of the GV form record (found in Company Settings) to provide field mapping for the data. Requires use of exact record IDs (36-character UUID hashes), which isn't comfortable for most users. Kept around for backwards compatibility.
    • form_name - Name of the GV form record (found in Company Settings) to provide field mapping for the data. Use this field instead of form_id, for convenience.
    • ip_address - IP address of the visitor who submitted the form (preferably IPv4)
    • domain - domain name of the website where the form was submitted (if provided, needs to be one of the domains registered in Company Settings)
    • hash - visitor ID (UUID hash), that allows to connect the form submission with web history
    • form_data - object containing data from the form submission

    Sample request (GET)

    curl "https://api.gleanview.com/integration?request={...,\"queue\":[{\"module\":\"form_fill\",\"function\":\"store\",\"record-data\":{\"form_name\":\"My Test Form\",\"ip_address\":\"90.100.191.94\",\"domain\":\"my.website.com\",\"hash\":\"a06c1cc0-62ea-11ea-bc55-0242ac130003\",\"form_data\":{\"first_name\":\"John\",\"last_name\":\"Smith\",\"company\":\"ABC Test Company 123\",\"email\":\"smith@abc-test-company-123.com\"}}}]}" -X GET --globoff

    Sample request (POST)

    curl https://api.gleanview.com/integration -X POST -d "request={...,\"queue\":[{\"module\":\"form_fill\",\"function\":\"store\",\"record-data\":{\"form_name\":\"My Test Form\",\"ip_address\":\"90.100.191.94\",\"domain\":\"my.website.com\",\"hash\":\"a06c1cc0-62ea-11ea-bc55-0242ac130003\",\"form_data\":{\"first_name\":\"John\",\"last_name\":\"Smith\",\"company\":\"ABC Test Company 123\",\"email\":\"smith@abc-test-company-123.com\"}}}]}"

For all the object types, the response is similar:


				[
				{
				"code": 200,
				"message": "OK",
				"data": {
				"inserted_count": 1,
				"inserted_bean_id":"df43a96a-317e-11ea-aec2-2e728ce88125"
				}
				}
				]
			

The response property inserted_bean_id contains the ID of the record created.
For call, email_history and note object types, there is a built-in process for checking duplicate records. If data provided was found to match an existing record, the ID of this record will be returned in inserted_bean_id, and no record will be created; the existing record will, however, be updated with the data from the request.
Important: If you need to update an existing record, rather than create a new one, you need to pass the record's ID as bean_id property of the record-data object. For objects of type form_fill , inserted_bean_id is always returned as NULL; these objects cannot be updated.
For note and email_history, it is possible to send attachment files using POST method; in this case the response will also contain property attachment-log, which gives a brief summary of what was uploaded with the note or e-mail.

Using Queue Result inside a Request Queue Element

A noteworthy feature of GleanView API Request Queue is chained use of results. As queue elements are processed consecutively, the result of a former element may be used as input in latter elements, particularly, for filtering. We encourage our clients to use this technique, as it allows to save on processing time and improves the application's performance.

A simple example.
A client needs to fetch one of their opportunities' related records, for instance, the owner user name of its primary contact's account. Also, the opportunity's name and the contact name is needed.

Without this technique, the client would have to perform five requests:

  1. Get the opportunity's name, account ID
  2. Get the opportunity's primary contact ID
  3. Get the contact's first and last name
  4. Get the account's user ID
  5. Get the user's first and last name

The example below shows, how this complex operation is done within just one request. This is, how the request queue will look:


"queue": [
    {
      "module": "opportunity",
      "function": "get-record",
      "id": "05a8dfa2-3b2d-11e7-be2a-0e362ec7d9bc",
      "field-list": [
        "id",
        "name",
        "account_id"
      ]
    },
    {
      "module": "opportunity_contact",
      "function": "get-record",
      "filter": {
        "primary": true,
        "opportunity_id": {
          "source": [
            {
              "offset": 0,
              "field": "id"
            }
          ],
          "expression": "%0%"
        }
      },
      "field-list": [
        "contact_id"
      ]
    },
    {
      "module": "contact",
      "function": "get-record",
      "filter": {
        "id": {
          "source": [
            {
              "offset": 0,
              "field": "contact_id"
            }
          ],
          "expression": "%0%"
        }
      },
      "field-list": [
        "first_name",
        "last_name"
      ]
    },
    {
      "module": "account",
      "function": "get-record",
      "id": {
        "source": [
          {
            "offset": 2,
            "field": "account_id"
          }
        ],
        "expression": "%0%"
      },
      "field-list": [
        "user_id"
      ]
    },
    {
      "module": "user",
      "function": "get-record",
      "filter": {
        "id": {
          "source": [
            {
              "offset": 0,
              "field": "user_id"
            }
          ],
          "expression": "%0%"
        }
      },
      "field-list": [
        "first_name",
        "last_name"
      ]
    }
  ]
		

Explanation.
To pass the result of a latter element of the queue to the current element, source and expression properties need to be defined on the filter sub-object (the value of the filter column property needs to be an object, and source/expression are defined inside it).


 "filter": {
        "id": {
          "source": [
            {
              "offset": 0,
              "field": "user_id"
            }
          ],
          "expression": "%0%"
        }
      },
      ...
		

Inside the source property, several data items can be defined, each being an object of two properties:

  • offset - the number of queue elements to go backwards, starting from the previous element (it will be number 0)
  • field - the name of the result field whose value is to be fetched into this source item

The expression property generates the value for the filter column. It uses the number between percent signs to locate the requested source item (array index, starting from zero). Essentially, it is a string, used in the outside logic. Within this string, numbers, wrapped with percent signs, are treated as special symbols and are replaced with the respective item from the source.

Summary.

  • First queue element fetches the opportunity fields: id, name, account_id.
  • Second queue element fetches a row from opportunity_contact, whose column primary is 1, and opportunity_id equals the id value from the previous queue element.
  • Third queue element fetches the contact record based on contact_id value from the previous queue element.
  • Fourth queue element retrieves the user_id value from the account record, located by the account_id value, taken from the third element going backwards in the queue. Note the offset: 2 in the source property of the filter column. Counting from zero, this is the third element prior to current.
  • Fifth queue element (the last one) loads the user data, operating by its preceding element's result.

And here is the result of the API request:


[
    {
        "code": 200,
        "message": "OK",
        "data": {
            "id": "05a8dfa2-3b2d-11e7-be2a-0e362ec7d9bc",
            "name": "marcel opp",
            "account_id": "4700d724-5cfb-11e7-be2a-0e362ec7d9bc"
        }
    },
    {
        "code": 200,
        "message": "OK",
        "data": {
            "contact_id": "fb7cdaee-3b2c-11e7-be2a-0e362ec7d9bc"
        }
    },
    {
        "code": 200,
        "message": "OK",
        "data": {
            "first_name": "Marcel",
            "last_name": "Bene"
        }
    },
    {
        "code": 200,
        "message": "OK",
        "data": {
            "user_id": "9102f512-7127-11e6-bb78-0a76494b82c1"
        }
    },
    {
        "code": 200,
        "message": "OK",
        "data": {
            "first_name": "cha",
            "last_name": "la"
        }
    }
]
		

Conclusively, the client's application using the API can process the result set and extract all desired values. It is important though, to remember the order of operations (request queue elements), for the results will be given in the same order.

Query Techniques

Where retrieving or updating records, the client can specify conditions, which should be evaluated by GleanView in order to select the records of interest. Generally, conditions are defined as with filter property of the request queue element. This property is an object of key-value pairs:

{
	"field1":"value1", // string
	"field2":1, // integer
	"field3":2.25 // float (amount)
}

This is the simple approach to filtering, useful hot most real-life scenarios. String or number values are supported, and they are directly matched with the record fields in the database.
The sample filter object above would convert to the following SQL condition:

WHERE field1='value1' AND field2=1 AND field3=2.25

If the client only wants to filter records by ID, an even simpler approach is available by using the id property:

{
	...
	"id":"437f9f6f-a13d-4bc7-a9e6-5443be0f66dc",
	...
}

This will convert to the following SQL condition:

WHERE id='437f9f6f-a13d-4bc7-a9e6-5443be0f66dc'

There are cases, when records are filtered using a related record ID. This is done by supplying the following properties: related-module, related-id. The most prominent example of such case is filtering accounts by contact ID.
Sample request queue element:

{
	"module":"account",
	"function":"get-record",
	"related-module":"contact",
	"related-id":"d720aa7c-45a6-4071-bf07-da4321041a8a",
	"field-list":["id","name","stage"]
}

This will generate an SQL query, similar to the following:

SELECT a.id, a.name, a.stage
FROM account a
JOIN contact c ON ...
WHERE c.id='d720aa7c-45a6-4071-bf07-da4321041a8a'

In other cases, the client may want to fetch some data off the records related to the main record being retrieved. To do this, related module names need to be added to related-modules property (as array elements), and related modules' columns of interest need to be added to field-list as object properties carrying two values: alias, field. The alias of the main module is always t0, the others are used as defined in Available Modules section.
The following example shows how to retrieve an account's name, along with its user's name and e-mail:

{
	"module":"account",
	"function":"get-record",
	"id":"6f816700-1866-416a-bb3f-a73bef96309a",
	"field-list":{
		"account_name":{"alias":"t0","field":"name"},
		"account_stage":{"alias":"t0","field":"stage"},
		"user_first_name":{"alias":"us","field":"first_name"},
		"user_last_name":{"alias":"us","field":"last_name"},
		"user_email":{"alias":"us","field":"email"},
	},
	"related-module-list":["user"]
}

The SQL query behind this request queue element follows:

SELECT
	t0.name AS 'account_name',
	t0.stage AS 'account_stage',
	us.first_name AS 'user_first_name',
	us.last_name AS 'user_last_name',
	us.email AS 'user_email'
FROM account t0
LEFT JOIN user us ON ...
WHERE t0.id='6f816700-1866-416a-bb3f-a73bef96309a'

Advanced Techniques
Several other query tweaks are offered, although some of them do not cover all modules and cannot be applied universally.

  • result counting is done by setting count-flag property in options to true or 1. Only applicable to get-records function. The result for the queue element (in case of query success) is a single row with row_count integer field being the count of records matching the query:

    Request queue element:
    {
    	"module":"account",
    	"function":"get-records",
    	"filter":{"stage":"Lead"},
    	"options":{"count-flag":true}
    }
    
    Response:
    	[
    		{
    			"code": 200,
    			"message": "OK\n\nDEBUG MESSAGE:......",
    			"data": [
    				{
    					"row_count":5200
    				}
    			]
    		}
    	]
  • result grouping is invoked by group-flag property in options to true or 1. Only applicable to get-records function, and currently grouping is only done by id column of the main module (this is hard-coded). Grouping by custom columns is not supported.
    Grouping can be done by itself (to avoid result duplication when employing related modules) or in combination with counting, which is shown in the example below:

    Request queue element:
    {
    	"module":"account",
    	"function":"get-records",
    	"filter":{"user_id":"98384899-1ed5-4af6-a7c9-1125d1ddc323"},
    	"options":{"group-flag":true},
    	"field-list":{
    		"account_name":{"alias":"t0","field":"name"},
    		"total_amount":{"alias":"op","field":"amount","function":"sum"}
    	}
    	"related-module-list":["opportunity"]
    }
    
    Response:
    [
    	{
    		"code": 200,
    		"message": "OK\n\nDEBUG MESSAGE:......",
    		"data": [
    			{
    				"account_name":"Test Account 1",
    				"total_amount":15000
    			},
    			{
    				"account_name":"Test Account 2",
    				"total_amount":250
    			},
    			...
    		]
    	}
    ]

    This example lists accounts owned by a GleanView user, along with their total opportunity amount. Sum counting is done by adding function property to the "total_amount" field definition. This property performs various operations on the field values of the grouped rows (or all rows, if group-flag is not set). Currently supported functions are:

    • sum - adds the field values as numerals
    • count - counts rows, whose values in this field are not NULL
    • count_distinct - counts distinct NON-NULL values
    • group_concat - joins distinct values as strings into a comma-separated list
  • limit, offset, order - these concepts are well-known in relational databases, and they function the same way in GleanView API. Only usable with get-records function, they are designed to allow the client to process a large set of results in several API requests, implementing a pagination mechanism.
    One important thing to know is, that order option can be defined as an array of strings - result column names (not to be confused with table columns, whose names may differ, if field-list property is set as an object - with string keys - these are result columns).
    The names in the array may be prefixed with symbols, modifying the sort direction. Also, the order of this array defines, how the sorting is done, which is explained in the example below:

    ["column1","!column2","*column3"]

    Here, the results are sorted by column1 in ascending order, then the rows, that have matching values in this column, are sorted by column2 in descending order, and lastly, the remaining matching rows are sorted by evaluating an emptiness check upon their values in column3 (rows with non-empty values go first; this order can be reversed, if "!" is added before "*").

    For simplicity, date-sort-flag option was added to sort the results by date_entered column of the main module in descending order. In simple language, this flag puts newer records first.

  • avoiding duplicates when running get-records function is done by setting deduplicate-flag option to true or 1. This is useful when making queries with related modules.

  • advanced filtering require understanding of the relational database concept and is implemented inside filter property, which, for this purpose, has to be defined as an array of objects. Each of these objects represents an SQL condition or a group of conditions (wrapped in parentheses when converted to SQL).
    These objects' structure is described below:

    • use-or - if true, the condition will be added with "OR", otherwise "AND" conjunction is used.
    • sub-conditions - array of objects with the same structure (used for condition groups, this is where nested conditions go).
    • table_alias
    • operator - one of the values:
      in, ~=, <, >, is_empty, is_zero, is_null
      These values can be preceded by "!", which will invert the operator's logic.
      If no value is given for this property, standard "equals" comparison applies.
      Consistently, passing "!" as the value will invoke "does-not-equal" comparison.
    • field - the field (column) in the condition
    • value - primitive value or array of primitive values
    • interpretation - adds additional normalization to the values in the condition; can take one of the following values:
      phone, string, string_trim, string_length
      The interpretation mechanisms are self-explanatory. If no (or invalid) value is set for this property, the value is used as is.

    The following example shows, how a structure of this kind converts to SQL.

    This is a sample filter array:

    [
    	{"table_alias":"t0","field":"child_count","operator":"!>","value":3},
    	{
    		"use-or":true,
    		"sub-conditions":[
    			{"table_alias":"co","field":"type","value":"test","interpretation":"string_trim"},
    			{"table_alias":"co","field":"job_function","operator":"!in","value":["value1","value2"]},
    			{"table_alias":"co","field":"name","operator":"~=","value":"test name"}
    		]
    	},
    ]

    And this is the SQL code it converts to:

    t0.child_count<=3
    OR (
    	TRIM(IFNULL(co.type,''))='test'
    	AND job_function NOT IN ('value1','value2')
    	AND LOCATE('test name',IFNULL(name,''))>0
    )
    

    This approach allows for extensive coding and implementation of complex queries, aimed to access very specific data, based on unique business logic. Use of these features with GleanView API allows to tailor the request to the client's specific workflow, but requires deep programming knowledge and sets a learning curve to be able to work around the API's limitations and avoid performance trade-offs.
    Please contact support, if you have questions.