Webhook

This explains how you can use the webhook to keep your surrounding systems up to date.

Save time and increase data quality by automating updates to any other system – a simple way to import and keep people synchronized between your organization in Huma and your other systems or services.

The formats can be subject to change.

Supported features

  • Employee profile events πŸ”—
    • Specific event for changing email used for login to a profile πŸ”—
    • Automated updates when users are added or removed
      Whenever a user is created or deleted in Huma, a message is automatically sent to the url registered.
    • Automatically receive real-time updates when a profile is changed in Huma
      Changes made in the supported profile fields (listed below) will be automatically sent as updates to the url registered.
    • Export current state of user profiles, including Custom Fields
      To initialise state for the system connecting by webhook, exporting will send updates for each employee with all current field values.
  • Team & Location events πŸ”—
    • Team & Location updates

      Updates are sent for the creation, update, or deletion of a Team or Location.

    • Membership changes
      Receive events whenever users are added to, or removed from a Team or Location
  • Absence events πŸ”—
    • Automated updates when absences are registered or removed
      Whenever a new absence is registered, or an existing one is removed, a message is automatically sent to the url registered
    • Receive real-time updates when an absence entry is reviewed, or otherwise edited
      Most commonly, a message will be sent when an absence request is accepted or rejected, but changing the requested dates, editing the explanatory note, or any other change will also cause a message to be sent.

Can I use webhooks for service "X"?

It is very common to have a "middle service" between the webhook and third party, that re-writes the format of the message so it is tailored to the receiver. Some of our customers let their IT-department make their own service to receive webhooks and send the message onwards to one or several of their systems, transformed to a format that those systems understand. Other customers outsource this to "middle service"-suppliers. For a general example, please check out this article.  

How to use the webhook

To access Integrations under System settings you'll need a System role with permissions to do Organization-wide settings. Read more here

To get started, go to System settings/Integrations/Webhooks and click connect, simply provide an url which can receive the requests the webhook will send. You can also register a client secret and/or an access token.

Both Access Token and Client Secret are optional to use.  They offer two different ways for the receiver to confirm that the sender is their actual Huma account. Whether this is necessary is up to you to decide.

  • If the client secret is set, each request will include a header [huma-hmac-sha256] with a hash of the json body, signed with the secret to verify the message.
  • If the access token is set, each request will include it as a standard bearer token.
All requests include a [huma-topic] header, as well as a json body containing a [topic] property. The value of header [huma-topic] and body property [topic] will be identical, and will be one of:

Changing a profile's main email, the topic will be:

  • user-email-update

Because the profile email is used for logging in to the service, there are extra steps when changing it, and the webhook event is sent as its own topic.

ℹ️ Note: a profile can have a private email address, which is treated as a normal field, since it does not affect authentication. Any changes to it will be sent in a users-update topic, see profile update event, and supported fields, below.

For profile data, the topic will be one of:

  • users-create
  • users-update
  • users-delete
  • users-export

For Team & Location events, the topic will be one of:

  • groups-create
  • groups-update
  • groups-delete
  • groups-export
  • groups-add-members
  • groups-remove-members

For absence data, the topic will be one of:

  • absence-create
  • absence-update
  • absence-delete
  • absence-export

     


 

Be aware, if a request is not handled within 1 second, it will time out, so it may be useful to persist received data and respond, then do any further work to the data in a separate process

 


 

Profile email change event πŸ”—

These events include a single object [user], which identifies the affected user. This object contains:

  • id
    • Always present
    • A unique identifier for the user
      • This value will remain unchanged over the user’s lifetime.
    • Value is a standard 128-bit UUID (see rfc4122)
  • oldEmail
    • Always present
    • The email that previously identified the profile
    • Value is a string, validated to be an email address
  • newEmail
    • Always present
    • The email that identifies the profile from now on
    • Value is a string, validated to be an email address
  • employmentId
    • Present if set, absent if the user does not have one
    • A unique identifier at the point where the request is sent: no two users can have the same employment ID
      • Note that a user’s employment ID can be changed, or removed, by a user with the appropriate permission, so a user is not guaranteed to have the same value in later requests.
    • Value is a string, no restriction other than uniqueness within the organization

Example:

{
"topic": "user-email-update",
"user": {
"id": "d96434d7-9506-4d5f-a969-7d1eea8bc3d6",
"oldEmail": "jesper@godmat.no",
"newEmail": "jesper.blom@godmat.no",
"employmentId": "1"
}
}

 

 


Profile events πŸ”—

