Payment Request Events

Seven events cover the life of a payment request. They all carry the same payload shape, so one handler can serve all of them — switch on the event field to decide what to do.

Identifier Fires when
paymentRequestIssued A worker submits a payment request.
paymentRequestApproved The company approves it, or auto-approval applies.
paymentRequestRejected The company rejects it.
paymentRequestPaid The company pays it.
paymentRequestCancelled It is cancelled.
paymentRequestWorkerPaidOut The worker has been paid out.
paymentRequestRecruiterPaidOut The staffing agency has been paid out.

Webhook payload

{
    "event": "paymentRequestIssued",
    "data": {
        "paymentRequest": {},
        "worker": {}
    }
}

Event Identifier

The event field carries one of the seven identifiers above. It is the only part of the payload that differs between them.

paymentRequest

{
    "id": "QmlsbDoxMjM0",
    "hireId": "SGlyZToxNTY4NTA=",
    "contractId": "Q29udHJhY3Q6MTIzNA==",
    "companyId": "Q29tcGFueTo0MjA=",
    "workerId": "V29ya2VyOjIzNDU2",
    "recruiterId": null,
    "jobId": "Sm9iOjc5MTM=",
    "jobName": "Project Coordinator",
    "currency": "USD",
    "netAmount": 440000,
    "grossAmount": 550000,
    "taxAmount": 110000,
    "rate": 550,
    "rateType": "daily",
    "hours": null,
    "days": 8,
    "weeks": null,
    "comments": "August timesheet",
    "purchaseOrderNumber": "BA-1234-5678",
    "startDate": "2026-08-01",
    "endDate": "2026-08-31",
    "issuedAt": "2026-09-01 09:14:22",
    "approvedAt": "2026-09-02 11:03:10",
    "rejectedAt": null,
    "paidAt": null,
    "cancelledAt": null,
    "status": "approved",
    "workerPaidOutStatus": "unpaid",
    "recruiterPaidOutStatus": null,
    "owners": [
        { "name": "Alex Kim", "email": "[email protected]" }
    ]
}
Field Notes
id Global ID of the payment request.
hireId, contractId, companyId, workerId, jobId Global IDs for looking the related objects up through the GraphQL API.
recruiterId null unless a staffing agency is attributed to the hire.
netAmount, grossAmount, taxAmount Integers in minor units of currency.
rate, rateType The rate the request was calculated from.
hours, days, weeks Just the unit matching rateType is populated; the others are null.
startDate, endDate The period the request covers, YYYY-MM-DD.
issuedAt, approvedAt, rejectedAt, paidAt, cancelledAt Timestamps in 24-hour time (YYYY-MM-DD HH:mm:ss), null until the transition happens. approvedAt is also set by auto-approval.
status One of new, approved, due, reminded, paid, prepaid.
workerPaidOutStatus, recruiterPaidOutStatus paid, unpaid, or null when not applicable.
owners The hire’s owners, as name and email only.

Warning

status is the payment request’s own status and does not map one-to-one onto the event names. A request can be prepaid because the worker was paid early through factoring or payroll, without a paymentRequestPaid event having fired for the company. Read the field rather than inferring state from which event arrived. Both fields are also webhook-only vocabularies, despite having GraphQL namesakes: status shares only approved with the API’s PaymentRequestStatus, and the payout fields are paid/unpaid only — not the API’s PaymentRequest.workerPayoutStatus, which is a separate field also carrying prepaid, due and overdue.

worker

The worker object is the same shape used by the other webhook events:

{
    "id": "V29ya2VyOjIzNDU2",
    "name": "Peter Bishop",
    "firstName": "Peter",
    "lastName": "Bishop",
    "middleName": "",
    "email": "[email protected]",
    "phone": "+16955024",
    "location": {
        "name": "Home address",
        "address": "150 Maplewood Drive, Suite 200",
        "city": "Springfield",
        "zipcode": "62704",
        "country": "US",
        "county": "",
        "state": "IL"
    },
    "businessEntity": {
        "entity_type": "common_business",
        "label": "Bishop Ltd.",
        "company_no": "987654321",
        "company_name": "Bishop Ltd.",
        "tax_no": "ST-1234567890"
    }
}

Handling these events

  • Amounts are in minor units. Treat grossAmount: 550000 in USD as $5,500.00.
  • Use id as your idempotency key together with event, since the same payment request produces several events over its life.
  • The payload deliberately carries a minimum of information. For anything beyond these fields, call the GraphQL API with the IDs supplied. See Handle Webhooks.