HeadSpin Documentation
Documentation

Performance Monitoring API

The Performance Monitoring API can be used to programmatically work with User Flows. See Performance Monitoring UI for a high-level description of HeadSpin Performance Monitoring and User Flows.

In this document we cover the routes that read and modify User Flows.

API Routes

The Performance Monitoring API routes are as follows:

Route Method Description
/v0/userflows GET Retrieve a list of all user flows
/v0/userflows PUT Create a new user flow with optional description
/v0/userflows/{user_flow_id} GET Retrieve info about a specific user flow
/v0/userflows/{user_flow_id}/measurements GET Retrieve measurement data for a user flow
/v0/userflows/{user_flow_id}/sessions GET List sessions in user flow
/v0/userflows/{user_flow_id}/sessions POST Assign a session to a user flow
/v0/userflows/{user_flow_id}/sessions/{session_id} GET Get a session's info
/v0/userflows/{user_flow_id}/sessions/{session_id} PATCH Update session (change status, move user flow)
/v0/userflows/{user_flow_id}/sessions/{session_id} DELETE Remove session from user flow
/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements POST Add data to event via session
/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements GET Get measurement data for session
/v0/userflows/{user_flow_id}/events GET List events in user flow
/v0/userflows/{user_flow_id}/events POST Create a new event for this device on user flow
/v0/userflows/{user_flow_id}/events/{event_id} GET Get an event's info
/v0/userflows/{user_flow_id}/events/{event_id} PATCH Update event (change status, move user flow)
/v0/userflows/{user_flow_id}/events/{event_id} DELETE Remove event from user flow
/v0/userflows/{user_flow_id}/events/{event_id}/measurements POST Add data to event directly
/v0/userflows/{user_flow_id}/events/{event_id}/measurements GET Get measurement data for event

Performance Events and Sessions

Performance events tie sessions to user flows along with their measurements. A performance event can also exist in isolation without a session. If a session is removed from a user flow, the underlying performance event is deleted and all custom measurements will no longer be associated with that session. Session capture measurements will persist, however. If a performance event is removed from a user flow, those measurements will be lost.

Listing User Flows

Route Method
/v0/userflows GET

Response

  • 200: User flow list.
    • user_flows:
      • user_flow_id
      • name
      • description
      • created_time: UNIX timestamp in seconds.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows
# Output
{
  "user_flows": [
    {
      "user_flow_id": "35761d40-074f-4ab9-aa90-a879c4f68783",
      "name": "User Flow 1",
      "description": null,
      "created_time": 1651079365.238
    },
    {
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "name": "User Flow 2",
      "description": null,
      "created_time": 1648660507.108
    },
    ...
  ]
}

Getting a Single User Flow

Route Method
/v0/userflows/{user_flow_id} GET

Response

  • 200: User flow info.
    • user_flow_id
    • name
    • description
    • created_time: UNIX timestamp in seconds.
  • 404: User flow does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id} 
# Output
{
  "user_flow_id": "35761d40-074f-4ab9-aa90-a879c4f68783",
  "name": "User Flow 1",
  "description": null,
  "created_time": 1651079365.238
},

Creating a User Flow

Route Method
/v0/userflows PUT

Body


{
  "name": "..." // User flow name, required
  "description": "..." // Optional description
}

Response

  • 200: User flow created (or already exists).
    • user_flow_id
    • name
    • description: If user flow already exists, this will not be updated.
    • created_time: UNIX timestamp in seconds.
  • 400: Missing or invalid arguments.

Example


curl -X PUT -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows  \
     --data '{"name": "New User Flow", "description": "A new user flow for testing"}'
# Output
{
  "user_flow_id": "8da4f275-d09f-4151-9237-9743194b0843",
  "name": "New User Flow",
  "description": "A new user flow for testing",
  "created_time": 1653077875.205
}

Deleting a User Flow

Route Method
/v0/userflows/{user_flow_id} DELETE

Response

  • <code class="dcode">200</code>: User flow successfully deleted.
  • <code class="dcode">404</code>: User flow does not exist.

Example


curl -X DELETE -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id} 
# Output
{
  "status": "Success",
  "status_code": 200
},

Retrieving Measurement Data

Route Method
/v0/userflows/{user_flow_id}/measurements GET

