Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Webhook Design Draft

Will Ross edited this page Aug 22, 2017 · 8 revisions

Just as a meta note, the code blocks on this page are using Python syntax, not JSON. The webhook API will be using JSON, it was just a bit faster for me to write it up like this. I'm going to be going through and fixing up this page later (moving comments out of code blocks and into tables probably, JSON syntax), this is just to start getting some feedback if possible. Comments at #88.

Events

request_submit

Fired when a Request is submitted to a Division.Note that this will be fired multiple times if a Request is moved to a new Division. This is an attempt to ease the eventual transition when I work on separating Killmail info from Requests (see Github issue #46 for details).

Example

{
    # All hook payloads will have an 'event' data member with one of the event
    # types listed above.
    'event': 'request_submit',
    # As mentioned above, this API is a half-step towards separating a Killmail
    # data from Request data. This means there will be some differences from
    # the existing read-only API.
    'killmail': {
        'href': 'https://zkillboard.com/kill/39861569/', # The link to the
                                                         # killmail submitted.
        'pilot': {
            'id': 570140137,
            'name': 'Paxswill',
            'corporation': {
                'id': 1018389948,
                'name': 'Dreddit',
            },
            # For those Pilots without an alliance, this item will be null.
            'alliance': {
                'id': 498125261,
                'name': 'Test Alliance Please Ignore',
            },
        },
        'timestamp': '2014-07-02T19:26:00' # This is equivalent to the kill
                                           # timestamp in the old API.
        'location': {
            'system': {
                'id': 30001160,
                'name': 'WD-VTV',
            },
            'constellation': {
                'id': 20000169,
                'name': 'UX3-N2'
            },
            'region': {
                'id': 10000014
                'name': 'Catch',
            },
        },
        'ship': 'Guardian',
    },
    'id': 39861569, # This ID will maintain the same semantics of the current
                    # request ID, in that it is also the ID of the killmail.
    'href': 'http://example.com/requests/12345', # An absolute URL to this
                                                 # request in the app.
    'division': { # The division this hook is being fired for.
        'id': 1,
        'name': 'Example Division',
    },
    'timestamp': '2014-07-09T19:43:58.126158', # This is equivalent to the
                                               # submission timestamp in the
                                               # old API
    'user': {
        'id': 42,
        'name': 'paxswill',
        'notes': [
            # If a user has no notes about them, this array will be empty.
            {
                'id': 34
                'note': 'A note about the user.',
                'timestamp': '2016-04-30T21:17:35',
                'submitter': { # The person who made the note
                    'id': 42,
                    'name': 'paxswill',
                },
            },
        ],
    },
    'details': 'Some text here.',
}

Consumer Response

The consumer MAY respond to a request. Not sure how I'm going to do this (a new HTTP request? Response to the original request?).

request_submit_response = {
    # All of these members are optional.
    'payout': '20000000', # Sets the base payout for the request
    'actions': [ # These actions are added in order.
        {
            'type': 'comment', # Required. One of 'approved', 'rejected',
                               # 'incomplete', 'evaluating',
                               # 'comment', or 'paid'. This must be a valid
                               # status for the request to move to (see
                               # documentation for the state diagram).
            'note': '', # Optional. If omitted, the default value is the empty
            # string.
        },
    ],
    'modifiers': [ # Order is irrelevant for modifiers, but they will probably
        # be added in order (this is an implementation detail, and
        # not guaranteed!).
        {
            'type': 'absolute', # Required. One of 'absolute' or 'relative'.
            'value': '5000000', # Required. If type is 'absolute', the amount
                                # to add to the base payout. For penalties, use
                                # a negative value. This value MAY be a String
                                # or a Number. String is recommended for
                                # absolute modifiers, as the app
                                # converts this value to a fixed point number.
            'note': '', # Optional. If omitted, the default value is the empty
            # string.
        },
    ],
}

action_add

Fired when an Action is added to a Request. Actions are things that change a Request's status, in addition to comments.

Example

action_add_hook = {
    'event': 'action_add',
    'action': { # The action that triggered this hook
        'user': {
            'id': 42,
            'name': 'paxswill',
        },
        'type': 'comment',
        'note': '', # May be empty, may have text.
                    # NOTE: should this be nullable?
        'timestamp': '2015-07-02T19:47:00'
    },
    'request': { 
        'killmail': {
            'href': 'https://zkillboard.com/kill/39861569/',
            'pilot': {
                'id': 570140137,
                'name': 'Paxswill',
                'corporation': {
                    'id': 1018389948,
                    'name': 'Dreddit',
                },
                'alliance': {
                    'id': 498125261,
                    'name': 'Test Alliance Please Ignore',
                },
            },
            'timestamp': '2014-07-02T19:26:00',
            'location': {
                'system': {
                    'id': 30001160,
                    'name': 'WD-VTV',
                },
                'constellation': {
                    'id': 20000169,
                    'name': 'UX3-N2'
                },
                'region': {
                    'id': 10000014
                    'name': 'Catch',
                },
            },
            'ship': 'Guardian',
        },
        'id': 39861569,
        'href': 'http://example.com/requests/12345',
        'division': {
            'id': 1,
            'name': 'Example Division',
        },
        'timestamp': '2014-07-09T19:43:58.126158',
        'user': {
            'id': 42,
            'name': 'paxswill',
            'notes': [
                {
                    'note': 'A note about the user.',
                    'timestamp': '2016-04-30T21:17:35',
                    'submitter': {
                        'id': 42,
                        'name': 'paxswill',
                    },
                },
            ],
        },
        'details': 'Some text here.',
        'actions': [
            # The action that triggered this hook /will/ be present in the
            # actions array. It /might not/ be the first (most recent) item in
            # the array.
            {
                'user': {
                    'id': 42,
                    'name': 'paxswill',
                },
                'type': 'comment',
                'note': '', # May be empty, may have text.
                # NOTE: should this be nullable?
                'timestamp': '2015-07-02T19:47:00'
                'id': 230,
            }
        ],
        'modifiers': [
            {
                'type': 'absolute', # One of 'absolute' or 'relative'.
                'value': '-5000000', # Absolute modifiers are given as strings
                                     # to avoid floating point errors.
                                     # Penalties have negative values (leading
                                     # negative sign), bonuses are positive (no
                                     # leading sign).
                'note': '',
                'timestamp':'2015-07-02T19:47:00',
                'id': 543, # The ID number of the modifier.
                'void': null, # If a modifier has not been voided (i.e.: it is
                              # still active), this member will be null.
            },
            {
                'type': 'relative',
                'value': 0.1, # Relative modifiers are given as double
                              # precision floating point numbers representing a
                              # percentage bonus or penalty (using the same
                              # logic as absolute modifiers: positive is bonus,
                              # negative is penalty).
                'note': 'Happy little bonus',
                'timestamp': '2010-12-24T12:24:10',
                'id': 9001,
                # If the modifier has been voided, instead of None, the value
                # will be similar to this:
                'void': {
                    'timestamp': '2014-07-02T19:26:00', # When the modifier was
                                                        # voided.
                    'user': { # The user that voided this modifier
                        'id': 42,
                        'name': 'paxswill',
                    },
                },
            },
        }

        ],
        'base_payout': '42000000',
        'payout': '37000000',
    },
}

