Universal CRM API - Reading data

Read data from your users' CRMs

Using Xkit's Universal CRM API, you can access records in your users' CRM. The API also supports finding relevant data via queries defined by you and configured by the user.

Read data

In order to read data from the CRM, your app needs to declare the fields that are relevant to it, which the user then maps to the actual data in their CRM.

Once configured by the user, all responses from Xkit for a CRM record for this CRM Object will be mapped according to the user's preferences.

To define fields for mapping, you pass them to the fields object in CRM Link.

Here's what the end user will experience when mapping the fields that you pass:

Mapping fields for reading using CRM Link

For example, your e-signature app may want a document_name, which the user could map to the Opportunity's Name property in Salesforce.

These fields will only apply for the CRM connection made for that specific invocation of CRM Link. Your app is responsible for managing differences in mappings between users or updates to internal schemas.

Because there are no guarantees about the structure of any given user's CRM, or even the existence of data in a mapped field, your application should always gracefully handle null values in any of your requested mapped fields.

User-defined fields

Many applications allow users to provide arbitrary data to the application. To allow your users to provide arbitrary data via their CRM, use an object-type field. An object-type field will allow your users to either:

  • Create custom fields with user-defined names and values as children of the field
  • Map the field to an object field that exists in the user's CRM

Format and Example

The fields are an object with the following structure:

  • Key: this is the slug or API name of the field, e.g. name
  • Value: an Xkit-flavored JSON schema description of the value of the field, e.g. { type: 'string' }
    • Include a label to have a user-facing title for this field
    • Include a description to help users map this field
await linkCRM('example.xkit.co', token, {
  connectionID: 'context-id',
  objects: {
    opportunity: {
      fields: {
        document_name: {
          type: "string",
          label: "Document Name",
          description: "The name of the document to pre-populate during document creation."
        },
        document_tags: {
          type: "object",
          label: "Document Tags",
          description: "Tags to apply to the document during creation"
        }
      }
    }
  }
})

Read data on demand

The Xkit API exposes two endpoints to read data on demand:

  • Get CRM Record
  • Get CRM Record Batch

In addition to these endpoints, the mapping the user defines will be used to return all records for all interactions with the Xkit CRM API.

Here's an example request/response for Get CRM Record:

Request

GET /api/v1/crm/<connectionID>/objects/opportunity/Opportunity:09876/mapping HTTP/1.1
Host: app.xkit.co
Authorization: Basic <credentials>

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "record": {
    "type": "opportunity",
    "id": "Opportunity:09876",
    "data": {
      "document_name": "Apple Opportunity Sales Contract",
      "document_tags": {}
    }
  }
}

Find data

In order to find relevant data in the user's CRM, you'll need to declare an event during CRM Link which you can later invoke using the Invoke Event endpoint.

Rather than directly searching through the user's CRM (which has an arbitrary and unknown structure), you'll instead tell the user the data that you need and they'll create a search query unique to their CRM within CRM Link to expose that data to you.

Here's how that looks from the user's perspective:

Handling a search event in CRM Link

Define search event

To define a search event, you'll pass an object to the events object of your CRM Object's definition in your CRM Link invocation with the following structure:

  • Key: this is the slug of the event, which you'll use when invoking the event in the Xkit API
  • Value: an object with the following structure
    • type: search
    • name: the user-facing name of the event, e.g. "Find Opportunities in Proposal"
    • description: the user-facing description of the event and how the user should handle it, e.g. "Opportunities or Deals in your CRM that are in a proposal stage and are available to have a document generated for them."
    • payloadSchema: Xkit-flavored JSON describing the schema of the payload you'll provide when invoking the event
await linkCRM('example.xkit.co', token, {
  connectionID: 'context-id',
  objects: {
    opportunity: {
      events: {
        find_proposal_opportunities: {
          type: "search",
          label: "Find Opportunities in Proposal",
          description: "Opportunities or Deals in your CRM that are in a proposal stage and are available to have a document generated for them.",
          payloadSchema: {
            account_id: {
              label: "Account ID",
              description: "ID of the Account associated with the opportunities",
              type: "string"
            }
          }
        }
      }
    }
  }
})

Invoke search event

Invoke the search event by using the Invoke Event endpoint. Page through the returned records to retrieve all of the found data, which will be mapped according to the fields defined in CRM Link

Here's an example request and response for invoking a search event for a CRM object with the slug opportunity and an event with the slug find_proposal_opportunities:

Request

POST /api/v1/crm/<connectionID>/objects/opportunity/events/find_proposal_opportunities HTTP/1.1
Host: app.xkit.co
Authorization: Basic <credentials>