Query Parameters

  • <code class="dcode">session_id={session_id}</code>: Select this session's measurements. <code class="dcode">session_id=</code> can be specified multiple times to filter on several sessions.
  • <code class="dcode">key={name}</code>: Select measurements with this key name. <code class="dcode">key=</code> can be specified multiple times to filter on several key names.
  • <code class="dcode">start_time={ISO|Unix timestamp}</code>: Inclusive lower bound for measurements' event time in either ISO formatted string or UNIX timestamp number.
  • <code class="dcode">end_time={ISO|Unix timestamp}</code>: Inclusive upper bound for measurements' event time in either ISO formatted string or UNIX timestamp number.
  • <code class="dcode">limit={num}</code>: Limit the number of measurements to <code class="dcode">num</code>.
  • <code class="dcode">offset={num}</code>: Start the selection at an offset by num, to be used with <code class="dcode">limit=</code>.
  • <code class="dcode">format={csv|json}</code>: Format of the response, either CSV or JSON. Default is JSON.
  • <code class="dcode">status={passed|failed|not_set|excluded}</code>: Filter measurements on the status of their sessions. Can be specified multiple times. If <code class="dcode">status</code> is omitted, then these statuses are implied: <code class="dcode">passed</code>, <code class="dcode">failed</code>, and <code class="dcode">not_set</code>.

All parameters can be combined.

Retrieving All Measurements for a User Flow


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements 
# Output
{
  "measurements": [
    {
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "user_flow_name": "first_test",
      "perf_event_id": "32584199-b06b-11ec-9907-06c4c57ba6cd",
      "event_time": "2022-03-30 16:48:22",
      "session_id": "bc744aef-b06a-11ec-9906-06c4c57ba6cd",
      "perf_key_id": "f37b98cb-b04c-11ec-ab81-027a65fb84e9",
      "key_name": "Content: Image",
      "key_type": "HeadSpin Session Metrics",
      "key_units": "bytes",
      "value": 56745
    },
    {
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "user_flow_name": "first_test",
      "perf_event_id": "7add22b7-691c-4257-9e9c-b472c90a1174",
      "event_time": "2022-04-19 12:31:47",
      "session_id": "348b3771-bffe-11ec-85db-06c4c57ba6cd",
      "perf_key_id": "f37b98cb-b04c-11ec-ab81-027a65fb84e9",
      "key_name": "Content: Image",
      "key_type": "HeadSpin Session Metrics",
      "key_units": "bytes",
      "value": 0
    },
    ...
  ]
}

Filtering By Session ID


curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements?session_id={session_id}" 

Filtering on Session Status


# Get measurements from only sessions that are PASSED
curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements?status=passed" 

# Get measurements from sessions that are either PASSED or UNSET
curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements?status=passed&status=not_set" 

Filtering by Measurement Name


# For key "All Issues Impact Time"
 curl --get -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_id}/measurements  \
     --data-urlencode "key=All Issues Impact Time"

Filtering on Event Time

<code class="dcode">start_time</code> and <code class="dcode">end_time</code> can be given as an ISO formatted datetime or UNIX timestamp.


# The following are equivalent for `start_time` 2022-03-30 16:48:22
curl --get -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements  \
     --data-urlencode "start_time=2022-03-30 16:48:22"

curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements?start_time=1648673302.0" 

Requesting CSV Format


curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements?format=csv" 
# Output
user_flow_id,user_flow_name,perf_event_id,event_time,session_id,perf_key_id,key_name,key_type,key_units,value
f24cbec7-b04c-11ec-97a0-06c4c57ba6cd,first_test,32584199-b06b-11ec-9907-06c4c57ba6cd,2022-03-30 16:48:22,bc744aef-b06a-11ec-9906-06c4c57ba6cd,f37b98cb-b04c-11ec-ab81-027a65fb84e9,Content: Image,HeadSpin Session Metrics,bytes,56745.0
f24cbec7-b04c-11ec-97a0-06c4c57ba6cd,first_test,7add22b7-691c-4257-9e9c-b472c90a1174,2022-04-19 12:31:47,348b3771-bffe-11ec-85db-06c4c57ba6cd,f37b98cb-b04c-11ec-ab81-027a65fb84e9,Content: Image,HeadSpin Session Metrics,bytes,0.0
f24cbec7-b04c-11ec-97a0-06c4c57ba6cd,first_test,f24cbec8-b04c-11ec-97a0-06c4c57ba6cd,2022-03-30 13:13:46,c1b5f76f-b04c-11ec-82b1-021b6b7c1650,f37b98cb-b04c-11ec-ab81-027a65fb84e9,Content: Image,HeadSpin Session Metrics,bytes,0.0
...

In the event of no measurements returned when requesting CSV, the response will be empty with a status of 204.

Paging Through Measurements