Consumer Response

Identical to the request_submit response with the exception that if a consumer's response includes an actions member, that consumer will not receive an event notification for those action(s) when they are added.

status_change

Convenience event for when an API consumer doesn't need all of the information of the action_add event. This event type does not fire when a comment is added to a Request.

Example

status_change_hook = {
    'event': 'status_change',
    'href': 'http://example.com/requests/123456789',
    'old_status': 'evaluating',
    'new_status': 'approved',
    'note': '', # Like the action.note item above, might be nullable.
    'timestamp': '2015-07-02T19:47:00'
    'id': 765, # The ID of the Action that changed the status.
    'user': {
        'id': 42,
        'name': 'paxswill',
    },
}

Consumer Response

The convenience hooks will not be able to respond. If a consumer wants to do that, they'll have to use the action_add hook. Do note that read-only access will be available (somehow) to consumers via the link in the href member.

comment_add

Counterpart to the status event type. Will only fire when a comment is added to a Request.

Example

comment_add_hook = {
    'event': 'comment_add',
    'href': 'http://example.com/requests/123456789',
    'note': 'Hopefully there\'s text here', # being a comment and all...
    'timestamp': '2015-07-02T19:47:00',
    'id': 325, # The ID of the Action, if you need to look it up later.
    'user': {
        'id': 42,
        'name': 'paxswill',
    },
}

Consumer Response

As mentioned above, the convenience hooks will not be able to respond.

payout_change

Fired when the base payout of a Request is changed.

Example