{
  "payload": {
    "account_id": "45678"
  }
}

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "records": [
    {
      "type": "opportunity",
      "id": "Opportunity:09878",
      "data": {
        "document_name": "Oracle Sales Contract",
        "document_tags": {}
      }
    }
  ],
  "page": {
    "has_more": false
  }
}

Pagination

In case the search event has more records than the limit specified by the CRM, it will return a page object with pagination information.

The response will contain:

  • page: the object describing the paging for this event
    • has_more: boolean indicating whether there are more records
    • next: a URL to query to get the next page of results

Example response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "records": [
    {
      "type": "opportunity",
      "id": "Opportunity:09878",
      "data": {
        "document_name": "Oracle Sales Contract",
        "document_tags": []
      }
    }
  ],
  "page": {
    "has_more": true,
    "next": "YWJjMTIzeHlk"
  }
}

To follow the next page, take the next value from the JSON response and send it as next query parameter:

POST /api/v1/crm/<connectionID>/objects/opportunity/events/find_proposal_opportunities?next=YWJjMTIzeHlk HTTP/1.1
Host: app.xkit.co
Authorization: Basic MTIzOjQ1Ng==

{
  "payload": {
    "account_id": "45678"
  }
}

Get changes to CRM data

Xkit uses Webhooks to notify your application that data in the CRM relevant to your application has changed.

There are three types of webhooks:

  • Create: an object has been created in user's CRM
  • Update: a field in the CRM Object's mapping has changed
  • Delete: a CRM object has been deleted

To receive webhooks, you'll need to subscribe to them. There are 2 ways of subscribing to webhooks:

  • subscribing to webhooks for specific CRM Object
  • subscribing to webhooks for objects that match criteria for one of search events

Configure Webhook URL

In the developer portal, configure the URL Xkit should call to initiate a webhook and the API key we should include in the Authorization header.

Look for the Webhooks API Token and CRM Webhooks URL fields in the Application Settings section on the settings page.

Configure Webhook URL and token in the Xkit Developer Portal

Subscribe to Webhook for specific CRM record

Subscribe to a webhook by calling the Webhook Subscribe endpoint for the specific CRM record.

Example request:

POST /api/v1/crm/<connectionID>/objects/opportunity/Opportunity:09876/subscriptions HTTP/1.1
Host: app.xkit.co
Authorization: Basic <credentials>

This endpoint returns a 204 and contains no data.

Example response:

HTTP/1.1 204 No Content

To remove the subscription send a DELETE request to the same URL

Example request:

DELETE /api/v1/crm/<connectionID>/objects/opportunity/Opportunity:09876/subscriptions HTTP/1.1
Host: app.xkit.co
Authorization: Basic <credentials>

The response would again be a 204

Example response:

HTTP/1.1 204 No Content

Subscribe to Webhook for CRM records that match search event criteria

Subscribe to a webhook by calling the Webhook Subscribe endpoint for CRM records that match criteria of specific event

Example request:

POST /api/v1/crm/<connectionID>/objects/opportunity/events/find_proposal_opportunities/subscriptions HTTP/1.1
Host: app.xkit.co
Authorization: Basic <credentials>

{
  "payload": {
    "account_id": "555ABC"
  }
}

This endpoint returns a 204 and contains no data.

Example response:

HTTP/1.1 204 No Content

To remove the subscription send a DELETE request to the same URL and with the same payload

Example request

DELETE /api/v1/crm/<connectionID>/objects/opportunity/events/find_proposal_opportunities/subscriptions HTTP/1.1
Host: app.xkit.co
Authorization: Basic <credentials>

{
  "payload": {
    "account_id": "555ABC"
  }
}

Response is again a 204

Example response:

HTTP/1.1 204 No Content

Webhook Payload

Webhook payloads are JSON objects with the following structure:

  • event: the Webhook event object
    • type: A string which is create, update, or delete, corresponding to the type of event
    • record: the CRM record which has been affected
    • connection: identifies the connection the object belongs to
    • platform_context: identifies the platform context the object belongs to

Example Payload:

POST <webhook url> HTTP/1.1
Content-Type: application/json
Authorization: Bearer <api key>

{
  "event": {
    "type": "update",
    "record": {
      "type": "opportunity",
      "id": "Opportunity:09876",
      "data": {
        "document_name": "Apple Opportunity Sales Contract",
        "document_tags": {}
      }
    }
    "platform_context": {
      "id": "usr5c7e8c43"
    },
    "connection": {
      "id": "12345"
    }
  }
}

Up next

Universal CRM API - Writing data

Updating your users' CRMs with data from your application

Read more ▶

Ready to build your CRM app?

Integrate every CRM with one build, request access to get started.