If a user flow has a large number of measurements, it may be useful to query the measurements in chunks specified by the <code class="dcode">limit=</code> and <code class="dcode">offset=</code> parameters. While no page info is returned, one can assume that if the result set is empty, no more results lie beyond it. The following Python snippet demonstrates requesting measurements 10 at a time until done.


import requests

url = "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/measurements"
headers = {"Authorization": "Bearer <your_api_token>"}
limit = 10
offset = 0
all_measurements = []
while True:
    params = {"limit": limit, "offset": offset}
    resp = requests.get(url, params=params, headers=headers)
    measurements = resp.json()["measurements"]
    if measurements:
        all_measurements.extend(measurements)
        offset += limit
    else:
        break

Note: If new sessions and measurements that match the query are added while paging through, the offset will be invalidated and results may be duplicated or missing.

Listing Sessions in a User Flow

Route Method
/v0/userflows/{user_flow_id}/sessions GET

Response

  • 200: List of user flow sessions.
    • sessions:
      • user_flow_id
      • perf_event_id
      • status
      • status_message
      • host
      • device_id
      • event_time: ISO format timestamp.
  • 404: User flow does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions 
# Output
{
  "sessions": [
    {
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "perf_event_id": "32584199-b06b-11ec-9907-06c4c57ba6cd",
      "session_id": "bc744aef-b06a-11ec-9906-06c4c57ba6cd",
      "status": "Passed",
      "status_message": null,
      "host": "proxy-us-mvo-5.headspin.io",
      "device_id": "289ad974",
      "event_time": "2022-03-30 16:48:22"
    },
    ...
  ]
}

Attaching a Session to a User Flow

Route Method
/v0/userflows/{user_flow_id}/sessions POST

Body


{
  "session_id": "..." // Session UUID ID, required
  "status": "..." // One of "Passed", "Failed", "Excluded", optional
  "status_message": "..." // Optional status message
}

Response

  • 200: Updated session info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 400:
    • Missing argument (session_id).
    • Invalid arguments (bad session_id).
    • Invalid status (Must be one of "Passed", "Failed", "Excluded").
    • Session already belongs to another user flow.
  • 404: Session or user flow does not exist.

Note: If a session gets attached to a user flow and its status is set to Passed, Failed, or Excluded, standard tags will be automatically added to the session. For more details on what these standard tags are, see Annotating Your Session: Session Tags.

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions  \
     --data '{"session_id": "{session_id}"}'
# Output
{
  "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
  "perf_event_id": "f527cb02-d8ce-471d-9660-689bff371b02",
  "session_id": "9f527e3f-daa1-11ec-ac12-06c4c57ba6cd",
  "status": "Not Set",
  "status_message": null,
  "host": "proxy-us-mvo-6.headspin.io",
  "device_id": "00008030-000559D902F0C02E",
  "event_time": "2022-05-23 10:07:04"
}

Getting a Single Session

Route Method
/v0/userflows/{user_flow_id}/sessions/{session_id} GET

Response

  • 200: Session info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 404: User flow or session does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id} 
# Output
{
  "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
  "perf_event_id": "f527cb02-d8ce-471d-9660-689bff371b02",
  "session_id": "9f527e3f-daa1-11ec-ac12-06c4c57ba6cd",
  "status": "Not Set",
  "status_message": null,
  "host": "proxy-us-mvo-6.headspin.io",
  "device_id": "00008030-000559D902F0C02E",
  "event_time": "2022-05-23 10:07:04"
}

Updating a Session's Status

Route Method
/v0/userflows/{user_flow_id}/sessions/{session_id} PATCH

Body


{
  "status": "Passed" // One of "Passed", "Failed", or "Excluded, required
  "status_message": "..." // Optional
}

Response

  • 200: Updated session info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 400:
    • Invalid arguments.
    • Invalid status.
  • 404: User flow or session does not exist.

Example


curl -X PATCH -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id} \
     --data '{"status": "passed", "status_message": "this session passed"}'
# Output
{
  "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
  "perf_event_id": "f527cb02-d8ce-471d-9660-689bff371b02",
  "session_id": "9f527e3f-daa1-11ec-ac12-06c4c57ba6cd",
  "status": "Passed",
  "status_message": "this session passed",
  "host": "proxy-us-mvo-6.headspin.io",
  "device_id": "00008030-000559D902F0C02E",
  "event_time": "2022-05-23 10:07:04"
}

Moving Session to Another User Flow

Route Method
/v0/userflows/{user_flow_id}/sessions/{session_id} PATCH

Body


{
  "user_flow_id": "..." // Target user flow ID
}

Response

  • 200: Updated session info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 400:
    • Invalid arguments.
    • Invalid status.
  • 404: User flow or session does not exist.