payout_change_hook = {
    'event': 'payout_change',
    # Note, that even though the base and computed payouts are included for
    # both the old and new values, this hook is only fired when the base payout
    # changes. For when the computed payout changes, look at the
    # modifier_change event.
    'old_payout': {
        'base_payout': '42000000', # Again, note that this API will be emitting
                                   # the payout values and absolute modifiers
                                   # as strings to avoid running into floating
                                   # point issues.
        'payout': '37000000',
    },
    'new_payout': {
        'base_payout': '40000000',
        'payout': '35000000',
    }
    'user': {
        # While right now the user that changed a payout is not surfaced in the
        # app (nor is it recorded) this might change in the future.
        'id': 42,
        'name': 'paxswill',
    },
    'request': action_add_hook['request'],
}

Consumer Response

Identical to the request_submit response with the exception that if a consumer's response includes a payout member, that consumer will not receive an event notification for that payout change.

modifier_change

Fired when a modifier is added to a Request or voided.

Example

modifier_change_hook = {
    'event': 'modifier_change',
    'modifier': { # The modifier that has been added or voided
        # For details on these fields, see action_add_hook.request.modifiers
        'type': 'relative',
        'value': -0.5, # Relative modifiers are specified as a percentage in
                         # a double precision floating point number.
        'note': '', # Again, might be null, might be an empty string. Not sure
                    # yet.
        'timestamp': '2014-07-02T19:26:00', # When the modifier was added.
        'id': 235, # This ID is global across the app, not by request.
        'void': None,
        # If the modifier has been voided, instead of None, the value will be
        # similar to this:
        'void': {
            'timestamp': '2014-07-02T19:26:00', # When the modifier was voided.
            'user': { # The user that voided this modifier
                'id': 42,
                'name': 'paxswill',
            },
        }
    },
    'user': {
        'id': 42,
        'name': 'paxswill',
    }
    'request': action_add_hook['request'],
}

Consumer Response

Identical to the request_submit response with the exception that if a consumer's response includes a modifiers member, that consumer will not receive event notifications for those modifiers.

note_add

Fired when a Note is added to a User.

Example

note_add_hook = {
    'event': 'note_add',
    'note': ('The text of the note. If there are embedded links, they will not'
             ' be marked up in any way. This includes the automatic '
             'linkification of things in the form #1234567 that normally links'
             ' to the request of that number.'),
    'id': 39, # The note's ID number
    'timestamp':'2016-05-30T21:17:35' 
    'submitter': { # The person who's adding the note.
        'id': 42,
        'name': 'paxswill',
    },
    'user': { # The user the note is being added to.
        'id': 42,
        'name': 'Paxswill',
        'notes': [
            {
                'id': 34
                'note': 'A note about the user.',
                'timestamp': '2016-04-30T21:17:35',
                'submitter': {
                    'id': 40,
                    'name': 'Kalrogin Kerona',
                },
            },
            # The information about the newly added note will be duplicated in
            # this array.
            {
                'id': 39,
                'note': 'The same text as the top-level note member',
                'timestamp': '2016-05-30T21:17:35',
                'submitter': {
                    'id': 42,
                    'name': 'paxswill',
                },
            },
        ],
    },
}

Consumer Response

No responses accepted.

role_change

Fired when a Permission is added to or removed to from a Division.

Example

role_change_hook = {
    'event': 'role_change',
    'role': {
        'entity': { # The User or Group that that is being added/removed
            'type': 'group', # Will be either 'user' or 'group'
            'name': 'Test Alliance', # The name of the User or Group
            'id': 21,
            # Also note, the number of members in a Group will not be exposed
            # via this API.
        },
        'permission': 'submit', # Will be one of 'submit', 'review', 'pay',
                                # 'audit' or 'admin'.
    },
    'action': 'add', # Will be one of 'add' or 'remove'
    'user': { # The user who added or removed the role in question. Like the
              # payout_change event, this data is not logged within the app.
        'id': 42,
        'name': 'paxswill',
    },
    # No timestamp, as role changes are not logged within the app. If the
    # consumer needs that sort of record keeping, they will need to do it
    # themselves (which is why this hook is here).
}

Consumer Response

No responses accepted.

login

Fired when a User logs in. The intent of this hook is to allow for customized logging setups.

Example

