Overview

PaySimple can notify your system or a 3rd party system when an event happens via webhooks. Webhooks are sent with an HTTP post to a publicly accessible url you specify when creating a webhook subscription. You may create as many webhook subscriptions as you wish, and each subscription may subscribe to multiple event types.

Webhook messages are lightweight by design. If you need more context data, call API4 or API5 endpoints using the ids returned in the body.

Delivery

For a webhook message to be delivered successfully, the endpoint must respond with a 2XX status code (eg 200, 201, etc.) within 10 seconds. If a successful response is not received, PaySimple will attempt to resend the webhook once every hour for 72 hours. PaySimple recommends using secure SSL encrypted endpoints hosted on port 443 (https).

Message Consumption Best Practices

It is best to write your consumer in an idempotent manner, as messages may be delivered out of order. Webhook events may be delivered more than once. An event payload will always have a unique event_id, which can be used to prevent duplicates upon message consumption.

Webhook Subscription API

Authorization

All requests to the webhook subscription API must contain the API 5 Authorization header.

Base URL

All requests must be sent using a base URL of https://api.paysimple.com/

Webhook Subscription Object

PropertyTypeDescription
idstringUniquely identifies a webhook subscription
urlstringUrl of the endpoint PaySimple will POST the event message to
event_typesarray of stringsList of event types to be delivered to url
is_activebooleantrue indicates messages should be delivered

Create Webhook Subscription

To create a webhook subscription, call the following endpoint with the url to accept the message and the event types to be sent.

Request:
POST /ps/webhook/subscription
{
    "url" : "https://myserver.mydomain.com/api/webhook",
    "event_types" : [ "payment_created" ],
    "is_active": true
}

Response:
200 OK
{
    "data": {
        "id": "wh_5b45075d253baf7fa0e1b8ee"
    }
}

Update Webhook Subscription

Request:
PUT /ps/webhook/subscription/{id}
{
    "url" : "https://myserver.mydomain.com/api/webhook",
    "event_types" : [ "payment_created" ],
    "is_active": true
}

Response:
204 No Content

Get Webhook Subscription

Request:
GET /ps/webhook/subscription/{id}

Response:
200 OK
{
    "data": {
        "id": "5b45075d253baf7fa0e1b8ee",
        "url": "https://myserver.mydomain.com/api/webhook",
        "event_types": [
            "payment_created"
        ],
        "is_active": false
    }
}

Get All Webhook Subscriptions

Request:
GET /ps/webhook/subscriptions

Response:
200 OK
{
    "total_item_count": 4,
    "data": [
        {
            "id": "5be22135d080e311b073d880",
            "url": "https://myserver.mydomain.com/api/webhook",
            "event_types": [
                "payment_created"
            ],
            "is_active": true
        },
        {
            "id": "5be221ead080e311b073d881",
            "url": "https://myserver.mydomain2.com/api/webhook",
            "event_types": [
                "payment_created"
            ],
            "is_active": true
        }
    ]
}

Delete Webhook Subscription

Request:
/ps/webhook/subscription/{id}

Response:
204 No Content

Manually Resend Webhooks

Request:
PUT /ps/webhook/manually_resend_webhooks
{ 
  "ids": ["id_1", "id_2", "id_n"] 
}

Response:
204 No Content

Webhook Event Types

The following events can be configured for delivery to the url specified in the webhook subscription via an HTTP post.

Webhook Message Object

PropertyTypeDescription
event_typestringName of event
event_idstringUniquely identifies the event.
merchant_idintegerUnique id of PaySimple merchant associated with the event.
created_atdatetimeUTC date and time event was created in ISO-8601 format
dataobjectEvent message body
client_idstringDeprecated. Use merchant_id. Unique id of PaySimple merchant associated with the event.

Payment Events

Payment Event Properties