Example


curl -X PATCH -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id} \
     --data '{"user_flow_id": "f3fa9514-f2a8-42f3-b5aa-767846a29b54"}'
# Output
{
  "user_flow_id": "f3fa9514-f2a8-42f3-b5aa-767846a29b54",
  "perf_event_id": "f527cb02-d8ce-471d-9660-689bff371b02",
  "session_id": "9f527e3f-daa1-11ec-ac12-06c4c57ba6cd",
  "status": "Passed",
  "status_message": "this session passed",
  "host": "proxy-us-mvo-6.headspin.io",
  "device_id": "00008030-000559D902F0C02E",
  "event_time": "2022-05-23 10:07:04"
}

Removing Session from User Flow

Route Method
/v0/userflows/{user_flow_id}/sessions/{session_id} DELETE

Response

  • <code class="dcode">200</code>: Session removed.
  • <code class="dcode">404</code>: User flow or session does not exist.

Note: While this does not remove measurements generated through session capture, any custom measurements uploaded will be lost.

Example


curl -X DELETE -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id} 
# Output
{
    "status": "Success",
    "status_code": 200
}

Retrieving a Session's Measurements

Route Method
/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements GET

Query Parameters

  • <code class="dcode">key={name}</code>: Select measurements with this key name. <code class="dcode">key=</code> can be specified multiple times to filter on several key names.
  • <code class="dcode">limit={num}</code>: Limit the number of measurements to <code class="dcode">num</code>.
  • <code class="dcode">offset={num}</code>: Start the selection at an offset by num, to be used with <code class="dcode">limit=</code>.
  • <code class="dcode">format={csv|json}</code>: Format of the response, either CSV or JSON. Default is JSON.

Response

  • 200: Measurement data.
    • measurements:
      • user_flow_id
      • user_flow_name
      • event_time: ISO format timestamp.
      • session_id
      • key_name
      • key_type
      • key_units
      • value: Float or string value if non-numeric.
  • 404: User flow or session does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements 
# Output
{
  "measurements": [
    {
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "user_flow_name": "My User Flow",
      "perf_event_id": "9f6bdf58-514e-43e2-a354-0e8f1f4a977a",
      "event_time": "2022-04-28 13:27:55",
      "session_id": "8a37be67-c718-11ec-896d-0acbaa89a1b3",
      "perf_key_id": "11552253-ecec-4caf-b0b6-837e07b6c9a0",
      "key_name": "Idle Time",
      "key_type": "Custom Metrics",
      "key_units": "seconds",
      "value": 100.0
    },
    ...
  ]
}

Note: If new measurements for this session are added while paging through, the offset will be invalidated and results may be duplicated or missing.

Listing Performance Events

Route Method
/v0/userflows/{user_flow_id}/events GET

Response

  • 200: List of user flow events.
    • events:
      • user_flow_id
      • perf_event_id
      • status
      • status_message
      • host
      • device_id
      • event_time: ISO format timestamp.
  • 404: User flow does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events 
# Output
{
  "events": [
    {
      "status": "Passed",
      "host": "{hostname}",
      "event_time": "2022-05-25 09:33:17",
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "perf_event_id": "2d5eafc6-9bb3-4488-a91d-3f6b660728d8",
      "status_message": null,
      "session_id": null,
      "device_id": "{ios-device-id}"
    },
    ...
  ]
}

Creating a New Performance Event

Route Method
/v0/userflows/{user_flow_id}/events POST

Body


{
  "device_address": "{ios-device-id}@{hostname}" // Device address, required
}

Response

  • 200: Performance event info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 400:
    • Missing or invalid device_address.
  • 404: User flow does not exist.

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events  \
     --data '{"device_address": "{ios-device-id}@{hostname}"}'
# Or equivalently,
curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events  \
     --data '{"device_id": "{ios-device-id}", "hostname": "{hostname}"}'
# Output
{
  "status": "Not Set",
  "host": "{hostname}",
  "event_time": "2022-05-25 09:46:41",
  "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
  "perf_event_id": "6234be65-4ded-43ee-8595-ac983ce37d41",
  "status_message": null,
  "session_id": null,
  "device_id": "{ios-device-id}"
}

Getting a Single Performance Event

Route Method
/v0/userflows/{user_flow_id}/events/{event_id} GET

Response

  • 200: Performance event info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 404: User flow or event does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events/{event_id} 
# Output
{
  "status": "Passed",
  "host": "{hostname}",
  "event_time": "2022-05-25 09:33:17",
  "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
  "perf_event_id": "2d5eafc6-9bb3-4488-a91d-3f6b660728d8",
  "status_message": null,
  "session_id": null,
  "device_id": "{ios-device-id}"
}

