Permissioned Webhooks

What are Permissioned Webhooks?

Permissioned Webhooks in BambooHR are a specific type of webhook you can create using the API. Like standard webhooks, they notify you about changes to employee data by sending information to a specified URL. The key difference is that permissioned webhooks are tied to the access level of the user who created them. This means the webhook can only monitor fields and send data that the specific user has permission to access. You'll need to ensure the user's access level, managed by your company's admin users, grants visibility to all the employee fields you intend to monitor or include in the webhook notifications. This documentation page focuses specifically on how to create these Permissioned Webhooks via the API.

Requirements

Permissioned Webhooks can be created by anyone with an API key just like any other API endpoint. Keep in mind that to use the webhook endpoints you will be restricted to one access level. Make sure that you have access to all the fields you will need. Access levels are managed by your admin users in Settings and clicking on Access Levels.

Please note that webhooks created by a user will stop functioning if that user's account is deactivated.

If you are a third party company, you will need to work with an employee of the Bamboo client company. Make sure you have the right permissions to access the information you need for your webhook.

Getting Monitor Fields and Post Fields

Before you create a webhook, you'll want to decide what fields to monitor and what fields to post. To see what fields you can monitor you can call this endpoint. Get monitor fields. You will also need to decide what fields to post when changes occur to the monitored fields. To view a list of all fields you can call this endpoint. Get a list of fields

GET: https://api.bamboohr.com/api/gateway.php/{{companyDomain}}/v1/webhooks/monitor_fields
GET: https://api.bamboohr.com/api/gateway.php/{{companyDomain}}/v1/meta/fields/

Keep in mind that you may not have access to all fields shown. Access will depend on your access levels granted to the user of the API key. Once you have chosen the fields you would like to monitor or post you can access them by using their IDs, or aliases if they are available to the field.

Configuration

Now that you have chosen your fields, we can start to create your webhook. With each chosen field you can specify a name to be passed to your webhook. This is what each field will return under when the webhook is sent to you.

You will also need a url to set where the webhooks will fire to. If you need a temporary url to test your webhook there is a nifty tool you can use at webhook.site.

You can specify a schedule of when you want the webhooks to fire. For example, you could set your webhooks to fire every half an hour by setting minute to 30. You can also limit how often a webhook will fire by setting a maximum number of requests per interval in seconds. Times represents the given number of times the webhook can fire per the given interval in seconds.

🚧

Keep in mind that we have a rate limit maximum of 1 time every 60 seconds.

Example

Now that you have decided on your fields and settings you are ready to call the create endpoint. Here is an example post body sent to the create endpoint. In this example I have created a webhook that uses employee number and first name. Then when changes are made to those fields, the employee number, first name, last name, and job title, are sent with the field names specified to what I am expecting on my end. I have set it to send to a temporary url every 2 minutes. I have also set a limit of 5 times for every 20 minutes.

{
  "name": "My new webhook",
  "monitorFields": [
        "employeeNumber",
        "firstName"
    ],
    "postFields": {
        "employeeNumber": "Employee #",
        "firstName": "First name",
        "lastName": "Last name",
        "17": "Job title"
    },
  "url": "https://example.com/8846d359-da33-42cb-a1ed-b3182c2ef4ec",
  "format": "json",
    "frequency": {
        "minute": 30
    },
    "limit": {
        "times": 5,
        "seconds": 1200
    }
}
{
    "id": "123",
    "name": "My new webhook",
    "created": "2021-10-04 17:10:47",
    "lastSent": null,
    "monitorFields": [
        "employeeNumber",
        "firstName"
    ],
    "postFields": {
        "employeeNumber": "Employee #",
        "firstName": "First name",
        "jobTitleId": "Job title",
        "lastName": "Last name"
    },
    "url": "https://example.com/8846d359-da33-42cb-a1ed-b3182c2ef4ec",
    "format": "json",
    "frequency": {
        "day": "",
        "month": "",
        "hour": "",
        "minute": "2"
    },
    "limit": {
        "times": "5",
        "seconds": "1200"
    },
    "privateKey": "37b26dc8cf1f08435fd0d08779268d77"
}
{
    "errors": {
        "monitorFieldViolations": [
          	{
              id: 636,
              name:"employeeNumber"
            }
        ],
        "postFieldViolations": [
          	{
              id: 636,
              name:"employeeNumber"
            }
        ]
    }
}

