As of the 12.4 release, Event Subscriptions are editable through LearningBuilder for LearningBuilder Subscribers.

Overview

RESTful APIs for establishing subscriptions between Programs.

Subscribers must “subscribe” to a Program in order to pull its data from the Hub. The Publisher’s data are not publicly accessible to prevent it from being scraped, and to give Publishers controls over their data.

API Hostnames

See https://heuristicsolutions.atlassian.net/wiki/spaces/DOCS/pages/3697770890/Learning+Hub#API-Hostnames

Authentication

See https://heuristicsolutions.atlassian.net/wiki/spaces/DOCS/pages/3697770890/Learning+Hub#Authentication

Unless otherwise specified, all endpoints on this page require an API Key with SYSTEM permissions.

Data model

SUBSCRIPTION

note

A Subscription is a relationship from a Subscriber to a Publisher that allows the Subscriber to receive the Publisher’s data.

A Subscription is a relationship from a Subscriber to a Publisher that allows the Subscriber to receive the Publisher’s data.

Field

Type

Notes

ProgramId

string (25 char)

The identifier of the Subscriber

PublisherProgramId

string (25 char)

The identifier of the Publisher

LastSyncUtc

UTC date/time

UTC timestamp of the last time the Subscriber pulled data from this Publisher

SyncEnabled

boolean

Whether or not the subscription supports the nightly sync process. (Applies to LearningBuilder Subscribers only)

Setting this to TRUE does not automatically enable the nightly sync, it just allows the nightly sync to process this subscription.

LbApiPayloadTemplate

JSON

JSON structure mapping different PublisherEventCategory values to the Handlebars template that converts those Events into a batch row payload for LearningBuilder’s WorkflowImportQueue/CreateBatch API.

See below for detailed explanation

LbApiPayloadTemplate syntax and purpose

note

This section applies specifically to Subscribers using LearningBuilder. Other systems will need to implement their own mechanism for processing data from the Hub.

This section applies specifically to Subscribers using LearningBuilder. Other systems will need to implement their own mechanism for processing data from the Hub.

Publishers and Subscribers think about and model their data differently, so the Publisher’s data typically needs modified or converted before it can be imported into LearningBuilder.

Each Event Subscription specifies:

Those templates are stored as the batchRowTemplate property in the LbApiPayloadTemplatef an EventSubsription:

"LbApiPayloadTemplate": {
  "{EventCategory1}": {
    "action": "import (default) | ignore",
    "label": "human readable note",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  }, 

  // ... additional category mappings as needed ...

  "_default": {
    "action": "import (default) | ignore",
    "label": "human readable note",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  }
}

Each key within the LbApiPayloadTemplate should match one of the Publisher’s PublisherEventCategory values, or the special marker _defaultwhich indicates a default template.

There are two reasons to include a PublisherEventCategory mapping:

Syntax examples

Example / scenario

Sample LbApiPayloadTemplate

Subscribe to all Publisher event categories, using the same template for everything

"LbApiPayloadTemplate": {
  "_default": {
    "action": "import",
    "label": "Import everything",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  }
}

Subscribe to all Publisher event data, with special handling for a specific category

"LbApiPayloadTemplate": {
  "some_key": {
    "action": "import",
    "label": "ACME Course",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  },
  "_default": {
    "action": "import",
    "label": "Import everything",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  }
}

Subscribe to a specific category only, ignoring everything else

"LbApiPayloadTemplate": {
  "COURSE": {
    "action": "import",
    "label": "ACME course",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  },
  "_default": {
    "action": "ignore",
    "label": "Nothing else matters"
  }
}

Ignore a specific category, process everything else using a common template

"LbApiPayloadTemplate": {
  "SOME_CATEGORY": {
    "action": "ignore",
    "label": "ACME course"
  },
  "_default": {
    "action": "import",
    "importProcessId": {WIQ Process Id},
    "batchRowTemplate": "{handlebars template}"
  }
}
note

Omitting the _default mapping has the same result as setting it to "action": "ignore", but it is recommended to explicitly include the default mapping to make the configuration easier to understand.

Omitting the _default mapping has the same result as setting it to "action": "ignore", but it is recommended to explicitly include the default mapping to make the configuration easier to understand.

Detailed data flow

It works like this:

image-20240911-171330.png

Event Subscriptions

“Event Subscriptions” track which Programs will receive the Events published by other Programs.

GET /api/programs/{programId}/eventSubs

Returns a list of Event Subscriptions for the specified Program.

Responses

Response Code

Headers and Body

200 (Ok)

[
  { 
    "ProgramId": "subscriber_program_id", 
    "PublisherProgramId": "publisher_program_id", 
    "CreatedUtc": "UTC date/time",
    "LastSyncUtc": "UTC date/time",
    "SynEnabled": true,
    "LbApiPayloadTemplate": {
      "SOME_CATEGORY": {
        "action": "import",
        "label": "ACME Course",
        "importProcessId": {WIQ Process Id},
        "batchRowTemplate": "{handlebars template}"
      }
    }    
  },
  ...
]

GET /api/programs/{programId}/eventSubs/{publisherProgramId}

Returns the details about {programId}'s subscription to {publisherProgramId}'s Events.

Responses

Response Code

Headers and Body

200 (Ok)

{ 
  "ProgramId": "foo", 
  "PublisherProgramId": "bar", 
  "CreatedUtc": "UTC date/time",
  "LastSyncUtc": "UTC date/time",
  "SynEnabled": true,
  "LbApiPayloadTemplate": { see docs above }  
}

POST /api/programs/{programId}/eventSubs

Creates a new Event Subscription. Returns an error if it already exists.

Audit fields such as CreatedUtc are assigned during creation.

JSON Payload

{
  "PublisherProgramId": "PublisherProgramId",
  "SyncEnabled": true,
  "LbApiPayloadTemplate": {
    "SOME_CATEGORY": {
      "action": "import",
      "label": "ACME Course",
      "importProcessId": {WIQ Process Id},
      "batchRowTemplate": "{handlebars template}"
    }
  }    
}

Responses

Response Code

Headers and Body

201 (Created)

A new Event Subscription was created. No body is returned.

HTTP headers:

Location: /API/programs/{programId}/eventSubs/{pubProgId}


PATCH /api/programs/{programId}/eventSubs/{publisherProgramId}

Updates an existing Event Subscription.

JSON Payload

{
    "LastSyncUtc": "date",
    "SyncEnabled": true,
    "LbApiPayloadTemplate": { see docs above }  
}

Responses

Response Code

Headers and Body

204 (No Content)

Update was performed successfully. No body is returned.


DELETE /api/programs/{programId}/eventSubs/{publisherProgramId}

Deletes an existing Event Subscription.

Responses

Response Code

Headers and Body

204 (No Content)

Delete was performed successfully. No body is returned.