Updating a Performance Event's Status

Route Method
/v0/userflows/{user_flow_id}/events/{event_id} PATCH

Body


{
  "status": "Passed" // One of "Passed", "Failed", or "Excluded, required
  "status_message": "..." // Optional
}

Response

  • 200: Updated event info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 400:
    • Invalid arguments.
    • Invalid status.
  • 404: User flow or event does not exist.

Example


curl -X PATCH -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events/{event_id}  \
     --data '{"status": "passed", "status_message": "this session passed"}'
# Output
{
  "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
  "perf_event_id": "f527cb02-d8ce-471d-9660-689bff371b02",
  "session_id": "9f527e3f-daa1-11ec-ac12-06c4c57ba6cd",
  "status": "Passed",
  "status_message": "this session passed",
  "host": "proxy-us-mvo-6.headspin.io",
  "device_id": "00008030-000559D902F0C02E",
  "event_time": "2022-05-23 10:07:04"
}

Moving Performance Event to Another User Flow

Route Method
/v0/userflows/{user_flow_id}/events/{event_id} PATCH

Body


{
  "user_flow_id": "..." // Target user flow ID
}

Response

  • 200: Updated session info.
    • user_flow_id
    • perf_event_id
    • status
    • status_message
    • host
    • device_id
    • event_time: ISO format timestamp.
  • 400:
    • Invalid arguments.
    • Invalid status.
  • 404: User flow or session does not exist.

Example


curl -X PATCH -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events/{event_id}  \
     --data '{"user_flow_id": "f3fa9514-f2a8-42f3-b5aa-767846a29b54"}'
# Output
{
  "user_flow_id": "f3fa9514-f2a8-42f3-b5aa-767846a29b54",
  "perf_event_id": "f527cb02-d8ce-471d-9660-689bff371b02",
  "session_id": "9f527e3f-daa1-11ec-ac12-06c4c57ba6cd",
  "status": "Passed",
  "status_message": "this session passed",
  "host": "proxy-us-mvo-6.headspin.io",
  "device_id": "00008030-000559D902F0C02E",
  "event_time": "2022-05-23 10:07:04"
}

Removing Performance Event from User Flow

Route Method
/v0/userflows/{user_flow_id}/events/{event_id} DELETE

Response

  • <code class="dcode">200</code>: Performance event deleted.
  • <code class="dcode">404</code>: User flow or session does not exist.

Note: While this does not remove measurements generated through session capture, any custom measurements uploaded will be lost. If the event has no session associated, all measurement data will be lost.

Example


curl -X DELETE -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/events/{event_id} 
# Output
{
    "status": "Success",
    "status_code": 200
}

Retrieving a Performance Event's Measurements

Route Method
/v0/userflows/{user_flow_id}/events/{event_id}/measurements GET

Query Parameters

  • <code class="dcode">key={name}</code>: Select measurements with this key name. <code class="dcode">key=</code> can be specified multiple times to filter on several key names.
  • <code class="dcoe">limit={num}</code>: Limit the number of measurements to <code class="dcode">num</code>.
  • <code class="dcode">offset={num}</code>: Start the selection at an offset by <code class="dcode">num</code>, to be used with <code class="dcode">limit=</code>.
  • <code class="dcode">format={csv|json}</code>: Format of the response, either CSV or JSON. Default is JSON.

Response

  • 200: Measurement data.
    • measurements:
      • user_flow_id
      • user_flow_name
      • event_time: ISO format timestamp.
      • session_id
      • key_name
      • key_type
      • key_units
      • value: Float or string value if non-numeric.
  • 404: User flow or event does not exist.

Example


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements 
# Output
{
  "measurements": [
    {
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "user_flow_name": "My User Flow",
      "perf_event_id": "9f6bdf58-514e-43e2-a354-0e8f1f4a977a",
      "event_time": "2022-04-28 13:27:55",
      "session_id": "8a37be67-c718-11ec-896d-0acbaa89a1b3",
      "perf_key_id": "11552253-ecec-4caf-b0b6-837e07b6c9a0",
      "key_name": "Idle Time",
      "key_type": "Custom Metrics",
      "key_units": "seconds",
      "value": 100.0
    },
    ...
  ]
}

Note: If new measurements for this event are added while paging through, the offset will be invalidated and results may be duplicated or missing.

Custom Measurement Data

The expected measurement POST payload for routes <code class="dcode">/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements</code> and <code class="dcode">/v0/userflows/{user_flow_id}/events/{event_id}/measurements</code> is:


