Contents
Walkthroughs
Happy path
A prospective student fills in a lead generation form within the FutureLearn application (either on a degree page, a program page or a student recruitment step within an open pathway course).
FutureLearn assigns a UUID to the submission and stores the submitted details in the FutureLearn database.
FutureLearn notifies the university of the incoming lead by making a simple HTTP call to an endpoint chosen by the university. The payload of the call is a JSON object containing the student recruitment lead UUID and the URL of the endpoint that can be used to retrieve the lead details.
The receiving server at the university uses the signature header to check that the notification is genuine. Assuming that it is, the receiver server places the notification in a queue for further processing and responds with an HTTP success code (typically 202 Accepted).
Request X-FL-Signature: K8EqxaOr8El7GjLp57yv8xaLf6aiFtSCc+jC4tATOtQ=
|
Response HTTP/1.1 202 Accepted |
On receiving the success response, FutureLearn sets the ‘notified at’ timestamp on the lead. No further attempt is made to notify the university of the lead through the webhook.
When the university is ready to process the request, the processing system uses the URL provided in the webhook payload to retrieve the details of the lead from the FutureLearn partners API.
FutureLearn responds with the details of the lead and sets the ‘transferred at’ timestamp on the lead.
Request GET https://api.futurelearn.com/partners/student_leads/e243ef6e-59d6-418b-a78f-cbe129975364 |
Response
HTTP/1.1 200 OK "first_name": "Susannah", "phone": "+44 1234 567890", "country": "United Kingdom", "status": "Full-time employment", "highest_education_level": "Undergraduate degree", "source_type": "degree_discipline", "degree_discipline": { "uuid": "5b78be83-3ecb-4fc9-8974-6a47fa405692", }, "interested_in_degree": true, "interested_in_organisation": false, "created_at": "2017-08-17T17:01:23Z", |
The university imports the relevant details from the response to its own marketing or lead management system (e.g. Marketo).
Verifying the authenticity of notifications
Before the receiving system follows the HREF in an incoming notification, it needs to check that the notification originated from FutureLearn and hasn’t been tampered with.
To do this, the receiving system calculates the base64-encoded SHA-256 HMAC digest of the request body (using the webhook’s shared secret as the HMAC key) and compares it against the signature provided in the X-FL-Signature request header.
If the two signatures match, the notification originated from FutureLearn (or at least from a party with access to the shared secret) and should be processed as normal.
If the two signatures do not match, then the notification may not be genuine. The receiving system should response with an HTTP client error code (e.g. 400 Bad Request) and discard the notification.
The following is an example of how this check may be implemented in a Ruby application:
def check_request_signature # Calculate the expected signature calculated_hmac = OpenSSL::HMAC.digest( 'sha256', 'replace-with-shared-secret', request.raw_post) expected_signature = Base64.strict_encode64(calculated_hmac) # Get the actual signature from the request headers actual_signature = request.headers['X-FL-Signature'] # Check that the two signatures match expected_signature, actual_signature) # Respond with 400 Bad Request response head :bad_request end |
Unhappy path
If FutureLearn gets an HTTP error response (or no response at all) from the webhook endpoint, the ‘notified at’ timestamp is not set and the webhook will be reattempted until it succeeds (with exponential backing-off).
Fields
Name |
Description |
Present |
uuid |
The UUID of the lead | Always |
href
|
The URL for getting the details of the lead |
Always |
first_name |
The first name of the prospective student | Always |
last_name |
The last name of the prospective student | Always |
|
The email address of the prospective student | Always ☨ |
phone |
The phone number of the prospective student | If provided |
country |
The country where the prospective student currently lives | Always ☨ |
status |
The current employment/student status of the prospective student | Always ☨ |
year_of_birth |
The prospective student’s year of birth | If provided (currently available for leads from courses only) |
highest_education_level |
The prospective student’s current highest education level | Always ☨ |
source_type |
The type of page that generated the lead. Currently one of ‘degree_discipline’, ‘program’ or ‘course’ | Always |
degree_discipline |
The UUID, partners API HREF, and partner issued code for the degree discipline. | When source type is ‘degree_discipline’ |
program |
The UUID, partners API HREF, and partner issued code for the program. | When source type is ‘program’ |
course |
The UUID, partners API HREF, and partner issued code for the course. | When source type is ‘course’. |
interested_in_organisation |
Whether the student selected the ‘find out more about {university}’ option | When source type is ‘program’ or ‘degree_disclipline’ |
interested_in_degree |
Whether the student selected the ‘find out more about {degree-discipline} degrees’ option | When source type is ‘program’ or ‘degree_disclipline’ |
interested_in_program |
Whether the student selected the ‘find out more about {program}’ option | When source type is ‘program’ |
Forwards compatibility
Fields may be added over time. Fields marked ☨ that are currently populated for all leads but may become optional in future. Consumers should therefore be written to gracefully handle situations where any those fields are blank.
Security
- Communication in both directions (pull APIs and webhooks) is always performed over HTTPS/SSL to ensure that the data transmitted cannot be read by third parties.
- ‘Pull’ API calls (university to FutureLearn) are authenticated using JWT bearer tokens so that FutureLearn can identify which partner system they originate from.
- Webhook calls (FutureLearn to university) are not authenticated, so the receiving endpoint must assume that any request it receives could have originated from an untrusted party.
- Webhook calls must never convey confidential data. Instead they should include an identifier or URL that the consumer can use to retrieve the data through an authenticated ‘pull’ API call. This is to protect against the risk of accidentally leaking confidential data to a third party in the event of a webhook being incorrectly configured.
Comments
0 comments
Please sign in to leave a comment.