login_hook = {
    'event': 'login',
    'user': {
        'id': 42,
        'name': 'paxswill',
        'method': 'Test OAuth', # Note: this will probably be the only place
                                # the authentication method the user uses is
                                # mentioned in the API. For other resources, I
                                # do not think it's relevant information.
        'new': false, # Wether this is the first time the user has logged in.
    },
    'source_ip': '123.45.67.89', # The IP address (v4 or v6) the user signs in
                                 # from. Not sure if I'll keep this data in or
                                 # not.
}

Consumer Response

This will be a special API, probably enabled by a special app configuration option. Even then, this is still up in the air.

login_response = {
    'divisions': [ # Optional. Divisions to create.
        {
            'name': 'Clever Division Name',
            'roles': [
                {
                    'entity': 14, # The ID of a User or Group to grant this
                                  # permission to.
                    'permission': 'submit', # Must be one of 'submit',
                                            # 'review', 'pay', 'audit' or
                                            # 'admin'.
                },
            ],
        },
    ],
    'roles': [ # Optional. Roles to grant in existing divisions.
        {
            'division': 1, # The ID of a division to grant this permission in.
            'entity': 14, # The ID of a User or Group to grant this
                          # permission to.
            'permission': 'submit', # Must be one of 'submit',
                                    # 'review', 'pay', 'audit' or
                                    # 'admin'.
        },

    ],
}

division_add

Fired when a Division is created.

Example

division_add_hook = {
    'event': 'division_add',
    'id': 2,
    'name': 'A Second Division',
    'user': { # This user will be a site-wide admin.
        'id': 42,
        'name': 'paxswill',
    },
}

Consumer Response

Again, not sure if this should even be included.

division_add_response = {
    'roles': [ # Optional. If present, must be an array.
        {
            'permission': 'submit', # Must be one of 'submit', 'review', 'pay',
                                    # 'audit' or 'admin'
            'entity': 40, # Must be the ID of a User or Group.
        },
    ],
}

Common Entities

Eve Object

Many items in Eve have both a name (which may or may not be localized in a language other than English) and an ID used by the various APIs CCP exposes. These items all share the same basic structure. English is used for the names of all items in this app.

Key Name Description
id The ID number for this item.
name The English name for this item.

Example

This example is using a solar system, but other items follow the sane pattern.

{
    "id": 30001160,
    "name": "WD-VTV"
}

Killmail

Killmails represent the information regarding the loss of a ship in Eve that a user is asking for compensation for.

Key Name Description
link The link the submitter provided for evaluation.
location A location object.
pilot A pilot object.
timestamp The date and time the loss happened within Eve. It will be in ISO 8601 format, without a timezone as everything in Eve is in UTC.
ship An Eve object for the ship (or other item) that generated a killmail in Eve.
id The reference ID for this killmail. It is the same ID that the Eve API uses to refer to this killmail.
href An absolute URL to the information from the app about this killmail.
user A user object.
divisions An array of division objects.
requests An object with the values being request objects and the keys the ID of the division for that request.

Example

{ 
    "killmail": {
        "href": "https://zkillboard.com/kill/39861569/",
        "pilot": {
            "id": 570140137,
            "name": "Paxswill",
            "corporation": {
                "id": 1018389948,
                "name": "Dreddit"
            },
            "alliance": {
                "id": 498125261,
                "name": "Test Alliance Please Ignore"
            }
        },
        "timestamp": "2014-07-02T19:26:00",
        "location": {
            "system": {
                "id": 30001160,
                "name": "WD-VTV"
            },
            "constellation": {
                "id": 20000169,
                "name": "UX3-N2"
            },
            "region": {
                "id": 10000014,
                "name": "Catch"
            }
        },
        "ship": "Guardian"
    },
    "id": 39861569,
    "href": "http://example.com/requests/12345",
    "division": {
        "id": 1,
        "name": "Example Division"
    },
    "timestamp": "2014-07-09T19:43:58.126158",
    "user": {
        "id": 42,
        "name": "paxswill",
        "notes": [
            {
                "note": "A note about the user.",
                "timestamp": "2016-04-30T21:17:35",
                "submitter": {
                    "id": 42,
                    "name": "paxswill"
                }
            }
        ]
    },
    "details": "Some text here.",
    "actions": [
        # The action that triggered this hook /will/ be present in the
        # actions array. It /might not/ be the first (most recent) item in
        # the array.
        {
            "user": {
                "id": 42,
                "name": "paxswill"
            },
            "type": "comment",
            "note": "", # May be empty, may have text.
            # NOTE: should this be nullable?
            "timestamp": "2015-07-02T19:47:00"
            "id": 230
        }
    ],
    "modifiers": [
        {
            "type": "absolute", # One of "absolute" or "relative".
            "value": "-5000000", # Absolute modifiers are given as strings
                                 # to avoid floating point errors.
                                 # Penalties have negative values (leading
                                 # negative sign), bonuses are positive (no
                                 # leading sign).
            "note": "",
            "timestamp":"2015-07-02T19:47:00",
            "id": 543, # The ID number of the modifier.
            "void": null # If a modifier has not been voided (i.e.: it is
                         # still active), this member will be null.
        },
        {
            "type": "relative",
            "value": 0.1, # Relative modifiers are given as double
                          # precision floating point numbers representing a
                          # percentage bonus or penalty (using the same
                          # logic as absolute modifiers: positive is bonus,
                          # negative is penalty).
            "note": "Happy little bonus",
            "timestamp": "2010-12-24T12:24:10",
            "id": 9001,
            # If the modifier has been voided, instead of None, the value
            # will be similar to this:
            "void": {
                "timestamp": "2014-07-02T19:26:00", # When the modifier was
                                                    # voided.
                "user": { # The user that voided this modifier
                    "id": 42,
                    "name": "paxswill"
                }
            }
        }
    ]
}