PropertyTypeDescription
payment_idintUniquely identifies the Payment associated with the event.
order_idstringUniquely identifies the Order associated with the event.
customer_idintegerUniquely identifies the Customer associated with the event.
account_idintegerUniquely identifies the Customer payment method associated with the event.
payment_statusstringIndicates the current state of the Payment object. Valid values: authorized,chargeback,failed,pending,posted,refund_settled,returned,reversed,reverse_n_s_f,reverse_posted,settled,voided. (see Payment Statuses
amountdecimalPayment amount in US dollars.
payment_typestringType of payment: credit_card or ach.
payment_tokenuuidId of one time use token submitted at checkout. Can be used to reference payment in an external system.

payment_created

Sent when a new payment is created successfully. Status will be Authorized for Credit Card payments and Posted for ACH payments. The event is not created when a check or cash transaction is made.

Payment Created Event Properties

PropertyTypeDescription
payment_sourcestringPaySimple module where payment originated. Valid values: process_one_time,recurring_payment,payment_plan,payment_store,buyer_portal,api3,api4,ios,android,batch_upload,online_store,subscription,virtual_terminal,payment_form_store,order_details,embeddable,ios_pos,android_pos.
estimated_deposit_datedateEstimated date the funds will be deposited in merchant's bank account.
{
  "event_type": "payment_created",
  "event_id": "evt_5b46372e3b63252f94fa2268",
  "merchant_id": 1225,
  "created_at": "2018-07-11T15:44:13.0523594Z",
  "data": {
    "payment_id": 29124495,
    "order_id": "odr_5b4625c73b6325b528e17739",
    "customer_id": 8047912,
    "account_id": 7319764,
    "payment_status": "authorized",
    "amount": 11.0,
    "payment_type": "credit_card",
    "payment_source": "subscription",
    "estimated_deposit_date": "2018-07-13T06:00:00Z",
    "payment_token": "4B776AC8-A566-4BF6-94B7-FC10584727B2"
  }
}

payment_failed

Sent when a payment fails due to a decline or other reason.

{
  "event_type": "payment_failed",
  "merchant_id": 1225,
  "event_id": "evt_5b2acc723b63251694fa9683",
  "created_at": "2018-06-20T21:51:46.3683368Z",
  "data": {
    "payment_id": 29124397,
    "order_id": "odr_5b2acc723b63251694fa9681",
    "customer_id": 8053900,
    "account_id": 7321631,
    "amount": 9999.01,
    "payment_type": "credit_card",
    "failure_code": "4005",
    "failure_reason": "Do Not Honor Try a different payment method.",
    "is_decline": true,
    "payment_token": "4B776AC8-A566-4BF6-94B7-FC10584727B2"
  }
}
PropertyTypeDescription
failure_codestringCode associated with failure (see [Payment Failure / Decline Codes])(ref:payment-failure-codes)
failure_reasonstringMessage associated with failure (see [Payment Failure / Decline Codes])(ref:payment-failure-codes)
is_declineboolIndicates if the payment request was declined or failed for another reason.

payment_submitted_for_settlement

Sent when a payment is submitted in a settlement batch to the payment processor.

PropertyTypeDescription
settlement_batch_idstringThe id of the batch that includes the settlement
estimated_deposit_datedatetimeThe date the payment is estimated to be deposited in the destination account
payment_idintUnique identifier for the payment
order_idstringUnique identifier for the order
payment_statusintCode linked to status of a payment. All codes are listed in the table below.
customer_idintUnique identifier for the customer
payment_tokenstringUnique token linked to the payment

Order Status Codes:

CodeDescription
-1No Payment Required
0Unknown
1Posted
2Settled
3Failed
4Intentionally omitted
5Voided
6Refunded
7Intentionally omitted
8Intentionally omitted
9Refund Posted
10Chargeback
11Intentionally omitted
12Authorized
13Returned
14Intentionally omitted
15Returned Non-Sufficient Funds
16Intentionally omitted
17Refund Settled
18Refund Scheduled
{
  "event_type": "payment_submitted_for_settlement",
  "event_id": "evt_5b2ac7e63b6325a85c23149d",
  "merchant_id": 1225,
  "created_at": "2018-06-20T21:32:22.6001792Z",
  "data": {
    "settlement_batch_id": "7207533",
    "estimated_deposit_date": "2018-06-22T06:00:00Z",
    "payment_id": 29124386,
    "order_id": "odr_5b2ac37e3b6325485045e437",
    "payment_status": 1,
    "customer_id": 8049543,
    "payment_token": "4B776AC8-A566-4BF6-94B7-FC10584727B2"
  }
}

payment_returned

Sent when an ACH payment is returned.

PropertyTypeDescription
settlement_codestringThe NACHA return code that indicates why the transaction was returned and not funded. See a full list here under the Transaction Return Codes section.
settlement_descriptionstringThe description field for the settlement code. See a full list here under the Transaction Return Codes section.
transaction_idstringThe id of the transaction returned upon creation
settlement_amountdecimalThe amount that was actually funded for the transaction. This will typically be the same as transaction_amount
transaction_amountdecimalThe amount that was authorized by the transaction
settlement_datedatetimeThe date and time the transaction was returned
transaction_datedatetimeThe date and time the transaction was created
{
  "event_type": "TransactionReturned",
  "merchant_id": 1225,
  "event_id": "evt_5b2ad06e3b63258604bf18fb",
  "created_at": "2018-06-22T22:08:20.5117408Z",
  "data": {
    "settlement_code": "R03",
    "settlement_description": "No Account",
    "transaction_id": "txn_5a79d4913b632554a83cc2e7",
    "settlement_amount": 10.00,
    "transaction_amount": 10.00,
    "settlement_date": "2018-06-22T22:08:20.5117408Z",
    "transaction_date": "2018-06-20T22:08:20.5117408Z"
   }
}

payment_settled

Sent when funds are expected to have reached the merchant's bank.

{
  "event_type": "payment_settled",
  "event_id": "evt_5b2ac7e83b6325a85c23149e",
  "merchant_id": 1225,
  "created_at": "2018-06-20T21:32:24.3265438Z"
  "data": {
    "payment_id": 29124386,
    "order_id": "odr_5b2ac37e3b6325485045e437",
    "payment_status": "settled",
    "customer_id": 8049543,
    "payment_token": "4B776AC8-A566-4BF6-94B7-FC10584727B2"
  }
}

payment_voided

Sent when payment is voided.

{
  "event_type": "payment_voided",
  "event_id": "evt_5b2ac7e83b6325a85c23149e",
  "merchant_id": 1225,
  "created_at": "2018-06-20T21:32:24.3265438Z"
  "data": {
    "payment_id": 29124386,
    "order_id": "odr_5b2ac37e3b6325485045e437",
    "payment_status": "voided",
    "customer_id": 8049543,
    "payment_token": "4B776AC8-A566-4BF6-94B7-FC10584727B2"
  }
}

payment_refunded

Sent when payment is refunded or a standalone credit card credit is issued. For standalone credit card credits, payment_id will be 0.

{
"event_type": "payment_refunded",
  "merchant_id": 1225,
  "event_id": "evt_5b2acc0d3b63251694fa9680",
  "created_at": "2018-06-20T21:50:05.8310192Z",
  "data": {
    "payment_id": 29124395,
    "refund_payment_id": 29124396,
    "order_id": "odr_5b2acb763b63251694fa967a",
    "customer_id": 8053900,
    "account_id": 7321631,
    "payment_status": "reverse_posted",
    "amount": 5.5,
    "payment_type": "credit_card",
    "estimated_deposit_date": "2018-06-22T06:00:00Z",
    "payment_token": "4B776AC8-A566-4BF6-94B7-FC10584727B2"
  } 
}

Customer Events

customer_created

Sent when a new customer record is created.

{
  "event_type": "customer_created",
  "event_id": "evt_5b2aca473b6325b3b4d22ed1",
  "merchant_id": 1225,
  "created_at": "2018-06-20T21:42:31.5412011Z",
  "data": {
    "customer_id": 8053900,
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]"
  }
}