{
  "data": [              // Measurement data
    {
      "key":   "...",    // Measurement name
      "value": "...",    // Measurement value
      "type":  "...",    // Measurement type/category; Optional
      "units": "..."     // Measurement units; Optional
    },
    ...
  ]
}

The <code class="dcode">data</code> field contains a list of measurements to be added to a session. A measurement is a key/value pair with additional metadata fields <code class="dcode">type</code> and <code class="dcode">units</code>. The type is effectively a category name that can be used to group measurements into categories.

For example, in the Performance Monitoring UI, the measurements dropdown groups measurements by type. In the following screenshot, "HeadSpin Session Metrics" is the <code class="dcode">type</code>, "Average Wait" is the <code class="dcode">key</code>, and "milliseconds" is the <code class="dcode">units</code>:

HeadSpin session metrics

The <code class="dcode">units</code> field is pure metadata and is not used in analysis.

The <code class="dcode">value</code> field does not have to be numeric. Non-numeric measurements will be ignored by the Performance Monitoring UI when rendering timeseries.

Uploading Custom Session Measurements

Route Method
/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements POST

Body


{
  "data": [
    "key": "Idle Time",
    "value": 3992.0,
    "type": "Custom Metrics" // Optional measurement type
    "units": "seconds" // Optional measurement units
  ],
  ...
}

Response

  • <code class="dcode">200</code>: Measurements uploaded successfully.
  • <code class="dcode">400</code>: Invalid or missing measurement data.
  • <code class="dcode">404</code>: User flow or session does not exist.

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements  \
     --data '{"data": [{"key": "Idle Time", "value": 3992.0}, {"key": "Load Time", "value": 3421.2}]}'
# Output
{
  "status": "Sucesss",
  "status_code": 200
}

Uploading Custom Performance Event Measurements

Route Method
/v0/userflows/{user_flow_id}/events/{event_id}/measurements POST

Body


{
  "data": [
    "key": "Idle Time",
    "value": 3992.0,
    "type": "..." // Optional
    "units": "..." // Optional
  ],
  ...
}

Response

  • <code class="dcode">200</code>: Measurements uploaded successfully.
  • <code class="dcode">400</code>: Invalid or missing measurement data.
  • <code class="dcode">404</code>: User flow or event does not exist.

Example


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/sessions/{session_id}/measurements  \
     --data '{"data": [{"key": "Idle Time", "value": 3992.0}, {"key": "Load Time", "value": 3421.2}]}'
# Output
{
  "status": "Sucesss",
  "status_code": 200
}

Legacy API Routes

Note: The HeadSpin <code class="dcode">v0</code> API refers to User Flows as <code class="dcode">perftests</code>. In some instances the field <code class="dcode">test_name</code> is used to refer to a User Flow name and <code class="dcode">perf_test_id</code> to refer to the User Flow ID. This discrepancy will be corrected in a future update to the API.

The Performance Monitoring API routes are as follows:

Route Method Description
/v0/perftests GET Retrieve a list of all user flows
/v0/perftests/{user_flow_id} GET Retrieve info about a specific user flow
/v0/perftests/upload POST Upload or update measurement data to a user flow

Listing User Flows (Legacy)


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/perftests 
# Output:
{
  "perf_tests": [
    {
      "created_time": 1538172182.261,
      "perf_test_id": "44a82e55-c36a-11e8-a1a8-00e04c6858ee",
      "description": null,
      "name": "My User Flow"
    },
    {
      "created_time": 1548213723.6,
      "perf_test_id": "0dce9ae5-1ebe-11e9-afbe-06af87227a14",
      "description": "A Description",
      "name": "Another User Flow"
    },
    ...
  ]
}

The <code class="dcode">created_time</code> is the time of creation of the User Flow as a unix epoch timestamp in seconds. The <code class="dcode">perf_test_id</code> is the ID of the User Flow, which corresponds to the ID in the UI URL bar when the User Flow is opened. For example if the URL bar is <code class="dcode">https://ui-dev.headspin.io/performance/userflows/44a82e55-c36a-11e8-a1a8-00e04c6858ee the perf_test_id is 44a82e55-c36a-11e8-a1a8-00e04c6858ee</code>.

Reading a Single User Flow (Legacy)

Append the User Flow ID to the above route to narrow in on a single User Flow:


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/perftests/44a82e55-c36a-11e8-a1a8-00e04c6858ee 
# Output
{
  "created_time": 1538172182.261,
  "perf_test_id": "44a82e55-c36a-11e8-a1a8-00e04c6858ee",
  "description": null,
  "name": "My User Flow"
}

