Domain Change
In Nov 2021 we changed our name from envisage to MetaPulse. The new domain is metapulse.com. Although the API will work on both metapulse.com and envisage.io, the latter is deprecated, therefore we recommend upgrading all API calls to metapulse.com
MetaPulse has a simple API that is available for your use, any feedback is welcome.
This document represents version 4 of the API. You can find all versions listed in our help article: See all API Versions
You can use the API to programmatically list, read, create, update and destroy data points against your graphs and members. For rate limits see MetaPulse API Usage Limits.
Sections:
Setup
_______________________________________
To begin, you will need the email you use to sign into MetaPulse along with the API key from your MetaPulse User Profile page.
If you will be doing a lot of API calls, it is best practice to create an API user in MetaPulse and give this user profile the permissions needed to access the necessary graphs.
While you can use your own email and API key, a dedicated API user account is recommended.
Testing Authentication
_______________________________________
The first test you should do is make sure you can authenticate with the server. MetaPulse uses header based authentication, so you need to set two headers in your request: API-EMAIL and API-KEY . The email is your user email, the API key is from your profile page.
You can check authentication is working by doing the following command using the curl system utility:
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
https://metapulse.com/api/v4/authentication
Which should give you a 200 OK with an empty body looking something like:
HTTP/2 200
date: Mon, 07 Jan 2019 02:35:35 GMT
content-type: text/html
...
This 200 OK means you have successfully connected to the server.
Using the Data Point API
_______________________________________
Available Data Point API actions:
Note all following date formats are YYYY-MM-DD
You can find the Graph ID (token) on the graphs page under the Graph Info menu option.
List All Data Points
The following lists all data points for a single graph. Values are returned in order of oldest to most recent.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
https://metapulse.com/api/v4/data_points?graph_id=<GRAPH_TOKEN>
So for example, if your API_EMAIL was user@example.com and your API_KEY was sdlexamplekfj and you wanted the data points for a weekly graph with the week ending on Thursday which had the graph token gra2example3 then the full command would be:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
https://metapulse.com/api/v4/data_points?graph_id=gra2example3
Which would return a JSON array looking something like this:
[
{
"graphToken": "gra2example3",
"majorEvent": false,
"note": null,
"periodEnd": "2018-11-9",
"periodStart": "2018-11-15",
"value": "2.0",
"updaterEmail": "bob@example.com",
"createdAt": "2018-11-16T09:14:54.133+10:00"
"updatedAt": "2018-11-16T09:14:54.133+10:00"
},
{
"graphToken": "gra2example3",
"majorEvent": false,
"note": "We launched the product this week!",
"periodEnd": "2018-11-16",
"periodStart": "2018-11-22",
"value": "4.0",
"updaterEmail": "bob@example.com",
"createdAt": "2018-11-23T09:14:05.894+10:00",
"updatedAt": "2018-11-23T09:14:05.894+10:00"
},
{
"graphToken": "gra2example3",
"majorEvent": false,
"note": null,
"periodEnd": "2018-11-23",
"periodStart": "2018-11-29",
"value": "5.0",
"updaterEmail": "bob@example.com",
"createdAt": "2018-11-30T09:14:23.276+10:00",
"updatedAt": "2018-11-30T09:14:23.276+10:00"
},
...
]
This will return up to 50 data points at a time. You can fetch the next set of results by passing the page parameter. For example: /api/v4/data_points?page=2. You can also customize the number of results by passing per_page=100 up to 500 results per request.
List All Data Points Using Timestamp
You can use the following parameters to list data points for a specific period:
starts_afterReturns data points where the period starts after the given date.starts_on_or_afterReturns data points where the period starts on or after the given date.starts_beforeReturns data points where the period starts before the given date.starts_on_or_beforeReturns data points where the period starts on or before the given date.ends_afterReturns data points where the period ends after the given date.ends_on_or_afterReturns data points where the period ends on or after the given date.ends_beforeReturns data points where the period ends before the given date.ends_on_or_beforeReturns data points where the period ends on or before the given date.
You can use it like this:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
/api/v4/data_points?graph_id=<TOKEN>&starts_after=2023-01-01&ends_on_or_before=2023-02-01
You can pass created_after and updated_after passing a timestamp to only retrieve records that have been created or updated after the specified timestamp.
When updated_after or created_after is used the records are returned in order of news to oldest.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
https://metapulse.com/api/v4/data_points?graph_id=<TOKEN>&created_after=2023-01-01
/** Or Use updated_after **/
https://metapulse.com/api/v4/data_points?graph_id=<TOKEN>&updated_after=2023-01-01
Show a Data Point
To view details for a specific data point, pass the date into the path:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
https://metapulse.com/api/v4/data_points/2018-11-28?graph_id=<TOKEN>
This would return the following response:
{
"graphToken": "<GRAPH_TOKEN>",
"majorEvent": false,
"note": null,
"periodEnd": "2018-11-28",
"periodStart": "2018-11-28",
"value": "12.0",
"updaterEmail": "bob@example.com",
"createdAt": "2018-11-30T09:14:23.276+10:00",
"updatedAt": "2018-11-30T09:14:23.276+10:00"
}
Create or Update a Data Point
To set the value for a data point, run the following command:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"graph_id":"<GRAPH_TOKEN>","period":"2018-11-28","value":"15"}' \
https://metapulse.com/api/v4/data_points/set
This would set the value on 28th of November, 2018 to equal 15, creating it if it does not exist or updating it if it does exist. This would respond with:
{
"graphToken": "<GRAPH_TOKEN>",
"majorEvent": false,
"note": null,
"periodEnd": "2018-11-28",
"periodStart": "2018-11-28",
"value": "15.0",
"updaterEmail": "bob@example.com",
"createdAt": "2018-11-30T09:14:23.276+10:00",
"updatedAt": "2018-11-30T09:14:23.276+10:00"
}
If there is an error setting the data point, you will receive a 400 Bad Request with an error message.
{"error": {"message": "Graph is archived"}}
Split a Weekly Data Point Across Two Months
It is possible to split a data point into two values if you have a weekly graph and the period spans two months. One value is assigned to the first month and another to the second month.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"graph_id":"<GRAPH_TOKEN>","period":"2018-11-02","earlier_split_value":"10","later_split_value":"5"}' \
https://metapulse.com/api/v4/data_points/set
In this example the organization's week ends on a Friday. The data point period is for the 27th of October through the 2nd of November, 2018. The value 10 would be assigned to the October portion and 5 would be assigned to the November portion of the week.
Delete a Data Point
To delete a data point, pass an empty value.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"graph_id":"<GRAPH_TOKEN>","period":"2018-11-28","value":""}' \
https://metapulse.com/api/v4/data_points/set
That for example would remove the value on 28th of November, 2018.
Set Multiple Data Points at Once
You can set multiple data points in a single request by supplying an array of data point values. This will create the data point if it does not exist and update the value if it does exist. If you pass an empty value it will delete the data point.
NOTE: You need to have edit permission level for all graphs you are trying to update with set_multiple
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{
"data_points": [
{"graph_id": "gra123","value": "14","period": "2018-11-28"},
{"graph_id": "gra123","value": "","period": "2018-11-29"}
]
}' \
https://metapulse.com/api/v4/data_points/set_multiple
For example, this would set the value on 28th of November, 2018 to equal 14 and delete the data point on the 29th.
This would return the following output:
HTTP/2 200
date: Mon, 07 Jan 2019 03:04:49 GMT
content-type: application/json
...
If you need to set multiple datapoints for the same date, pass the period separately in the same /api/v4/data_points/set_multiple request.
{
"period": "2019-01-01",
"data_points": [
{"graph_id": "gra12345", "value": 1},
{"graph_id": "gra34567", "value": 2, "note": "Some note"},
{"graph_id": "gra56789", "value": 3, "period": "2019-02-01"}
]
}
Note the last data point has a period. This will override the initial period passed in. Any data points which don't have a period fall back to that global period.
Also, this behaves the same as the set action, so it will:
Create a data point if it doesn't exist
Update a data point if it already exists
Delete a data point if it exists and the given value is empty
Data Point Options
The following options can be passed in when setting a data point.
| The Graph ID (token) the data point belongs to. |
| The date the data point is on. |
| The decimal value assigned to the data point. |
| The first part of the value if it is a weekly period which covers two months. |
| The last part of the value if it is a weekly period which covers two months. |
| The note attached to the data point. |
| Extra content to add to an existing note. |
| Boolean |
| Set to |
Increment a Data Point
You can increment a data point for the 28th of November, 2018 by 1, creating it if it does not exist and setting it to the value of 1 or updating it by 1 if it does. Passing in a note value will append it to the existing note (if any) joined with a new line.
To do this, you would run the following command:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X PATCH \
-d '{"graph_id":"<GRAPH_TOKEN>","value":"1","note":"Second Note","period":"2018-11-28"}' \
https://metapulse.com/api/v4/data_points/increment
Which would give you in response if the graph already had the value of 15 and note of "First Note":
{
"graphToken": "<GRAPH_TOKEN>",
"majorEvent": false,
"note": "First Note\nSecond Note",
"periodEnd": "2018-11-28",
"periodStart": "2018-11-28",
"value": "16.0",
"updaterEmail": "bob@example.com",
"createdAt": "2018-11-30T09:01:32.921+10:00"
"updatedAt": "2018-11-30T09:14:23.276+10:00"
}
Note, passing a negative value will decrement the data point by the amount given.
Using the Graphs API
_______________________________________
Available Graph API actions:
Create a Graph
POST /api/v4/graphs HTTP/1.1
Host: metapulse.com
Content-Type: application/json
{
"organisation_token": "abc123",
"graph": {
"name": ,
"graph_type": "weekly",
"responsible_member_email": "name@email.com"
}
}
The organisation_token is the same as the "Organization ID" found on the organization settings.
If you want to add additional graph attributes while creating a graph, here's the full list:
| Name of the graph |
| You can add a description for the graph |
| daily, weekly, monthly, quarterly, yearly, comparison, calculated or concatenated |
| daily, weekly, monthly, quarterly or yearly |
|
|
| To assign the graph to a member, you need to provide the member's email address. |
| 1, 2, 3, etc. |
| |
| any symbol |
| |
| You can set a minimum value for the graph. If there is a value outside of this scope, the scope will be ignored. |
| You can set a maximum value for the graph. If there is a value outside of this scope, the scope will be ignored. |
| gap, zero or hide |
| |
| |
| |
| |
| It determines how values are displayed at lower frequencies. For example, it can display all values in the period, the average of all values, the minimum / maximum value within the period, the first or last reported value of the period. The values are |
| It's useful when daily graphs are used. It will collect data on all or specific days. The format is |
|
|
Search for a list of Graphs
MetaPulse has a power search function in the Graphs Index API.
Both graph names and user names can be searched.
The follow code returns all graphs with the term "Income" in the name.
Note, this also will returns any graph with an associated user that has the search term in their name.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
https://metapulse.com/api/v4/graphs?term=Income
Which should return 200 OK with an array of the graph tokens, names and graph type that match the search:
[
{
"token": "grawrddq12o",
"name": "Total Clients",
"graphType": "weekly",
"availableFrequencies": ["weekly", "monthly", "quarterly", "yearly"],
"hidden": false,
"archived": false,
"responsibleMemberFullName": "Bob Smith",
"responsibleMemberEmail": "bob@example.com",
"responsibleMemberEmployeeId": "ABC123",
"customAttributes": [{"name": "Internal ID", "value": "789"}]
}, {
"token": "gra8sd2qkez",
"name": "Gross Income",
"graphType": "daily",
"availableFrequencies": ["daily", "weekly", "monthly", "quarterly", "yearly"],
"hidden": false,
"archived": false,
"createdAt": "2018-11-30T09:01:32.921+10:00"
"updatedAt": "2018-11-30T09:14:23.276+10:00"
"responsibleMemberFullName": "Jane Smith",
"responsibleMemberEmail": "jane@example.com",
"responsibleMemberEmployeeId": "",
"customAttributes": []
}
]
The possible list of types returned for graphType are:
dailyweeklymonthlyquarterlyyearlycalculatedcomparisonconcatenated
This will return up to 50 graphs at a time. You can fetch the next set of results by passing the page parameter. For example: /api/v4/graphs?page=2. You can also customize the number of results by passing per_page=100 up to 500 results per request.
By default only active graphs are returned. Pass include_hidden=true to also return hidden graphs. Pass include_archived=true to also return archived graphs.
Search for a list of Graphs Using Timestamp
You can pass created_after and updated_after passing a timestamp to only retrieve records that have been created or updated after the specified timestamp.
When updated_after or created_after is used the records are returned in order of news to oldest.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/graphs?term=Income"
"https://metapulse.com/api/v4/graphs?term=Income&created_after=<TIMESTAMP>"
/** Or Use updated_after **/
"https://metapulse.com/api/v4/graphs?term=Income&updated_after=<TIMESTAMP>"
Set Custom Attributes on a Graph
Custom attributes allow you to define your own metadata on a graph. You can set custom attributes on a graph by supplying a name and value:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"graph_id": "grawrddq12o", "name": "Department", "value": "A17"}' \
"https://metapulse.com/api/v4/graph_custom_attributes"
That example will either create or update the custom attribute "Department" on graph grawrddq12o. For setting a Date Range Type see Setting a Member Custom Attributes with type Date Range.
The graph details will be returned on success:
{
"token": "grawrddq12o",
"name": "Total Clients",
"graphType": "weekly",
"availableFrequencies": ["weekly", "monthly", "quarterly", "yearly"],
"hidden": false,
"archived": false,
"createdAt": "2018-11-30T09:01:32.921+10:00"
"updatedAt": "2018-11-30T09:14:23.276+10:00"
"responsibleMemberFullName": "Bob Smith",
"responsibleMemberEmail": "bob@example.com",
"responsibleMemberEmployeeId": "ABC123",
"customAttributes": [{"name": "Department", "value": "A17"}]
}
Update a Graph
Send a PATCH request to the https://metapulse.com/api/v4/graphs/GRAPH_ID URL to update the graph.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X PATCH \
-d '{"graph": {"name": "Updated Name", "responsible_member_email": "name@email.com"}}'
} \
https://metapulse.com/api/v4/graphs/gra12345
This would change the graph name and responsible member assigned to the graph matching the ID gra12345.
Delete a Graph
Graphs can be deleted through the API. You need to pass a DELETE method to the https://metapulse.com/api/v4/graphs/[GRAPH_ID] URL. For example:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X DELETE \
https://metapulse.com/api/v4/graphs/[GRAPH_ID]
Using the Member Graphs API
_______________________________________
Available Member Graphs API actions:
List all viewable Graphs for a Member
To get a list of all graph tokens and the graph names viewable by a given user email, you can run the following command:
export params="email=mikel@reinteractive.net&type=viewable"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/member_graphs?${params}"
Which should return 200 OK with an array of the graph tokens, names and graph type that the user is able to edit:
[
{
"token": "grawrddq12o",
"name": "Total Clients",
"graphType": "weekly",
"hidden": false,
"archived": false,
"createdAt": "2018-10-12T11:21:13.209+10:00"
"updatedAt": "2018-10-13T17:12:43.847+10:00"
"responsibleMemberEmail": "bob@example.com",
"responsibleMemberEmployeeId": ""
}, {
"token": "gra8sd2qkez",
"name": "Gross Income",
"graphType": "daily",
"hidden": false,
"archived": false,
"createdAt": "2018-11-30T09:01:32.921+10:00"
"updatedAt": "2018-11-30T09:14:23.276+10:00"
"responsibleMemberEmail": "jane@example.com",
"responsibleMemberEmployeeId": ""
}
]
The possible list of types returned for graphType are:
daily
weekly
monthly
quarterly
yearly
calculated
comparison
concatenated
You can also specify the member using their Employee ID field if set:
export params="employee_id=ABC123&type=viewable"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/member_graphs?${params}"
This will return up to 50 graphs at a time. You can fetch the next set of results by passing the page parameter. For example: /api/v4/member_graphs?page=2. You can also customize the number of results by passing per_page=100 up to 500 results per request.
Note, you can pass created_after and updated_after passing a timestamp to only retreive records that have been created or updated after the specified timestamp.
List all editable Graphs for a Member
To get a list of all graph tokens and the graph names that the given member can edit, pass the type=editable parameter, for example:
export params="email=mikel@reinteractive.net&type=editable"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/member_graphs?${params}"
This will return the same output as listing the viewable graphs above.
List all responsible Graphs for a Member
To get a list of all graph tokens and the graph names that the given member is responsible for, pass the type=responsible parameter, for example:
export params="email=mikel@reinteractive.net&type=responsible"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/member_graphs?${params}"
This will return the same output as listing the viewable graphs above.
List all Graphs for a Member Using Timestamp
You can pass created_after and updated_after passing a timestamp to only retrieve records that have been created or updated after the specified timestamp.
When updated_after or created_after is used the records are returned in order of news to oldest.
export params="email=mikel@reinteractive.net&type=editable"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/member_graphs?${params}"
"https://metapulse.com/api/v4/member_graphs&type=responsible&created_after=<TIMESTAMP>"
/** Or Use updated_after **/
"https://metapulse.com/api/v4/member_graphs&type=responsible&updated_after=<TIMESTAMP>"
Using the Members API
_______________________________________
Available Member API actions:
List members under an organization
You can fetch members for an organization using the following:
See Organisation ID to get the ORGANISATION_TOKEN.
export params="organisation_id=<ORGANISATION_TOKEN>"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/members?{params}"
List members under an organization - Example Request
# GET https://metapulse.com/api/v4/members?organisation_id=orgmvn0c5uy
This will return the following fields for each member:
{
"id": "memi5vgbo31",
"email": "harry@example.com",
"fullName": "Harry Cash",
"phoneNumber": "",
"phoneExtension": "",
"mobileNumber": "",
"employeeId": "",
"status": "Permanent",
"hireDate": null,
"avatar": "https://staging-assets.metapulse.com/uploads/member/avatar/245/1728503930-980549575293776-0001-4252/avatar.png",
"avatarMedium": "https://staging-assets.metapulse.com/uploads/member/avatar/245/medium_1728503930-980549575293776-0001-4252/avatar.png",
"avatarSmall": "https://staging-assets.metapulse.com/uploads/member/avatar/245/small_1728503930-980549575293776-0001-4252/avatar.png",
"avatarThumb": "https://staging-assets.metapulse.com/uploads/member/avatar/245/thumb_1728503930-980549575293776-0001-4252/avatar.png",
"countryCode": "",
"countryName": "",
"state": null,
"city": "",
"building": "",
"floorName": "",
"floorSection": "",
"timeZone": "Sydney",
"postId": "posdb5a2hhq",
"postName": "Sales Director",
"positionId": "posdb5a2hhq",
"positionName": "Sales Director",
"orgNodeName": "Sales",
"teamLeader": true,
"assistant": false,
"managerEmail": "ceo@example.com",
"notificationEmailFrequency": "hourly",
"saml": false,
"archivedAt": null,
"createdAt": "2020-03-23T06:19:24.060Z",
"updatedAt": "2025-04-14T17:50:22.931Z",
"ancestryPath": [
{
"id": "uniw0xykhuv",
"name": "Building HQ USA",
"post": "1.",
"position": "1."
},
{
"id": "uniqup68j6m",
"name": "Sales",
"post": "1.C.",
"position": "1.C."
}
],
"customAttributes": [
{
"name": "Formal Given Name",
"type": "text",
"value": "Harry"
},
{
"name": "Formal Family Name",
"type": "text",
"value": "Cash"
}
]
}
This will return up to 50 members at a time. You can fetch the next set of results by passing the page parameter. For example: /api/v4/members?page=2. You can also customize the number of results by passing per_page=100 up to 500 results per request.
Note, you can pass created_after and updated_after passing a timestamp to only retreive records that have been created or updated after the specified timestamp.
The Ancestry Path will return a JSON array of all positions from the top of their organization chart all the way down to the member's highest position. This provides a way to determine what area each member is in.
List members under another member
It's possible to fetch members overseen by another member by passing the overseen_by parameter.
export params="organisation_id=<ORGANISATION_TOKEN>&overseen_by=<EMAIL>"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/members?{params}"
List members under another member - Example Request
# GET https://metapulse.com/api/v4/members?organisation_id=orgmvn3c2mz&overseen_by=harry@example.com
List members under another member - Example Response
[
{
"id": "mem5ikznbgx",
"email": "bob@example.com",
"fullName": "Bob Builder",
"phoneNumber": "1-769-854-2688",
"phoneExtension": "",
"mobileNumber": "",
"employeeId": "",
"status": "",
"hireDate": null,
"avatar": "https://staging-assets.metapulse.com/uploads/user/avatar/1/avatar(2).png",
"avatarMedium": "https://staging-assets.metapulse.com/uploads/user/avatar/1/medium_avatar(2).png",
"avatarSmall": "https://staging-assets.metapulse.com/uploads/user/avatar/1/small_avatar(2).png",
"avatarThumb": "https://staging-assets.metapulse.com/uploads/user/avatar/1/thumb_avatar(2).png",
"countryCode": "",
"countryName": "",
"state": null,
"city": "",
"building": "",
"floorName": "",
"floorSection": "",
"timeZone": "UTC",
"postId": "posjc2gavav",
"postName": "Director of Marketing",
"positionId": "posjc2gavav",
"positionName": "Director of Marketing",
"orgNodeName": "Sales",
"teamLeader": false,
"assistant": false,
"managerEmail": "harry@example.com",
"notificationEmailFrequency": "immediately",
"saml": false,
"archivedAt": null,
"createdAt": "2018-10-15T06:28:12.678Z",
"updatedAt": "2025-04-03T20:13:53.084Z",
"ancestryPath": [
{
"id": "uniw0xykhuv",
"name": "Building HQ USA",
"post": "1.",
"position": "1."
},
{
"id": "uniqup68j6m",
"name": "Sales",
"post": "1.C.",
"position": "1.C."
}
],
"customAttributes": []
},
{
"id": "mem2uc32jud",
"email": "sarah@example.com",
"fullName": "Sarah Black",
"phoneNumber": "",
"phoneExtension": "",
"mobileNumber": "",
"employeeId": "",
"status": "Permanent",
"hireDate": null,
"avatar": "https://staging-assets.metapulse.com/uploads/member/avatar/246/sarah_black.jpg",
"avatarMedium": "https://staging-assets.metapulse.com/uploads/member/avatar/246/medium_sarah_black.jpg",
"avatarSmall": "https://staging-assets.metapulse.com/uploads/member/avatar/246/small_sarah_black.jpg",
"avatarThumb": "https://staging-assets.metapulse.com/uploads/member/avatar/246/thumb_sarah_black.jpg",
"countryCode": "AU",
"countryName": "Australia",
"state": "",
"city": "",
"building": "",
"floorName": "",
"floorSection": "",
"timeZone": "Sydney",
"postId": "posjlir7x8o",
"postName": "Director of Sales",
"positionId": "posjlir7x8o",
"positionName": "Director of Sales",
"orgNodeName": "Sales & Marketing",
"teamLeader": false,
"assistant": false,
"managerEmail": null,
"notificationEmailFrequency": "immediately",
"saml": false,
"archivedAt": null,
"createdAt": "2020-03-23T08:44:53.186Z",
"updatedAt": "2025-02-24T23:17:16.210Z",
"ancestryPath": [
{
"id": "uninubczmok",
"name": "CEO",
"post": "1.",
"position": "1."
},
{
"id": "uniqvo8df9t",
"name": "Sales & Marketing",
"post": "1.C.",
"position": "1.C."
}
],
"customAttributes": [
{
"name": "Formal Given Name",
"type": "text",
"value": "Sarah"
},
{
"name": "Formal Family Name",
"type": "text",
"value": "Black"
}
]
}
This will return a list of members which are under that given member in the Team Chart.
Show a Specific Member
After you get the Member ID from the List action, or from the Manage Member Page, you can request details for an individual member as follows:
export email="<API_EMAIL>"
export key="<API_KEY>"
export memberid="<MEMBER_ID>" # eg, memaqt2owd7
export params="organisation_id=<ORGANISATION_TOKEN>"
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: ${email}" \
-H "api-key: ${key}" \
-X GET \
"https://metapulse.com/api/v4/members/{memberid}?{params}"
Show a Specific Member - Example Request
# GET https://metapulse.com/api/v4/members/mem3p3rlk8f?organisation_id=orgmvn0c5uy
This will return the same attributes as shown in Member Example Response.
Set Custom Attributes for a Member
Using the Member ID (mem12345678) obtained via the List action above, or from the Members Data Export, you can update the member's Custom Attributes as follows:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"name": "Department", "value": "A17"}' \
"https://metapulse.com/api/v4/members/<MEMBER_ID>/custom_attributes"
Setting a Member Custom Attributes with type Date Range
Here's syntax for setting a Date Range:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"name": "On Leave", "value": {"start_date":"2022-01-01","end_date":"2022-02-13"}}' \
"https://metapulse.com/api/v4/members/<MEMBER_ID>/custom_attributes"
Updating Member Attributes
Using the Member ID (mem12345678) obtained from the Members Data Export, you can update any of of the following member attributes:
Status
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"status": "Contractor"
}
}
The status options are "Permanent", "Contractor", "Intern" and "Trial".
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"email": "harry@example.com"
}
}
Employee ID
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"employee_id": "B17"
}
}
Hire Date
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"hire_date": "2024-06-01"
}
}
Full Name
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"full_name": "Harry Cash"
}
}
Phone Number
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"phone_number": "+16225349475"
}
}
Phone Extension
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"phone_extension": "23"
}
}
Mobile Number
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"mobile_number": "+18215349726"
}
}
Country
(The country ISO code needs to be entered. Only two characters are accepted. For full list of all country ISO codes, see https://countrycode.org/)
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"country_code": "US"
}
}
State
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"state": "Florida"
}
}
City
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"city": "Miami"
}
}
Building
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"city": "Miami"
}
}
Floor Name
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"floor_name": "Research"
}
}
Floor Section
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"floor_section": "Marketing"
}
}
Time Zone
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"time_zone": "Eastern Time (US & Canada)"
}
}
List of accepted time zones (see "TZ identifier" column):
Add Avatar
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"remote_avatar_url": "https://images.com/photos/photo-2259337.jpeg"
}
}
Remove Avatar (True/False, true to remove)
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"remove_avatar": true
}
}
SAML
(True/False. It can only be set if SAML is enabled on the account and the user is restricted to that account.)
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"allow_saml": true
}
}
Restrict User to an Account
(True/False, if it's the user's only account)
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"restrict_to_current_account": true
}
}
Email Alerts
(This is for sending a notification when an Alert is created. It should be true or false and the member being set needs to have permission to view alerts.)
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"email_alerts": true
}
}
Send Invitation
(You can only set this on new members. It doesn't work on existing members. It should be true or false. )
POST https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"organisation_id": "orgvev3c5uy",
"member": {
"email": "bob@example.com",
"full_name": "Bob Cat",
"send_invitation": true
}
}
Scheduled Mailings and Reminders
This refers to the following four reminders:
For this to work, you would need to set it to Custom Mailings and then enable/disable the desired reminder. Here's an example:
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{"member":
{
"mailings_preference": "custom",
"mailing_settings_attributes": [
{
"email_template_id": "07ad2013-8105-49ac-b82f-49acc4c18b75",
"enabled": false
},
{
"email_template_id": "794e2b80-42bf-4acb-ac69-51bw276c7ac1",
"enabled": false
},
{
"email_template_id": "a117bb21-b52a-4c12-82d5-f649bf78b0c4",
"enabled": false
},
{
"email_template_id": "79bf6m09-6678-4c79-b8fe-b9126c47af7a",
"enabled": false
}
]
}
}
To get the Email Template IDs, you would need to export the Email Templates from the Data Export page.
Email Frequency Notification (can be never, immediately, hourly, daily or weekly)
This refers to the following setting:
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member": {
"notification_email_frequency": "immediately"
}
}
Customize Individual Notifications
This refers to all predefined email notifications that are being sent when a specific event is triggered, such as when a Knowledge Item is created or a Graphs View is shared with another member, etc.
These notification relate to Knowledge, Alerts, Data Import, Data Export and Views (Knowledge, Objectives or Graphs.):
PATCH https://metapulse.com/api/v4/members/<MEMBER_ID>
{
"member":
{
"email_notification_settings":
{
"0": {
"type_key": "knowledge_approval_step_pending",
"frequency": "hourly"
},
"1": {
"type_key": "knowledge_approval_step_pending",
"frequency": "hourly"
},
"2": {
"type_key": "knowledge_approval_requested",
"frequency": "hourly"
}
}
}
}
Here, they keys "0" and "1" don't have any special meaning, they just need to be unique.
The above example only includes 3 types. Here's a list of all of them, including the available frequencies:
The type_key can be one of:
knowledge_approval_step_pendingknowledge_approval_requestedknowledge_item_version_approvedknowledge_item_version_publishedknowledge_assignment_createdknowledge_assignment_updatedknowledge_assignment_manually_createdknowledge_assignments_multiple_createdknowledge_assignment_completedknowledge_subject_assignment_createdknowledge_collaborator_addedknowledge_collaboration_requestknowledge_comment_createdknowledge_comment_mentionknowledge_periodic_reviews_dueknowledge_periodic_reviews_overduealert_created_confirmationalert_assigneddata_import_succeededdata_import_faileddata_export_succeededdata_export_failedview_shared
And the frequency can be one of:
neverimmediatelyhourlydailyweekly
If the update is successful, the response will be 200 with the member details (same as GET member). If there's a validation error the response will be 400 error code with JSON body. Here's an example:
{
"errors": {
"message": "Unable to save member due to the following error: Email is invalid"
}
}
Show Away Periods
Show Away Periods for a Member
List
Returns array of away periods for a given member.
Show Away Periods for a Member - Example Request
# GET https://metapulse.com/api/v4/member/[MEMBER_ID]/away_periods
Show Away Periods for a Member - Example Response
[
{
"id": "e1957d54-bf87-4d1a-8aa1-d71d0563ddae",
"startDate": "2022-01-01",
"endDate": "2022-02-02",
"reason": "Holiday"
}
]
Show
Returns data for a single away period given an ID. Note the ID is in the URL.
Show a Single Away Period for a Member - Example Request
# GET https://metapulse.com/api/v4/member/[MEMBER_ID]/away_periods/[AWAY_PERIOD_ID]
Show a Single Away Period - Example Response
{
"id": "e1957d54-bf87-4d1a-8aa1-d71d0563ddae",
"startDate": "2022-01-01",
"endDate": "2022-02-02",
"reason": "Holiday",
}
Create
Creates an away period given attributes.
Create a Single Away Period - Example Request
# POST https://metapulse.com/api/v4/member/[MEMBER_ID]/away_periods
{
"away_period": {
"start_date": "2022-01-01",
"end_date": "2022-02-02",
"reason": "Holiday"
}
}
Create a Single Away Period - Example Success Response
Same as "Show" above
Create a Single Away Period - Example Failure Response
# Returns 400 bad request
{"error":{"message":"Unable to save away period: Start Date can't be blank."}}
Update
Updates an away period given id and attributes.
Update a Single Away Period - Example Request
# PATCH https://metapulse.com/api/v4/member/[MEMBER_ID]/away_periods/[AWAY_PERIOD_ID]
{
"away_period": {
"start_date": "2022-01-01",
"end_date": "2022-02-02",
"reason": "Holiday"
}
}
Example Success Response
Same as "Show" above
Example Failure Response
Same as "Create" above
Destroy
Deletes an away period given id.
Delete a Single Away Period - Example Request
# DELETE https://metapulse.com/api/v4/member/[MEMBER_ID]/away_periods/[AWAY_PERIOD_ID]
Example Response
Nothing (200 OK)
Show Away Periods for all Members
List
Returns all away periods for a given organization.
Show Away Periods for all Members - Example Request
# GET https://metapulse.com/api/v4/members/away_periods/?organisation_id=[ORGANIZATION_ID]
Show Away Periods for all Members - Example Response
[
{
"id": "07e48750-b935-4e34-a24f-81b36bd830bb",
"startDate": "2022-10-10",
"endDate": "2022-10-15",
"reason": "Vacation",
"memberId": "memqomqq6z1",
"memberEmail": "sally@example.com"
},
{
"id": "bc6dfde0-ae30-4f69-84f1-d8c15654689a",
"startDate": "2024-06-15",
"endDate": "2024-06-21",
"reason": "Vacation",
"memberId": "mem1x1843ct",
"memberEmail": "bill@example.com"
},
{
"id": "fac08ea7-b927-470e-849c-aa02ecdf88f3",
"startDate": "2024-08-12",
"endDate": "2024-08-22",
"reason": "Vacation",
"memberId": "mem1st9w5wz",
"memberEmail": "kim@example.com"
}
]
If there are too many, you can split them in pages. The limit per page is 500.
Show Away Periods for all Members Page by Page - Example Request
# GET https://metapulse.com/api/v4/members/away_periods?page=2&per_page=500
Create a member
Create a member - Example Request
# POST https://metapulse.com/api/v4/members/
{
"organisation_id": "orgt5omjbsk",
"member": {
"email": "bobcat@example.com",
"full_name": "Bob Cat"
}
}
Create a member - Example Response
{
"id": "mem2drlgc88",
"email": "bobcat@example.com",
"fullName": "Bob Cat",
"phoneNumber": null,
"phoneExtension": null,
"mobileNumber": null,
"employeeId": null,
"status": null,
"hireDate": null,
"avatar": null,
"avatarMedium": null,
"avatarSmall": null,
"avatarThumb": null,
"countryCode": null,
"countryName": null,
"state": null,
"city": null,
"building": null,
"floorName": null,
"floorSection": null,
"timeZone": "Sydney",
"postId": null,
"postName": null,
"positionId": null,
"positionName": null,
"orgNodeName": null,
"managerEmail": null,
"createdAt": "2024-08-23T17:08:35.613Z",
"updatedAt": "2024-08-23T17:08:35.613Z",
"customAttributes": []
}
Archive a member
Archive a member - Example Request
# POST https://metapulse.com/api/v4/members/<MEMBER_ID>/archive
This will return an empty 200 OK response.
Unarchive a member
Unarchive a member - Example Request
# POST https://metapulse.com/api/v4/members/<MEMBER_ID>/unarchive
This will return an empty 200 OK response.
Using the Team Chart API
Team Charts
The Team Charts API lets you list and read the team charts in an organisation. A team chart is the top-level container for the org structure; it contains teams, which contain positions, which are filled by members.
For an introduction to authentication and the common request format, see the MetaPulse API v4 overview.
All examples assume:
API_EMAIL— the email of your MetaPulse userAPI_KEY— the API key from your MetaPulse user profileORG_ID— your organisation id (e.g.org12abc3de4)
Every endpoint requires the organisation_id query parameter.
Endpoints
Method | Path | Description |
GET |
| List team charts |
GET |
| Show a team chart |
The Team Chart Object
{
"id": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"name": "Operations",
"main": true,
"missionStatement": "Deliver a great product to our customers.",
"archivedAt": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}Field | Type | Description |
| UUID | Unique identifier of the team chart. |
| string | Display name. |
| boolean | Whether this is the org's main team chart. |
| string | null | Free-form mission statement. |
| timestamp | null | Set when the team chart is archived. |
| timestamp | When the team chart was created. |
| timestamp | When the team chart was last updated. |
List Team Charts
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/team_charts?organisation_id=<ORG_ID>"
Returns a JSON array of team chart objects. Pagination defaults to 50 results per page; pass page and per_page (up to 500) to customise.
[
{
"id": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"name": "Operations",
"main": true,
"missionStatement": "Deliver a great product to our customers.",
"archivedAt": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
},
{
"id": "8a2c3d44-1b22-4ee2-9101-7c8a9d0e2b33",
"name": "Sales",
"main": false,
"missionStatement": null,
"archivedAt": null,
"createdAt": "2025-01-20T10:00:00.000+10:00",
"updatedAt": "2025-01-20T10:00:00.000+10:00"
}
]
Show a Team Chart
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/team_charts/<ID>?organisation_id=<ORG_ID>"
Returns a single team chart object, or 404 Not Found if no team chart with that id exists in the organisation.
{
"id": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"name": "Operations",
"main": true,
"missionStatement": "Deliver a great product to our customers.",
"archivedAt": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}
Errors
All endpoints return errors in a consistent shape:
{ "error": { "message": "<human-readable message>" } }Status | When |
| Missing or invalid |
| The team chart or organisation id doesn't exist or isn't visible to your user. |
Teams
The Teams API lets you list, read, create, update, archive and re-parent the teams inside a team chart. A team is a node in the org structure; teams nest under a parent team, and each team holds one or more positions (see the Positions API).
For an introduction to authentication and the common request format, see the MetaPulse API v4 overview.
All examples assume:
API_EMAIL— the email of your MetaPulse userAPI_KEY— the API key from your MetaPulse user profileORG_ID— your organisation id (e.g.org12abc3de4)
Every endpoint requires the organisation_id query parameter.
Endpoints
Method | Path | Description |
GET |
| List teams |
GET |
| Show a team |
POST |
| Create a team |
PATCH |
| Update a team |
POST |
| Archive a team |
POST |
| Unarchive a team |
POST |
| Re-parent a team |
The Team Object
{
"id": "tea12abc3de4",
"name": "Engineering",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 0,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}Field | Type | Description |
| string | Unique id for the team (e.g. |
| string | Display name. |
| UUID | The team chart this team belongs to. |
| string | null | Id of the parent team, or |
| integer | Sort order among siblings. |
| timestamp | null | Set when the team is archived. |
| boolean |
|
| timestamp | When the team was created. |
| timestamp | When the team was last updated. |
List Teams
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/teams?organisation_id=<ORG_ID>"
Returns a JSON array of team objects. Defaults to active (non-archived) teams, ordered by sequence then id. Pagination defaults to 50 results per page; pass page and per_page (up to 500) to customise.
Query Parameters
Parameter | Description |
| Only return teams in the given team chart. |
| Only return teams whose parent is this team. Pass |
|
|
| Page number (1-based). |
| Page size (default 50, max 500). |
[
{
"id": "tea12abc3de4",
"name": "Engineering",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 0,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
},
{
"id": "tea56def7gh8",
"name": "Design",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 1,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-16T09:14:54.133+10:00",
"updatedAt": "2025-01-16T09:14:54.133+10:00"
}
]
Show a Team
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/teams/<ID>?organisation_id=<ORG_ID>"
Returns a single team object, or 404 Not Found if no team with that id exists in the organisation.
{
"id": "tea12abc3de4",
"name": "Engineering",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 0,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}
Create a Team
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{
"team": {
"name": "Engineering",
"team_chart_id": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parent_id": "tea98zyx7wvu"
}
}' \
"https://metapulse.com/api/v4/teams?organisation_id=<ORG_ID>"
Returns the created team (HTTP 200):
{
"id": "tea12abc3de4",
"name": "Engineering",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 0,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-01-15T09:14:54.133+10:00"
}
See Errors for the validation failure response.
Body Parameters (under team)
Parameter | Required | Description |
| yes | Display name. |
| yes | UUID of the team chart this team belongs to. |
| no | Id of the parent team. Omit (or |
| no | Free-form information about the team. |
| no | The team's valuable final product (also accepted as |
| no | Knowledge item linked to this team. |
| no | Sort order among siblings. |
| no | Hex color, e.g. |
| no | Whether the color is shown on the chart. |
| no | Whether the team is displayed as elevated on the chart. |
| no | Create as a draft (unpublished) team. Create-only; ignored on update. |
Update a Team
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X PATCH \
-d '{ "team": { "name": "Product Engineering" } }' \
"https://metapulse.com/api/v4/teams/<ID>?organisation_id=<ORG_ID>"
Accepts the same body parameters as create, except draft (which is create-only). Returns the updated team (HTTP 200):
{
"id": "tea12abc3de4",
"name": "Product Engineering",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 0,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-10T14:32:01.554+10:00"
}
See Errors for the validation failure response.
Archive a Team
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
"https://metapulse.com/api/v4/teams/<ID>/archive?organisation_id=<ORG_ID>"
Returns HTTP 200 with an empty body. A team can only be archived when it has no active children and no active aliases; attempting to archive a team that violates either constraint returns 401 Unauthorized.
Unarchive a Team
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
"https://metapulse.com/api/v4/teams/<ID>/unarchive?organisation_id=<ORG_ID>"
Returns HTTP 200 with an empty body. The team must currently be archived; unarchiving an already-active team returns 401 Unauthorized.
Move a Team
Re-parents the team. Pass parent_id at the top level (not nested under team).
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{ "parent_id": "tea98zyx7wvu" }' \
"https://metapulse.com/api/v4/teams/<ID>/move?organisation_id=<ORG_ID>"
Pass "parent_id": null to make the team a root team. Returns the updated team (HTTP 200):
{
"id": "tea12abc3de4",
"name": "Engineering",
"teamChartId": "6f9f2b1c-3d4e-4a55-9c12-2f3b8e2a1d7e",
"parentId": "tea98zyx7wvu",
"sequence": 0,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-10T14:32:01.554+10:00"
}
Returns 404 Not Found if the parent id can't be found in the organisation.
Errors
All endpoints return errors in a consistent shape:
{ "error": { "message": "<human-readable message>" } }Status | When |
| Validation failure on create/update/move (e.g. blank name, unknown |
| Missing or invalid |
| The team, parent team, or organisation id doesn't exist or isn't visible to your user. |
Example validation error from create or update:
{ "error": { "message": "Unable to save team due to the following error: Name can't be blank" } }
Roles
The Roles API lets you list, read, create and update the roles in an organisation. A role is a reusable job description; positions (see the Positions API) reference a role.
For an introduction to authentication and the common request format, see the MetaPulse API v4 overview.
All examples assume:
API_EMAIL— the email of your MetaPulse userAPI_KEY— the API key from your MetaPulse user profileORG_ID— your organisation id (e.g.org12abc3de4)
Every endpoint requires the organisation_id query parameter.
Endpoints
Method | Path | Description |
GET |
| List roles |
GET |
| Show a role |
POST |
| Create a role |
PATCH |
| Update a role |
The Role Object
{
"id": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"name": "Engineer",
"displayName": "Software Engineer",
"purpose": "Build and maintain the product.",
"function": "Writes, reviews, and ships code.",
"results": "Working features delivered to customers.",
"teamLeader": false,
"assistant": false,
"graphPermissionLevel": "view",
"knowledgeItemId": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}Field | Type | Description |
| UUID | Unique identifier of the role. |
| string | Internal name (must be unique within the organisation). |
| string | null | Display name shown on the chart. |
| string | null | The role's purpose. |
| string | null | The role's function. |
| string | null | The role's valuable final product / expected results. |
| boolean | Whether members in this role lead the team they sit on. |
| boolean | Whether members in this role are assistants to the team leader. |
| string | Default permission level for graphs. One of |
| UUID | null | Knowledge item linked to this role. |
| timestamp | When the role was created. |
| timestamp | When the role was last updated. |
List Roles
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/roles?organisation_id=<ORG_ID>"
Returns a JSON array of role objects, ordered by name. Pagination defaults to 50 results per page; pass page and per_page (up to 500) to customise.
Query Parameters
Parameter | Description |
| Only return roles that have at least one position on this team. |
| Only return roles that the given member fills via at least one position. |
| Page number (1-based). |
| Page size (default 50, max 500). |
[
{
"id": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"name": "Engineer",
"displayName": "Software Engineer",
"purpose": "Build and maintain the product.",
"function": "Writes, reviews, and ships code.",
"results": "Working features delivered to customers.",
"teamLeader": false,
"assistant": false,
"graphPermissionLevel": "view",
"knowledgeItemId": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}
]
Show a Role
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/roles/<ID>?organisation_id=<ORG_ID>"
Returns a single role object, or 404 Not Found if no role with that id exists in the organisation.
{
"id": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"name": "Engineer",
"displayName": "Software Engineer",
"purpose": "Build and maintain the product.",
"function": "Writes, reviews, and ships code.",
"results": "Working features delivered to customers.",
"teamLeader": false,
"assistant": false,
"graphPermissionLevel": "view",
"knowledgeItemId": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}
Create a Role
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{
"role": {
"name": "Engineer",
"display_name": "Software Engineer",
"purpose": "Build and maintain the product."
}
}' \
"https://metapulse.com/api/v4/roles?organisation_id=<ORG_ID>"
Returns the created role (HTTP 200):
{
"id": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"name": "Engineer",
"displayName": "Software Engineer",
"purpose": "Build and maintain the product.",
"function": null,
"results": null,
"teamLeader": false,
"assistant": false,
"graphPermissionLevel": "view",
"knowledgeItemId": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-01-15T09:14:54.133+10:00"
}
See Errors for the validation failure response.
Body Parameters (under role)
Parameter | Required | Description |
| yes | Internal name (must be unique within the organisation). |
| no | Display name shown on the chart. |
| no | The role's purpose. |
| no | The role's function. |
| no | The role's valuable final product (also accepted as |
| no | Boolean — sometimes referred to as |
| no | Alias of |
| no | Boolean. |
| no | One of |
| no | Knowledge item linked to this role. |
Update a Role
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X PATCH \
-d '{ "role": { "display_name": "Staff Software Engineer" } }' \
"https://metapulse.com/api/v4/roles/<ID>?organisation_id=<ORG_ID>"
Accepts the same body parameters as create. Returns the updated role (HTTP 200):
{
"id": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"name": "Engineer",
"displayName": "Staff Software Engineer",
"purpose": "Build and maintain the product.",
"function": "Writes, reviews, and ships code.",
"results": "Working features delivered to customers.",
"teamLeader": false,
"assistant": false,
"graphPermissionLevel": "view",
"knowledgeItemId": null,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-10T14:32:01.554+10:00"
}
See Errors for the validation failure response.
Errors
All endpoints return errors in a consistent shape:
{ "error": { "message": "<human-readable message>" } }Status | When |
| Validation failure on create/update (e.g. blank or non-unique name). |
| Missing or invalid |
| The role or organisation id doesn't exist or isn't visible to your user. |
Example validation error from create or update:
{ "error": { "message": "Unable to save role due to the following error: Name can't be blank" } }
Positions
The Positions API lets you list, read, create, update, archive, and reassign positions. A position sits on a team, points at a role (see the Roles API), and is filled by a member.
For an introduction to authentication and the common request format, see the MetaPulse API v4 overview.
All examples assume:
API_EMAIL— the email of your MetaPulse userAPI_KEY— the API key from your MetaPulse user profileORG_ID— your organisation id (e.g.org12abc3de4)
Every endpoint requires the organisation_id query parameter.
Endpoints
Method | Path | Description |
GET |
| List positions |
GET |
| Show a position |
POST |
| Create a position |
PATCH |
| Update a position |
POST |
| Reassign the member on a position |
POST |
| Archive a position |
The Position Object
{
"id": "pos45fgh6ij7",
"name": "Senior Engineer",
"teamId": "tea12abc3de4",
"roleId": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"roleName": "Engineer",
"memberId": "mem78klm9no0",
"alias": null,
"sourcePositionId": null,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}Field | Type | Description |
| string | Unique id for the position (e.g. |
| string | Display name. Falls back to |
| string | null | Id of the team this position sits on. |
| UUID | null | Id of the role this position represents. |
| string | null | Name of the role, denormalised for convenience. |
| string | null | Id of the member currently filling this position. |
| string | null | Alias type when the position is a reference to another position. |
| string | null | When |
| timestamp | null | Set when the position is archived. |
| boolean |
|
| timestamp | When the position was created. |
| timestamp | When the position was last updated. |
List Positions
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/positions?organisation_id=<ORG_ID>"
Returns a JSON array of position objects, ordered by sequence then id. Defaults to active (non-archived) positions. Pagination defaults to 50 results per page; pass page and per_page (up to 500) to customise.
Query Parameters
Parameter | Description |
| Only return positions on this team. |
| Only return positions filled by this member. |
| Only return positions for this role (UUID). |
|
|
| Page number (1-based). |
| Page size (default 50, max 500). |
[
{
"id": "pos45fgh6ij7",
"name": "Senior Engineer",
"teamId": "tea12abc3de4",
"roleId": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"roleName": "Engineer", "memberId": "mem78klm9no0",
"alias": null,
"sourcePositionId": null,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}
]
Show a Position
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X GET \
"https://metapulse.com/api/v4/positions/<ID>?organisation_id=<ORG_ID>"
Returns a single position object, or 404 Not Found if no position with that id exists in the organisation.
{
"id": "pos45fgh6ij7",
"name": "Senior Engineer",
"teamId": "tea12abc3de4",
"roleId": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"roleName": "Engineer",
"memberId": "mem78klm9no0",
"alias": null,
"sourcePositionId": null,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-02T11:02:10.221+10:00"
}
Create a Position
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{
"position": {
"team_id": "tea12abc3de4",
"role_id": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"member_id": "mem78klm9no0",
"custom_name": "Senior Engineer"
}
}' \
"https://metapulse.com/api/v4/positions?organisation_id=<ORG_ID>"
Returns the created position (HTTP 200):
{
"id": "pos45fgh6ij7",
"name": "Senior Engineer",
"teamId": "tea12abc3de4",
"roleId": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"roleName": "Engineer",
"memberId": "mem78klm9no0",
"alias": null,
"sourcePositionId": null,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-01-15T09:14:54.133+10:00"
}
See Errors for the validation failure response.
Body Parameters (under position)
Parameter | Required | Description |
| yes | Id of the team this position will sit on. |
| no | UUID of the role this position represents. |
| no | Id of the member filling this position. Omit for a vacant position. |
| no | Override the role name with a position-specific label. |
| no | Sort order among siblings. |
| no | Mark as a temporary position. |
| no | Location fields. |
| no | Create as a draft (unpublished) position. Create-only; ignored on update. |
Update a Position
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X PATCH \
-d '{ "position": { "custom_name": "Staff Engineer" } }' \
"https://metapulse.com/api/v4/positions/<ID>?organisation_id=<ORG_ID>"
Accepts the same body parameters as create, except member_id and draft (which is create-only). To change which member fills a position, use Replace member. If you include member_id in an update request it is silently ignored.
Returns the updated position (HTTP 200):
{
"id": "pos45fgh6ij7",
"name": "Staff Engineer",
"teamId": "tea12abc3de4",
"roleId": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"roleName": "Engineer",
"memberId": "mem78klm9no0",
"alias": null,
"sourcePositionId": null,
"archivedAt": null,
"draft": false,
"createdAt": "2025-01-15T09:14:54.133+10:00",
"updatedAt": "2025-02-10T14:32:01.554+10:00"
}
See Errors for the validation failure response.
Replace a Member
Reassigns the member filling a position. Internally this archives the existing position and returns a fresh one with the new member assigned — so the response id differs from the request id. The original position's id is echoed back as previousPositionId.
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{ "member_id": "mem99qrs8tuv" }' \
"https://metapulse.com/api/v4/positions/<ID>/replace_member?organisation_id=<ORG_ID>"
Pass "member_id": null to vacate the position. Returns HTTP 201:
{
"id": "pos11new2222",
"name": "Senior Engineer",
"teamId": "tea12abc3de4",
"roleId": "9c1f4d22-2c8a-4d3e-b5b7-8b6e6a1f1a01",
"roleName": "Engineer",
"memberId": "mem99qrs8tuv",
"previousPositionId": "pos45fgh6ij7",
"archivedAt": null,
"draft": false,
"createdAt": "2025-02-10T09:14:54.133+10:00",
"updatedAt": "2025-02-10T09:14:54.133+10:00"
}
Archive a Position
curl -i \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
"https://metapulse.com/api/v4/positions/<ID>/archive?organisation_id=<ORG_ID>"
Returns HTTP 200 with an empty body. Any aliases of the position are archived along with it.
Errors
All endpoints return errors in a consistent shape:
{ "error": { "message": "<human-readable message>" } }Status | When |
| Validation failure on create/update (e.g. missing required association). |
| Missing or invalid |
| The position, team, role, member, or organisation id doesn't exist or isn't visible to your user. |
Example validation error from create or update:
{ "error": { "message": "Unable to save position due to the following error: Team can't be blank" } }
Set Custom Attributes for a Position
Using the position ID obtained from the Members List above or via Team Chart Data Export, you can update the position's Custom Attributes as follows:
curl -i \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "api-email: <API_EMAIL>" \
-H "api-key: <API_KEY>" \
-X POST \
-d '{"name": "Department", "value": "A17"}' \
"https://metapulse.com/api/v4/posts/<POST_ID>/custom_attributes"
For setting a Date Range Type see Setting a Member Custom Attributes with type Date Range.
Debugging
_______________________________________
Getting APIs to work can be a real pain sometimes, especially if you don't have direct access to send requests out.
A good tool to figure out if you are sending the API request correctly is beeceptor.com which is a free service to show you what your application is actually sending to MetaPulse.
Debugging
curl -i -H "api-key: API_KEY" \
-H "api-email: bob@example.com" \
https://test-metapulse.free.beeceptor.com/authentication
After sending this you'll get something back like:
HTTP/1.1 200 OK
Date: Tue, 05 Feb 2019 12:23:29 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Hey ya! Great to see you here. Btw, nothing is configured for this request path. Create a rule and start building a mock API.
Which shows you BeeCeptor got your message.
Going to https://app.beeceptor.com/console/test-metapulse will then show you a request, which you can click and then view the headers of and see something like:
Which looks good!
Questions / Comments
_______________________________________
If you have any questions or comments, please contact us via support.




