Taking Bitcoin payments with Paydefy via API integration.
Available as a self coded option with the API endpoints below or a paid integration with your existing software that Paydefy can develop for you.
Once your store has been set up in the Payment Processing section of your Paydefy account, integrating Bitcoin payments with your shop via the API takes 5 steps:
- Creating an invoice for the payment amount
- Payment of the invoice
- A webhook notifying that a payment has taken place.
- Verifying the webhook by checking the invoice status on the server.
- Marking the payment Complete
API_Key
Paydefy supports authenticating and authorizing users through an API Key that is generated through the Paydefy account interface. Send the API Key as a header value to Authorization with the format: token {token}.
Use an API key to read store information with cURL:
STORE_ID=”yourStoreId”
curl -s \
-H “Content-Type: application/json” \
-H “Authorization: token $API_KEY” \
-X GET \
“$BTCPAY_INSTANCE/api/v1/stores/$STORE_ID”
Step 1.
Create a new invoice
path Parameters
| storeIdrequired | string (StoreId)Example: 9CiNzKoANXxmk5ayZngSXrHTiVvvgCrwrpFQd4m2K776The store ID |
Request Body schema: application/json
| *metadata | Buyer informations (object) or Product information (object) or Order information (object) or Payment request information (object) or Point of Sale (Cart view) (object) or Receipt information (object) (InvoiceMetadata)Additional information around the invoice that can be supplied. The mentioned properties are all optional and you can introduce any json format you wish. |
| **checkout | object NullableAdditional settings to customize the checkout flow |
| receipt | object NullableAdditional settings to customize the public receipt |
| amount | string <decimal> NullableThe amount of the invoice. If null or unspecified, the invoice will be a top-up invoice. (ie. The invoice will consider any payment as a full payment) |
| currency | string NullableThe currency of the invoice (if null, empty or unspecified, the currency will be the store’s settings default)’ |
| additionalSearchTerms | Array of strings NullableAdditional search term to help you find this invoice via text search |
*You can add any metadata you wish, but note that ‘orderId’ is quoted in your Paydefy transactions and statements.
**Checkout options:
| speedPolicy | string NullableEnum: “HighSpeed” “LowMediumSpeed” “LowSpeed” “MediumSpeed”This is a risk mitigation parameter for the merchant to configure how they want to fulfill orders depending on the number of block confirmations for the transaction made by the consumer on the selected cryptocurrency. “HighSpeed”: 0 confirmations (1 confirmation if RBF enabled in transaction) “MediumSpeed”: 1 confirmation “LowMediumSpeed”: 2 confirmations “LowSpeed”: 6 confirmations |
| paymentMethods | Array of strings NullableA specific set of payment methods to use for this invoice (ie. BTC, BTC-LightningNetwork). By default, select all payment methods enabled in the store. |
| defaultPaymentMethod | string NullableDefault payment type for the invoice (e.g., BTC, BTC-LightningNetwork). Default payment method set for the store is used if this parameter is not specified. |
| lazyPaymentMethods | boolean NullableIf true, payment methods are enabled individually upon user interaction in the invoice. Default to store’s settings’ |
| expirationMinutes | number <minutes> NullableThe number of minutes after which an invoice becomes expired. Defaults to the store’s settings. (The default store settings is 15) |
| monitoringMinutes | number <minutes> NullableThe number of minutes after an invoice expired after which we are still monitoring for incoming payments. Defaults to the store’s settings. (The default store settings is 1440, 1 day) |
| paymentTolerance | number <double> [ 0 .. 100 ] NullableDefault: 0A percentage determining whether to count the invoice as paid when the invoice is paid within the specified margin of error. Defaults to the store’s settings. (The default store settings is 0) |
| redirectURL | string NullableWhen the customer has paid the invoice, the URL where the customer will be redirected when clicking on the return to store button. You can use placeholders {InvoiceId} or {OrderId} in the URL, BTCPay Server will replace those with this invoice id or metadata.orderId respectively. |
| redirectAutomatically | boolean NullableWhen the customer has paid the invoice, and a redirectURL is set, the checkout is redirected to redirectURL automatically if redirectAutomatically is true. Defaults to the store’s settings. (The default store settings is false) |
| defaultLanguage | string NullableThe language code (eg. en-US, en, fr-FR…) of the language presented to your customer in the checkout page. BTCPay Server tries to match the best language available. If null or not set, will fallback on the store’s default language. |
Responses
200 Information about the new invoice
400 A list of errors that occurred when creating the invoice
403
POST /api/v1/stores/{storeId}/invoices
PAYLOAD
application/json
{
- “metadata”:
- {
- “orderId”: “pos-app_346KRC5BjXXXo8cRFKwTBmdR6ZJ4”,
- “orderUrl”: “https://localhost:14142/apps/346KRC5BjXXXo8cRFKwTBmdR6ZJ4/pos“,
- “itemDesc”: “Tea shop”,
- “posData”:
- {},
- “receiptData”:
- {}
- },
- “checkout”:
- {
- “speedPolicy”: “HighSpeed”,
- “paymentMethods”:
- [],
- “defaultPaymentMethod”: “BTC-CHAIN”,
- “lazyPaymentMethods”: true,
- “expirationMinutes”: 90,
- “monitoringMinutes”: 90,
- “paymentTolerance”: 0,
- “redirectURL”: “string”,
- “redirectAutomatically”: true,
- “defaultLanguage”: “string”
- },
- “receipt”:
- {
- “enabled”: true,
- “showQR”: null,
- “showPayments”: null
- },
- “amount”: “5.00”,
- “currency”: “USD”,
- “additionalSearchTerms”:
- [
- “string”
- ]
}
PHP EXAMPLE in worpdress:
$url = ‘https://paydefy.com/api/v1/stores/[StoreID]/invoices’;
$apiKey = ‘[APIKey]’;
$success_url = ‘[Success URL]’;
$body = json_encode([
‘amount’ => $amount,
‘currency’ => $currency,
‘metadata’ => [
‘orderId’ => $order_id
],
‘checkout’ => [
‘speedPolicy’ => ‘LowSpeed’,
‘paymentMethods’ => [‘BTC’, ‘BTC-LightningNetwork’],
‘redirectURL’=> $success_url
]
]);
$args = array(
‘method’ => ‘POST’,
‘headers’ => array(
‘Authorization’ => ‘token ‘ . $apiKey,
‘Content-Type’ => ‘application/json’,
),
‘body’ => $body
);
$response = wp_remote_post($url, $args);
$data = json_decode(wp_remote_retrieve_body($response), true);
NOTE: You can use the ‘CheckoutLink’ to redirect the payer to the Paydefy site to make payment or use an in-store modal where the payer will not leave your site.
To use the Modal:
Pull the js script from https://paydefy.co/modal/btcpay.js
Launch with the invoice ‘id’ of the invoice to pay (Received in the response of your create invoice request above. See the ‘Get Invoice’ response below for further info).
Example:
<script src=”https://paydefy.co/modal/btcpay.js”></script>
<script>
newWindow = window.btcpay.showInvoice(‘InvoiceID’);
</script>
STEP 2.
After a customer has paid the invoice a Webhook will be fired to the webhook endpoint url (set up in your Payment Processing Setup on your Paydefy account under “Site URL”). (My Profile -> Payment Processing -> Setup/Edit button.)
STEP 3.
WEBHOOK RETURN
Once the invoice has been paid, a webhook will fire and return to the URL you set up in your Paydefy Profile under payment processing. (Remember to set up a new webhook secret in Payment Processing to use the API. For a custom URL be sure to update the Webhook and URL at the same time.)
header Parameters
| BTCPay-Sigrequired | stringExample: sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9The HMAC of the body’s byte with the secret’s of the webhook. sha256=HMAC256(UTF8(webhook’s secret), body) |
Request Body schema: application/json
| deliveryId | stringThe delivery id of the webhook |
| webhookId | stringThe id of the webhook |
| originalDeliveryId | stringIf this delivery is a redelivery, the is the delivery id of the original delivery. |
| isRedelivery | booleanTrue if this delivery is a redelivery |
| type | stringThe type of this event, current available are InvoiceCreated, InvoiceReceivedPayment, InvoiceProcessing, InvoiceExpired, InvoiceSettled, InvoiceInvalid, and InvoicePaymentSettled. |
| timestamp | number <int32>The timestamp when this delivery has been created |
| storeId | stringThe store id of the invoice’s event |
| invoiceId | stringThe invoice id of the invoice’s event |
| metadata | objectUser-supplied metadata added to the invoice at the time of its creation |
| manuallyMarked | booleanWhether the invoice have been manually marked as confirmed |
| overPaid | booleanWhether this invoice has received more money than expected |
Responses
default Unexpected error
PAYLOAD:
application/json
{
- “deliveryId”: “string”,
- “webhookId”: “string”,
- “originalDeliveryId”: “string”,
- “isRedelivery”: true,
- “type”: “string”,
- “timestamp”: 1592312018,
- “storeId”: “9CiNzKoANXxmk5ayZngSXrHTiVvvgCrwrpFQd4m2K776”,
- “invoiceId”: “string”,
- “metadata”: { },
- “manuallyMarked”: true,
- “overPaid”: true
}
NOTE: type “InvoiceSettled” is for a complete and full payment and the purchase can be completed. Type “InvoicePaymentSettled” is when only partial payment of the invoice has been made and the invoice is not settled in full.
PHP Example:
$raw = file_get_contents(‘php://input’);
$hash = (function_exists(‘hash_hmac’) ? hash_hmac(‘sha256’, $raw, [YourSecretHash]) : ‘no hash mac function!!’);
// verify hmac256
$headers = getallheaders();
foreach ($headers as $key => $value) {
if (strtolower($key) === ‘btcpay-sig’) {
$sig = $value;
}
}
$prefix = ‘sha256=’;
$str = $sig;
if (substr($str, 0, strlen($prefix)) == $prefix) {
$header = substr($str, strlen($prefix));
}
//CHECK Hash MATCHES
if ($hash == $header) {
Hash matches sig and order can be processed further. (It is vital to do the next step for confirmation and confirm the invoice is settled on the server)
}
Once a webhook has been received it’s important to verify the webhook by fetching the invoice data and checking its type status as “InvoiceSettled”. Only then is it safe to process the payment as fully paid.
STEP 4.
Get Invoice:
path Parameters
| invoiceIdrequired | stringThe invoice ID |
| storeIdrequired | string (StoreId)Example: 9CiNzKoANXxmk5ayZngSXrHTiVvvgCrwrpFQd4m2K776The store ID |
Responses
200 specified invoice
403 If you are authenticated but forbidden to view the specified invoice
404 The key is not found for this invoice
GET/api/v1/stores/{storeId}/invoices/{invoiceId}
Response Samples:
application/json
{
- “metadata”:
- {
- “orderId”: “pos-app_346KRC5BjXXXo8cRFKwTBmdR6ZJ4”,
- “orderUrl”: “https://localhost:14142/apps/346KRC5BjXXXo8cRFKwTBmdR6ZJ4/pos“,
- “itemDesc”: “Tea shop”,
- “posData”:
- {},
- “receiptData”:
- {}
- },
- “checkout”:
- {
- “speedPolicy”: “HighSpeed”,
- “paymentMethods”:
- [],
- “defaultPaymentMethod”: “BTC-CHAIN”,
- “lazyPaymentMethods”: true,
- “expirationMinutes”: 90,
- “monitoringMinutes”: 90,
- “paymentTolerance”: 0,
- “redirectURL”: “string”,
- “redirectAutomatically”: true,
- “defaultLanguage”: “string”
- },
- “receipt”:
- {
- “enabled”: true,
- “showQR”: null,
- “showPayments”: null
- },
- “id”: “string”,
- “storeId”: “9CiNzKoANXxmk5ayZngSXrHTiVvvgCrwrpFQd4m2K776”,
- “amount”: “5.00”,
- “paidAmount”: “5.00”,
- “currency”: “USD”,
- “type”: “Standard”,
- “checkoutLink”: “string”,
- “createdTime”: 1592312018,
- “expirationTime”: 1592312018,
- “monitoringExpiration”: 1592312018,
- “status”: “Expired”,
- “additionalStatus”: “Invalid”,
- “availableStatusesForManualMarking”:
- [
- “Expired”
- ],
- “archived”: true
}
Step 5.
Once you’ve confirmed “paidAmount” correlated against the internal order amount of the purchase via order ID or other metadata, the payment can be confirmed and the order completed.
*You use the Paydefy API at your own risk and Paydefy will in no way be held responsible for the erroneous or incorrect use or application of the API.