Creating and Updating User Flow Data (Legacy)

<code class="dcode">/v0/perftests/upload</code> is a powerful route which can be used to achieve the following:

  • Create a new user flow
  • Attach a session to a user flow
  • Change the status of a session in a user flow
  • Upload new measurements to a session in a user flow
  • Modify existing measurements to a session in a user flow

Subsets of these actions can be performed simulatenously in a single HTTP request.

The POST payload to this route is as follows:


{
  "test_name":   "...",  // User Flow name
  "session_id":  "...",  // Session ID
  "status":      "...",  // One of: "passed", "failed", "excluded"
  "data": [              // Measurement data
    {
      "key":   "...",    // Measurement name
      "value": "...",    // Measurement value
      "type":  "...",    // Measurement type/category; Optional
      "units": "..."     // Measurement units; Optional
    },
    ...
  ]
}

The <code class="dcode">data</code> field contains a list of measurements to be added to a session. A measurement is a key/value pair with additional metadata fields <code class="dcode">type</code> and <code class="dcode">units</code>. The type is effectively a category name that can be used to group measurements into categories.

For example, in the Performance Monitoring UI, the measurements dropdown groups measurements by type. In the following screenshot, "HeadSpin Session Metrics" is the <code class="dcode">type</code>, "Average Wait" is the <code class="dcode">key</code>, and "milliseconds" is the <code class="dcode">units</code>:

replica db category

The <code class="dcode">units</code> field is pure metadata and is not used in analysis.

The <code class="dcode">value</code> field does not have to be numeric. Non-numeric measurements will be ignored by the Performance Monitoring UI when rendering timeseries.

Attaching a session to a user flow (Legacy)

To attach a session to user flow, we pass the user flow name in <code class="dcode">test_name</code> and the the session's <code class="dcode">session_id</code>:


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/perftests/upload  \
     -d '{"test_name": "My User Flow", "session_id": "7ef6c7ba-6c6d-11e9-be69-a45e60be08cf"}'

Important Note: If the user flow with the given name does not exist, a new user flow with this name will be created, and the session will be attached to it.

Updating the status of a session (Legacy)

To update the status of a session that is already attached to a user flow, we pass the <code class="dcode">session_id</code> and <code class="dcode">status</code>


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/perftests/upload  \
     -d '{"session_id": "7ef6c7ba-6c6d-11e9-be69-a45e60be08cf", "status" :"passed"}'

Adding custom measurements (Legacy)

To add a custom measurement named "My Measurement" with value <code class="dcode">50</code>, we invoke the API as follows:


curl -X POST -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/perftests/upload  \
     -d '{"session_id": "7ef6c7ba-6c6d-11e9-be69-a45e60be08cf", "data": [{"key": "My Measurement", "value": 50}]}'

Notes:

  • Many measurements can be added at the same time, by appending to the <code class="dcode">data</code> list.
  • The <code class="dcode">type</code> and <code class="dcode">units</code> fields can be optionally passed for each measurement.
  • If a measurement with that name and type already exists, its value will be overwritten with the new value.

Simultaneous updates (Legacy)

The above three update modes (Attaching a session to a user flow, Updating the status on a session, Adding custom measurements) can be performed simulanously, by passing all the fields: <code class="dcode">test_name</code>, <code class="dcode">session_id</code>, <code class="dcode">status</code>, and <code class="dcode">data</code>.

Retrieving KPI Measurements (Verizon)

This route is intended to serve KPI values that are stored as measurements. A single KPI is comprised of three measurements that specify <code class="dcode">time_to_interactive</code>, <code class="dcode">availability</code>, and <code class="dcode">ttfb</code> (time to first byte). For a measurement to appear as part of a KPI, given a key name <code class="dcode">$KEY</code>, there should be measurement with key name <code class="dcode">$KEY_ttfb</code> in the user flow.

Route Method
/v0/userflows/{user_flow_id}/verizon GET

Query Parameters

  • <code class="dcode">session_id={session_id}</code>: Select this session's measurements. <code class="dcode">session_id=</code> can be specified multiple times to filter on several sessions.
  • <code class="dcode">kpi={name}</code>: Select KPIs with this name. <code class="dcode">kpi=</code> can be specified multiple times to filter on several kpis.
  • <code class="dcode">start_time={ISO|Unix timestamp}</code>: Inclusive lower bound for measurements' event time in either ISO formatted string or UNIX timestamp number.
  • <code class="dcode">end_time={ISO|Unix timestamp}</code>: Inclusive upper bound for measurements' event time in either ISO formatted string or UNIX timestamp number.
  • <code class="dcode">format={csv|json}</code>: Format of the response, either CSV or JSON. Default is JSON.
  • <code class="dcode">status={passed|failed|not_set|excluded}</code>: Filter measurements on the status of their sessions. Can be specified multiple times. If <code class="dcode">status</code? is omitted, then these statuses are implied: <code class="dcode">passed</code>, <code class="dcode">failed</code>, and <code class="dcode">not_set</code>.