Location

A location within the Eve universe.

Key Name Description
system An object for a solar system.
constellation An object for the constellation system is in.
region An object for the region that constellation is in.

Each of these objects are described in the Eve items section.

Each of the values in this object are an object with a name and id key. name will be a string with the human-readable name of the item in question in English. id will be a number with the integer ID number used by Eve for that entity.

Example

{
    "system": {
        "id": 30001160,
        "name": "WD-VTV"
    },
    "constellation": {
        "id": 20000169,
        "name": "UX3-N2"
    },
    "region": {
        "id": 10000014,
        "name": "Catch"
    }
}

Pilot

An object describing a player's character within Eve.

Key Name Description
id The Eve ID number for this pilot.
name A string with the name of this pilot.
corporation An Eve object for the corporation this pilot is in.
alliance If the corporation is in an alliance, this value will be an Eve object for that alliance. Otherwise, it will be null.

Examples

A pilot in a coproation that is in an alliance:

{
    "id": 570140137,
    "name": "Paxswill",
    "corporation": {
        "id": 1018389948,
        "name": "Dreddit"
    },
    "alliance": {
        "id": 498125261,
        "name": "Test Alliance Please Ignore"
    }
}

A pilot in a corporation that is not in an alliance.

{
    "id": 93260529,
    "name": "Aimi Shihari",
    "corporation": {
        "id": 98261309,
        "name": "Such Corporation"
    },
    "alliance": null
}

User

A User is the person who owns the account that a pilot is associated with.

Key Name Description
id The unique ID number for this user. This value is internal to the app and has no meaning outside of it. It will not change once it has been assigned.
name In contrast to id, the display name of the user may change, and is not guaranteed to be unique.
notes An array of notes left about this user. If a user does not have any notes, the array will be empty.

User Notes

A User may have notes attached to them by other users with the reviewer, payer or admin permission. They can only be seen by users with the reviewer, payer, auditor or admin permission in the division that created them.

Key Name Description
note The text of the note.
timestamp The date and time this note was made.
submitter A user object (without a notes key and value) for the user that left this note.
division The division that this note was made from.

Example

{
    "id": 42,
    "name": "paxswill",
    "notes": [
        {
            "note": "A note about the user.",
            "timestamp": "2016-04-30T21:17:35",
            "submitter": {
                "id": 42,
                "name": "paxswill"
            }
        }
    ]
}

Division

A division is an administrative section that a user can submit requests for reimbursement too. Each division will have sets of people who will be able to submit requests within, review requests within the division to set a payout and approve or reject them, mark those same requests as paid, audit made requests in a division, or administer that division.

Key Name Description
id The unique ID number for this division. It is only unique within the set of all divisions in this app, and will not change.
name The name of this division. This is not guaranteed to not change in the future.
permissions A permissions object.
permissions An object with values being arrays of permission objects with the keys being one of "submit", "review", "pay", "audit", or "admin" corresponding to that role within the division.

Permissions

Keys are one of "submit", "review", "pay", "audit", and "admin" corresponding to that role within the division, values are an array of objects corresponding to users or groups that have that role. The objects will have name, id and type keys, type being one of the strings user or group and the other two keys being self explanatory.

Example