customer_updated

Sent when a customer record details are modified. This event is not sent when payment methods are created or updated for a customer.

{
  "event_type": "customer_updated",
  "event_id": "evt_5b2aca473b6325b3b4d22ed1",
  "merchant_id": 1225,
  "created_at": "2018-06-20T21:42:31.5412011Z",
  "data": {
    "customer_id": 8053900,
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]"
  }
}

customer_deleted

Sent when a customer record is deleted.

{
  "event_type": "customer_deleted",
  "event_id": "evt_5b2aca473b6325b3b4d22ed1",
  "merchant_id": 1225,
  "created_at": "2018-06-20T21:42:31.5412011Z",
  "data": {
    "customer_id": 8053900
  }
}

Offering Events

offering_created

Sent when a new product or service is created in the catalog.

{
  "event_type": "offering_created",
  "merchant_id": 1225,
  "event_id": "evt_5b2ad1043b6325aa54da13af",
  "created_at": "2018-06-20T22:11:16.0994208Z",
  "data": {
    "offering_id": "5b2ad104253bb5aff8af67be"
  }
}

offering_updated

Sent when a product or service is modified in the catalog.

{
  "event_type": "offering_updated",
  "merchant_id": 1225,
  "event_id": "evt_5b2ad1043b6325aa54da13af",
  "created_at": "2018-06-20T22:11:16.0994208Z",
  "data": {
    "offering_id": "5b2ad104253bb5aff8af67be"
  }
}

offering_deleted

Sent when a product or service is removed from the catalog.

{
  "event_type": "offering_deleted",
  "merchant_id": 1225,
  "event_id": "evt_5b2ad1043b6325aa54da13af",
  "created_at": "2018-06-20T22:11:16.0994208Z",
  "data": {
    "offering_id": "5b2ad104253bb5aff8af67be"
  }
}

Webhook Verification

Each webhook request sent from PaySimple contains a "paysimple-hmac-sha256" field in the request header, which can be used to verify the message. To verify the message, a webhook recipient can calculate "paysimple-hmac-sha256" using the C# code below. The code requires two parameters: 1) the signature secret and 2) the webhook event request body. The Signature Secret is provided in the response to the request to create the webhook. If you do not have this saved, the signature secret can be obtained by sending a request to the Get Webhook Subscription endpoint. The webhook event request body is is the raw text of the body of the request message that is sent to your webhook consumer.

new HMACSHA256(Encoding.ASCII.GetBytes(signatureSecret))
    .ComputeHash(Encoding.ASCII.GetBytes(webhookEventRequestBody))
    .Aggregate("", (current, t) => current + t.ToString("X2"))

Once you have calculated the "paysimple-hmac-sha256" using the code above, simply compare it to the value of the "paysimple-hmac-sha256" from the webhook request header. If the values match, then the message has been verified.

📘

Troubleshooting Tip

If you consistently fail to verify webhook messages using the code above, be sure to check the webhook event request body for anything that does not match the format of a response as shown above. Occasionally, white space can be added on the consumer end that is different from the original message. In particular check for any white space added in dates before or after a dash ( '-' ) character or any white space before or after special characters.


Did this page help you?