As this is a RESTful API, much of the return data will be the same. You'll want to verify that the created webhook matches your intent. This will also be the only time you will receive the private key so be sure to save it. If you ever need another key, you want to create a new webhook and delete the previous one.

If an error does occur, it will be returned under the errors key value with a list of issues found in the request. For field permission errors you will need to reach out to an account admin user and ask for those fields to be included on the API users access level permissions.

Webhook Data Format

The webhook URL will be sent a POST request with a list of employees triggered by the monitor fields with data you have requested. Employee data will be batched when possible, so that if multiple employees' data has been changed, they will be sent together.

Data will be posted in the JSON or the standard format of an HTML form submission. We recommend the JSON format. The structure will be:

{
	"employees": [
		{
			"changedFields": [
				"Employee #"
			],
			"fields": {
				"Employee #": {
					"value": "358304"
				},
				"First Name": {
					"value": "Sebastian"
				},
				"Last Name": {
					"value": "Hickle"
				},
				"Job Title": {
					"value": null
				}
			},
			"id": "40351"
		},
		{
			"changedFields": [
				"First name"
			],
			"fields": {
				"Employee #": {
					"value": "351881"
				},
				"First Name": {
					"value": "Angelino"
				},
				"Last Name": {
					"value": "Bergstrom"
				},
				"Job Title": {
					"value": "Developer"
				}
			},
			"id": "40546"
		}
	]
}
employees[40351][changedFields][0] = Employee #
employees[40351][Employee #] = 358304
employees[40351][First name] = Sebastian
employees[40351][Last name] = Hickle
employees[40351][Job title] = 

employees[40546][changedFields][0] = First name
employees[40546][Employee #] = 35188
employees[40546][First name] = Angelino
employees[40546][Last name] = Bergstrom
employees[40546][Job title] = Developer
{
  "errors": [
    {
      "companyDomain": "samltest",
      "webhookId": "3",
      "error": "permission denied to the following fields",
      "fields": {
        "636": "Employee #"
      }
    }
  ]
}
errors[0][companyDomain] = samltest
errors[0][webhookId] = 3
errors[0][error] = Permission denied to the following fields
errors[0][fields][636] = Employee #

"changedFields" is an array of fields that were changed. If the field is included in the employee data, it will give the name of the posted field. Otherwise, a field ID will be given, and more information about the field can be looked up using the API.

While this structure will not be changed, you will receive results based on the fields you have chosen to monitor and post. In addition, in the future, we may add more context to this structure, so it is good practice to ignore fields that your webhook does not recognize.

If you monitor a field that belongs to a table, keep in mind that the webhook will be triggered every time the table is updated, even if the field being monitored is not updated. An example would be if you were monitoring the job title field. This belongs to the job info table so you would also be notified if the reporting to field was updated, since it belongs to the same table.

📘

Note: You will need to parse the form submission data

The actual return data for the example above is this:

employees%5B40351%5D%5BchangedFields%5D%5B0%5D=Employee+%23&employees%5B40351%5D%5BEmployee+%23%5D=358304&employees%5B40351%5D%5BFirst+name%5D=Sebastian&employees%5B40351%5D%5BLast+name%5D=Hickle&employees%5B40351%5D%5BJob+title%5D=&employees%5B40546%5D%5BchangedFields%5D%5B0%5D=First+name&employees%5B40546%5D%5BEmployee+%23%5D=35188&employees%5B40546%5D%5BFirst+name%5D=Angelino&employees%5B40546%5D%5BLast+name%5D=Bergstrom&employees%5B40546%5D%5BJob+title%5D=Developer

Permissioned Webhook Shortcomings

  • Permission Changes: Changes to the API user's permissions can invalidate a Permissioned Webhook or prevent it from accessing certain fields.
  • User Deactivation: If the user account associated with a Permissioned Webhook's API key is deactivated (e.g., employee departure), the webhook will stop functioning.
  • There is also the situation to take into account when you lose access to specific users. This can happen for various reasons. If you need to verify who you still have access to you can make use of the datasets endpoint. In this example call, you will receive a list of all users who you currently have access to.
POST https://{{url}}/api/gateway.php/{{company}}/v1/datasets/employee?format=JSON
Content-Type: application/json
Authorization: Basic {{token}} _

{
    "fields": [
        "firstName",
        "lastName"
    ]
}