All parameters can be combined.

Retrieving KPI Data for a User Flow


curl -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon 
# Output
{
  "measurements": [
    {
      "session_id": "8a37be67-c718-11ec-896d-0acbaa89a1b3",
      "user_flow_id": "f24cbec7-b04c-11ec-97a0-06c4c57ba6cd",
      "user_flow_name": "iOS_AAL",
      "session_start_time": "2022-04-28 13:27:55",
      "location": "Mountain View - US",
      "kpi": "Sign In",
      "amID": "072f7c50-2785-4c60-8833-359c5cfbc24a",
      "e2erequestid": "b02b5205-b86c-49d8-bc8e-f37fc32e9e9d-7089536",
      "digital_ig_session": "POW-M-e42a58c2-6b8e-4a2d-ad1e-67759700ca48",
      "ttfb": 200,
      "time_to_interactive": 3816,
      "availability": 100
    },
    ...
  ]
}

Requesting CSV Format


curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon?format=csv" 
# Output
session_id,user_flow_id,user_flow_name,session_start_time,location,kpi,time_to_interactive,availability,ttfb,amID,e2erequestid,digital_ig_session
dece402e-eb9d-11ec-a563-acde48001122,33d76193-77a6-11eb-b372-021b6b7c1650,Another Test User Flow,2022-06-03 11:11:22,Mountain View - US,Verizon Test Key,8999.0,9001.0,9000.0,072f7c50-2785-4c60-8833-359c5cfbc24a,b02b5205-b86c-49d8-bc8e-f37fc32e9e9d-7089536,POW-M-e42a58c2-6b8e-4a2d-ad1e-67759700ca48
...

Filtering on Session Time

To retrieve KPI data for a specific time frame, use the <code class="dcode">start_time=</code> and <code class="dcode">end_time=</code> query parameters. These values can be specified as an ISO format string or UNIX timestamp. All times should be in UTC.


# From 2022-05-04 14:15:00 to 2022-05-04 15:15:00
curl --get -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon  \
     --data-urlencode "format=csv" \
     --data-urlencode "start_time=2022-05-04 14:15:00" \
     --data-urlencode "end_time=2022-05-04 15:15:00"

Filtering By Session ID


curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon?session_id={session_id}" 

Filtering on Session Status


# Get measurements from only sessions that are PASSED
curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon?status=passed" 

# Get measurements from sessions that are either PASSED or UNSET
curl -H "Authorization: Bearer <your_api_token>" "https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon?status=passed&status=not_set" 

Filtering on KPIs

To filter on KPIs by name (case-sensitive), use the <code class="dcode">kpi=</code> query parameter. Multiple <code class="dcode">kpi=</code> values can be appended to the same request.


# To filter on "Sign In" KPIs in the user flow
curl --get -H "Authorization: Bearer <your_api_token>" https://api-dev.headspin.io/v0/userflows/{user_flow_id}/verizon  \
     --data-urlencode "format=csv" \
     --data-urlencode "kpi=Sign In"
# Output
session_id,user_flow_id,user_flow_name,session_start_time,location,kpi,time_to_interactive,availability,ttfb
520f225e-cd62-11ec-a6c8-f01898f3a82f,573be968-b41e-11ec-921c-0acef5dbfa51,iOS_AAL,2022-05-06 13:31:11,Palo Alto - US,Sign In,1150.0,100.0,117.0
eef81b5e-cd54-11ec-9a48-f01898f3a82f,573be968-b41e-11ec-921c-0acef5dbfa51,iOS_AAL,2022-05-06 11:55:21,Palo Alto - US,Sign In,4167.0,100.0,200.0
898f87dc-cd53-11ec-aec1-f01898f3a82f,573be968-b41e-11ec-921c-0acef5dbfa51,iOS_AAL,2022-05-06 11:45:22,Palo Alto - US,Sign In,4083.0,100.0,200.0
...

When New KPIs Are Added

This endpoint is designed around the convention of given a KPI like "Shop", there will be three measurements with keys <code class="dcode">Shop</code>, <code class="dcode">Shop_Availability</code>, and <code class="dcode">Shop_ttfb</code>. Therefore, if a new KPI is added, for it to resolve correctly it should conform to this.