{
    "id": 1,
    "name": "Example Division",
    "permissions": {
        "submit": [
            {
                "id": 23,
                "name": "paxswill",
                "type": "user"
            },
            {
                "id": 39,
                "name": "Test Alliance",
                "type": "group"
            }
        ],
        "review": [],
        "pay": [],
        "audit": [],
        "admin": [
            {
                "id": 23,
                "name": "paxswill",
                "type": "user"
            }
        ]
    }
}

Request

A request made to a division to reimburse a user for the loss detailed in a killmail. the payout and base_payout keys are strings of a fixed-point number. Instead of using a native JSON number, we're using a string to try to maintain data integrity as much as possible and avoid floating-point issues.

Key Name Description
id A unique ID number for this specific request. Other requests for this killmail will have different IDs.
details A string containing additional information about the request.
timestamp The date and time a request was submitted/created.
division A division object without the permissions key.
actions An array of action objects, in reverse chronological order.
modifiers An aray of modifier objects, in chronological order.
base_payout The base payout amount for this request, as a string.
payout The total payout for this request, computed from the base payout and modifiers.
status The current status of this request. Will be one of evaluating, approved, incomplete, rejected or paid.

Example

{
    "details": "I literally forgot how to broadcast for armor.",
    "timestamp": "2014-07-09T19:43:58.126158",
    "id": 70,
    "division": {
        "id": 2,
        "name": "A Second Division"
    },
    "actions": [
        {
            "user": {
                "id": 42,
                "name": "paxswill"
            },
            "type": "comment",
            "note": "",
            "timestamp": "2015-07-02T19:47:00",
            "id": 230
        }
    ],
    "modifiers": [
        {
            "type": "absolute",
            "value": "-5000000",
            "note": "",
            "timestamp":"2015-07-02T19:47:00",
            "id": 543,
            "void": null
        },
        {
            "type": "relative",
            "value": 0.1,
            "note": "Happy little bonus",
            "timestamp": "2010-12-24T12:24:10",
            "id": 9001,
            "void": {
                "timestamp": "2014-07-02T19:26:00",
                "user": {
                    "id": 42,
                    "name": "paxswill"
                }
            }
        }
    ],
    "base_payout": "100000000",
    "payout": "142500000",
    "status": "approved"
}

Action

Actions are the way reviewers and payers change the status of a request. THey are also the way users can add a comment to a request.

Key Name Description
user The user who created the action.
type A string of either comment, evaluating, approved, incomplete, rejected, or paid. When something other than comment, this action changes the request's status.
note A string containing additional information about this action.
timestamp The date and time this action was created.
id A unique ID number for this action.

Example

{
    "user": {
        "id": 42,
        "name": "paxswill"
    },
    "type": "comment",
    "note": "",
    "timestamp": "2015-07-02T19:47:00",
    "id": 230
}

Modifier

Modifiers provide a way for reviewers to change the base payout of a request, by either increasing or decreasing the final payout. There are two kinds of modifiers available; absolute and relative. Absolute modifiers change the final payout by a set amount that does not depend on the value of the base payout. Relative modifiers on the other hand modify the final payout as a percentage of the base payout. If a modifier has a positive value, it will increase the final payout, while negative values will decrease it.

Key Name Description
type A string of either absolute or relative
value For an absolute modifier, a string of a fixed-point number. For a relative modifier, a double precision floating point number representing a percentage.
note A string containing a note about this modifier. May be an empty string.
timestamp The date and time this modifier was initially created.
id A unique ID number for this modifier.
user A user object without the notes key for the user who added/created this modifier.
void Either null if this modifier has not been voided, or a void object

Void Object

If a modifier has been voided, it will have an object as the value for the void key.

Key Name Description
timestamp The date and time the modifier was voided.
user A user object without the notes key for the user who voided the modifier.

Examples

An absolute modifier that has not been voided.

{
    "type": "absolute",
    "value": "-5000000",
    "note": "",
    "timestamp":"2015-07-02T19:47:00",
    "id": 543,
    "user": {
        "id": 42,
        "name": "paxswill"
    },
    "void": null
}

A relative modifier that has been voided.

{
    "type": "relative",
    "value": 0.1,
    "note": "Happy little bonus",
    "timestamp": "2010-12-24T12:24:10",
    "id": 9001,
    "user": {
        "id": 22,
        "name": "Aimi Shihari"
    },
    "void": {
        "timestamp": "2014-07-02T19:26:00",
        "user": {
            "id": 42,
            "name": "paxswill"
        }
    }
}