All request bodies also include a [users] array, which contains an object for each affected user. These objects will always contain:

  • id
    • Always present
    • A unique identifier for the user
      • This value will remain unchanged over the user’s lifetime.
    • Value is a standard 128-bit UUID (see rfc4122)
  • email
    • Always present
    • A unique identifier at the point where the request is sent: no two users can have the same email
      • Note that a user’s email can be changed by a user with the appropriate permission (see , so a user is not guaranteed to have the same value in later requests.
    • Value is a string, validated to be an email address
  • employmentId
    • Present if set, absent if the user does not have one
    • A unique identifier at the point where the request is sent: no two users can have the same employment ID
      • Note that a user’s employment ID can be changed, or removed, by a user with the appropriate permission, so a user is not guaranteed to have the same value in later requests.
    • Value is a string, no restriction other than uniqueness within the organization
  • status
    • Always present
    • either ACTIVE or INACTIVE


Create

A user or users being created in your Huma account is sent as a [POST] request, with full profile objects for the created users in the [users] array.

For example:

{
"topic": "users-create",
"users": [
{
"id": "09d41e51-0963-4763-933b-8c9df093d653",
"status": "ACTIVE",
"givenName": "Ida",
"preferredName": null,
"familyName": "Fossdal",
"email": "ida.fossdal@godmat.no",
"privateEmail": null,
"phone": "+47 955 55 167",
"address": {
"line1": "Fossvegen 82",
"line2": null,
"postalCode": "1823",
"city": "Bergen",
"country": "NO"
},
"birthDate": "1993-07-29",
"nationality": null,
"dietaryRequirements": null,
"funfacts": null,
"interests": null,
"bankAccount": {
"type": "national",
"number": "12345678903",
"country": ""
},
"gender": "Female",
"civilStatus": null,
"employmentId": "1",
"firstDayOfWork": "2001-09-14",
"employmentStartDate": "2001-09-14",
"lastDayOfWork": null,
"employmentEndDate": null,
"terminationNoticeDate": null,
"terminationDate": null,,
"employmentType": "Permanent",
"employmentPercentage": 100
"jobTitle": "CEO",
"jobDescription": "Make the decisions",
"identifications": null,
"salary": {
"periodUnit": "yearly",
"amount": 950000,
"currency": "NOK",
"note": null
},
"supervisor": null
},
{
"id": "d96434d7-9506-4d5f-a969-7d1eea8bc3d6",
"givenName": "Jesper",
"preferredName": null,
"familyName": "Blom",
"email": "jesper.blom@godmat.no",
"privateEmail": null,
"phone": "+46 7555512",
"address": {
"line1": null,
"line2": null,
"postalCode": "520 43",
"city": "Stockholm",
"country": "SE"
},
"birthDate": "1989-09-08",
"nationality": null,
"dietaryRequirements": null,
"funfacts": null,
"interests": null,
"bankAccount": null,
"gender": "Male",
"employmentId": "31",
"employmentStartDate": "2019-01-01",
"firstDayOfWork": "2019-01-01",
"lastDayOfWork": null,
"employmentEndDate": null,
"terminationNoticeDate": null,
"terminationDate": null,,
"employmentType": "Permanent",
"employmentPercentage": 100
"jobTitle": null,
"jobDescription": null,
"identifications": null,
"salary": {
"periodUnit": "yearly",
"amount": 700000,
"currency": "SEK",
"note": null
},
"supervisor":{
"id": "09d41e51-0963-4763-933b-8c9df093d653",
"email": "ida.fossdal@godmat.no"
}
}
]
}

Delete

A user or users being deleted in your Huma account is sent as a [DELETE] request, with the [users] object(s) containing only identifiers.

For example:

{
"topic": "users-delete",
"users": [
{
"id": "d96434d7-9506-4d5f-a969-7d1eea8bc3d6",
"email": "jesper.blom@godmat.no",
"employmentId": "1",
"status": "INACTIVE"
}
]
}

 

Update πŸ”—

A regular update is sent as a [PATCH] request, with the [users] object(s) containing only identifiers and the actually changed field(s).

For example, an employee changing their bank details to use IBAN:

{
"users": [
{
"id": "d96434d7-9506-4d5f-a969-7d1eea8bc3d6",
"email": "jesper.blom@godmat.no",
"employmentId": "31",
"status": "INACTIVE",
"bankAccount": {
"type": "international",
"iban": "FR7630006000011234567890189",
"bic": "AGRIFRPP"
}
}
],
"topic": "users-update"
}

Export πŸ”—

An export is sent as one or more POST request(s), each detailing the full state of all fields supported by the webhook for all users, including empty values for fields that have not been set. Each request details up to 50 profiles, so if your organization has more than 50 users, the export will be sent as multiple requests. E.g. an export from an organizations with 132 users would receive three requests, the first two with 50 user objects each, followed by a final request with 32 user objects.

For example:

{
    "topic": "users-export",
    "users": [
        {
            "id": "c2c8d497-352a-4c21-bf7c-aefbaec37717",
            "status": "ACTIVE",
            "givenName": "Patrick",
            "preferredName": null,
            "familyName": "Remen",
            "email": "patrick.remen@godmat.no", 
            "privateEmail": null,
            "phone": "+46 7455564",
            "address": {
                "line1": null,
                "line2": null,
                "postalCode": "464 95",
                "city": "Stockholm",
                "country": "SE"
            },
            "birthDate": "1987-02-13",
            "nationality": null,
            "dietaryRequirements": null,
            "funfacts": null,
            "interests": null,
            "bankAccount": null,
            "gender": "Male",
            "civilStatus": null,
            "employmentId": "30",
            "firstDayOfWork": "2012-03-13",
            "employmentStartDate": "2012-03-13",
            "lastDayOfWork": null,
            "employmentEndDate": null,
            "terminationNoticeDate": null,
            "terminationDate": null,
            "employmentType": "Permanent",
            "employmentPercentage": 100,
            "jobTitle": null,
            "jobDescription": null,
            "identifications": null,
            "salary": {
                "periodUnit": "yearly",
                "amount": 550000,
                "currency": "NOK",
                "note": null
            },
            "supervisor":{
                "id": "09d41e51-0963-4763-933b-8c9df093d653",
                "email": "ida.fossdal@godmat.no"
            }
        },
        {
            "id": "12b87a11-7b5a-4c77-bef2-f46522d99e1c",
            "givenName": "Laila",
            "preferredName": null,
            "familyName": "StΓΈa",
            "email": "laila.stoa@godmat.no",
            "privateEmail": null,
            "phone": "+47 455 53 217",
            "address": {
                "line1": "Kleivbakken 21",
                "line2": null,
                "postalCode": "2412",
                "city": "Bergen",
                "country": "NO"
            },
            "birthDate": "1981-08-04",
            "nationality": null,
            "dietaryRequirements": null,
            "funfacts": null,
            "interests": null,
            "bankAccount": {
                "type": "national",
                "number": "12345678902",
                "country": "NO"
            },
            "gender": "Female",
            "employmentId": "2",
            "employmentStartDate": "1999-05-18",
            "firstDayOfWork": "1999-05-18",
            "lastDayOfWork": null,
            "employmentEndDate": null,
            "terminationNoticeDate": null,
            "terminationDate": null,
            "employmentType": "Permanent",
            "employmentPercentage": 60,
            "jobTitle": null,
            "jobDescription": null,
            "identifications": null,
            "salary": {
                "periodUnit": "yearly",
                "amount": 500000,
                "currency": "NOK",
                "note": null
            },
            "supervisor":{
                "id": "09d41e51-0963-4763-933b-8c9df093d653",
                "email": "ida.fossdal@godmat.no"
            }
        },
        {
            "id": "d96434d7-9506-4d5f-a969-7d1eea8bc3d6",
            "status": "ACTIVE",
            "givenName": "Jesper",
            "preferredName": null,
            "familyName": "Blom",
            "email": "jesper.blom@godmat.no", 
            "privateEmail": null,
            "phone": "+46 7555512",
            "address": {
                "line1": null,
                "line2": null,
                "postalCode": "520 43",
                "city": "Stockholm",
                "country": "SE"
            },
            "birthDate": "1989-09-08",
            "nationality": null,
            "dietaryRequirements": null,
            "funfacts": null,
            "interests": null,
            "bankAccount": {
                "type": "international",
                "iban": "FR7630006000011234567890189",
                "bic": "AGRIFRPP"
            },
            "gender": "Male",
            "civilStatus": null,
            "employmentId": "31",
            "firstDayOfWork": "2019-01-01",
            "employmentStartDate": "2019-01-01",
            "lastDayOfWork": null,
            "employmentEndDate": null,
            "terminationNoticeDate": null,
            "terminationDate": null,
            "employmentType": "Permanent",
            "employmentPercentage": 100,
            "jobTitle": null,
            "jobDescription": null,
            "identifications": null,
            "salary": {
                "periodUnit": "yearly",
                "amount": 700000,
                "currency": "SEK",
                "note": null
            },
            "supervisor":{
                "id": "09d41e51-0963-4763-933b-8c9df093d653",
                "email": "ida.fossdal@godmat.no"
            }
        }
    ]
}

Supported fields πŸ”—

These are the profile fields that the webhook will send updates about:

Field JSON key
Email address email β€” note that changes to a profile's main email is sent as a user-email-update event
Status status
Given name givenName
Family name familyName
Preferred name preferredName
Phone number phone
Private email privateEmail
Address address
Date of birth birthDate
Nationality nationality
Dietary restrictions dietaryRequirements
Fun facts funfacts
Interests interests β€”either null or an array of strings
Bank account number

bankAccount β€” either null or an object. The object contains the fields type, and two other fields, depending on the value of type.

If type is national, the other two fields are number, and country.

If type is international, the other two fields are iban and bic.

  • type β€” either national or international
  • number β€” present if type is national. A string containing an account number for national accounts.
  • country β€” present if type is national. A two-letter ISO 3166-1 alpha-2 country code.
  • iban β€” present if type is international.
  • bic β€” present if type is international.
Gender gender
Civil status civilStatus
Employment ID employmentId
Employment start date employmentStartDate
Probation end date probationEndDate
First day of work firstDayOfWork
Termination notice date terminationNoticeDate
Last day of work lastDayOfWork
Employment end date employmentEndDate
Employment type

employmentType β€” either null, if not set, or one of:

  • Permanent
  • Temporary
  • Casual
  • Trainee
  • Consultant
Employment percentage employmentPercentage
Job title jobTitle
Job description jobDescription
Identifications

identifications β€” either null or an array of identification objects. Each identification object contains the fields id, type, country, and value.

  • id β€” the Huma-internal ID for this object
  • type β€” the type of identification, one of:
    • national
    • passport
  • value β€” the identification code itself, e.g. a passport number for passport, or "personnummer" for a norwegian national (i.e. country value of NO)
  • country β€” the issuing country for the identification. A two-letter ISO 3166-1 alpha-2 country code.
Salary

salary β€” an object containing the fields, periodUnit, amount, currency, and optionally note.

  • periodUnit β€” One of hourly, weekly, monthly, or yearly
  • amount β€” A decimal number
  • currency β€” An ISO 4217 currency code
  • note β€” An optional field, containing free text
Supervisor

supervisor β€” either null or an object containing the fields id and email.

  • id β€” the supervisor's user ID
  • email β€” the supervisor's email address

Custom fields πŸ”—

Any custom fields your organization has defined will be included in update events when the custom field is the one being updated. They will also all be included in export events.

If an event includes any custom fields, the user profile object(s) will contain a field custom, which is an object with the the custom fields as keys and corresponding values. If the custom value is unset, it will be included as a null.

As an example, for an organization that has defined two custom fields: Shirt size and License plate. An export for a user with the value "XL" for "Shirt size" and "License plate" not set, would include the following:

"custom": {
    "shirtSize": "XL",
    "licensePlate": null
}

See custom fields for more detail on how field name is determined, and the kinds of values custom fields can contain.


 

Absence events πŸ”—

All absence event request bodies include an [absence] array, which contains an object for each affected absence entry. Each entry object will always contain all supported information for the entry.

 


 

Create

Absence entries being registered in your Huma account are sent as [POST] requests.

For example:

{
    "topic": "absence-create",
    "absence": [
        {
            "id": "45be6bce-88f5-4f67-a6de-cbd84df21e1e",
            "status": "pending",
            "type": {
                "name": "vacation"
            },
          "user": {
                "id": "c2c8d497-352a-4c21-bf7c-aefbaec37717",
                "email": "patrick.remen@godmat.no"
            },
            "startDate": "2022-10-24",
            "endDate": "2022-10-28",
            "workRelated": false,
            "note": null,
            "comment": null,
            "reviewedAt": null,
            "reviewedBy": null,
            "registeredAt": "2022-10-04T11:57:13.819Z",
            "registeredBy": {
                "id": "c2c8d497-352a-4c21-bf7c-aefbaec37717",
                "email": "patrick.remen@godmat.no"
            }
        }
    ]
}

Update

Absence entries being updated in your Huma account – whether it’s a reviewer changing the status, edit by a requesting employee, or changes made by a manager on behalf of an employee – are sent as [PATCH] requests.

For example:

{
    "topic": "absence-update",
    "absence": [
        {
            "id": "e9b5a57f-2f36-462e-aed2-19c6aa990fce",
            "status": "approved",
            "type": {
                "name": "vacation"
            },
            "user": {
                "id": "c2c8d497-352a-4c21-bf7c-aefbaec37717",
                "email": "patrick.remen@godmat.no"
            },
            "startDate": "2022-10-10",
            "endDate": "2022-10-14",
            "workRelated": false,
            "note": null,
            "comment": null,
            "reviewedAt": "2022-10-05T11:57:13.819Z",
            "reviewedBy": {
                "id": "d96434d7-9506-4d5f-a969-7d1eea8bc3d6",
                "email": "jesper.blom@godmat.no",
            },
            "registeredAt": "2022-10-04T11:51:08.962Z",
            "registeredBy": {
                "id": "c2c8d497-352a-4c21-bf7c-aefbaec37717",
                "email": "patrick.remen@godmat.no"
            }
        }
    ]
}

Delete

Absence entries being deleted in your Huma account are sent as [DELETE] requests. The absence objects only contain identifiers.

For example:

{
    "topic": "absence-delete",
    "absence": [
        {
            "id": "e9b5a57f-2f36-462e-aed2-19c6aa990fce"
        }
    ]
}

Supported fields πŸ”—

These are the absence fields that the webhook will send updates about:

Field JSON key
The entry's ID id
Status status - one of pending, approved, or rejected
Type

type - an object containing the field name, with the name of the absence type, one of:

  • vacation
  • selfCertifiedSick
  • sick
  • paidTimeOff
  • unpaidTimeOff
  • sickChild
  • parentalLeave
User user - an object containing the fields id and email, for the user the entry is in regard to
Start date startDate
End date endDate
grade grade - a decimal number, where , 1.0 is 100% absence, 0.5 is 50%, etc.
Work related workRelated
Notes added when the entry was registered note
Comment added when the entry was reviewed comment
The time of the entry's last review reviewedAt
The entry's reviewer reviewedBy - an object containing the fields id and email, for the last user who reviewed the entry
The time of the entry's registration registeredAt
The user who registered the entry registeredBy - an object containing the fields id and email, for the user who registered the entry

 


 

Team & Location events πŸ”—

All Team or Location event request bodies include a [groups] array, which contains an object for each affected Team or Location. Each group object will always contain a unique and unchanging [id] field, the group [name], and the group [type], which will be either [team] or [location].

 


 

Create

When a Team or Location is created, you will receive a [POST] request:

{
    "topic": "groups-create",
    "groups":
    [
        {
            "id": "<group ID>",
            "name": "<group name>",
            "type": "<team/location>",
            "description": "<optional group description>",
          "links": [
                "<link name>\n<link url>"
            ],
          "address": {
                "line1": "Example street 57",
                "line2": "<optional second line>",
                "postalCode": "9999",
                "city": "Demo city",
                "country": "Theoretia"
            },
          "members": [
                {
                    "id": "<user ID>",
                    "email": "<user email>"
                }
            ]
        }
    ]
}

Update

When the details of a Team or Location are changed, you will receive a [PUT] request:

{
  "topic": "groups-update",
    "groups":
    [
        {
            "id": "<group ID>",
            "name": "<group name>",
            "type": "<team/location>",
            "description": "<optional group description>",
          "links": [
                "<link name>\n<link url>"
            ],
          "address": {
                "line1": "Example street 57",
                "line2": "<optional second line>",
                "postalCode": "9999",
                "city": "Demo city",
                "country": "Theoretia"
            },
          "members": [
                {
                    "id": "<user ID>",
                    "email": "<user email>"
                }
            ]
        }
    ]
}

Delete

When a Team or Location is deleted, you will receive a [DELETE] request:

{
  "topic": "groups-delete",
    "groups":
    [
        {
            "id": "<group ID>",
            "name": "<group name>",
            "type": "<team/location>",
            "description": "<optional group description>",
          "links": [
                "<link name>\n<link url>"
            ],
          "address": {
                "line1": "Example street 57",
                "line2": "<optional second line>",
                "postalCode": "9999",
                "city": "Demo city",
                "country": "Theoretia"
            },
          "members": [
                {
                    "id": "<user ID>",
                    "email": "<user email>"
                }
            ]
        }
    ]
}

Add members

When new members are added to a Team or Location, you will receive a [PUT] request:

{
  "topic": "groups-add-members",
    "groups": [
        {
            "id": "<group ID>",
            "name": "<group name>",
            "type": "<team/location>",
          "members-added": [
                {
                    "id": "<user ID>",
                    "email": "<user email>"
                }
            ]
        }
    ]
}

Remove members

When members of a Team or Location are removed, you will receive a [PUT] request:

{
"topic": "groups-remove-members",
"groups": [
{
"id": "<group ID>",
"name": "<group name>",
"type": "<team/location>",
"members-removed": [
{
"id": "<user ID>",
"email": "<user email>"
}
]
}
]
}

 



Security & compliance

By connecting with webhooks, you authorize Huma to access your webhooks account as described in our Terms of Service under Third-Party Platforms.

The webhook and other integrations require a Business or Enterprise subscription