SpankPay APIs
Purchase
A purchase is a request for a payment. When created with the Button API or the JavaScript API, the user will be presented with a payment form prompting them to send cryptocurrency equivalent in value to the requested amount. Once the cryptocurrency has been received, the callback
webhook will be called, and the Button/JavaScript onPurchaseComplete
callback called.
Attribute
Description
id
The purchase's ID (assigned by SpankPay)
timestamp
The timestamp the purchase was created (ISO 8601 format, assigned by SpankPay)
apiKey
The API key used to create this purchase.
amount
The amount of the purchase, in "currency". Must be positive and rounded to the appropriate number of decimal places for the purchase currency.
currency
acceptedCurrencies
Must be a subset of the API Key's list of accepted currencies.
Optional.
metadata
Arbitrary metadata provided by the caller, stored and returned along with the purchase. We suggest including the order or invoice number, and an opaque customer ID. Limited to 128kb of JSON data. Optional.
Input Currencies
The Input Currency for a Purchase is the currency used by the user to pay for the purchase.
Currently valid input currencies:
Currency
Description
BTC
Bitcoin
ETH
Ethereum
BOOTY
BOOTY Coin
DOGE
Doge Coin
LTC
Litecoin
Output Currencies
The Output Currency for a Purchase is the currency which will be displayed to the user, and the currency which will be credited to your account. For example, a US$10 Purchase will have "amount": "10.00"
and "currency": "USD"
. When paying, the user will be given the option to pay with (for example) 0.074 ETH or 0.0026 BTC.
Currently valid output currencies:
Currency
Description
USD
US Dollars
BTC
Bitcoin
ETH
Ethereum
Creating a Purchase with a Button
A SpankPay button is the simplest way to accept SpankPay on your site.
When the button is clicked, the user will be presented with the SpankPay purchase frame, and the data-on-payment
callback will be called once the payment is complete and your callback has accepted the payment.
See also:
Creating a Purchase with the SpankPay JavaScript API
For complete control over the user's SpankPay experience, the API can be called directly.
The SpankPay.showPurchase(...)
method can be used to show the SpankPay purchase frame.
See also:
Purchase Frame Events
Events can be handled either by passing a callback to SpankPay.showPurchase(...)
, or binding to the event on the returned frame object:
Event
Description
close
Triggered when the frame is closed.
stateChange
payment
Frame State
The purchase frame state, exposed through frame.state
and the stateChange
event, has the following fields:
Attribute
Description
isOpen
true
or false
, depending on whether or not the frame is showing.
status
The status
will be one of: "awaiting-payment"
, "confirming-payment"
, or "complete"
.
payment
payment
Event
payment
EventThe payment
event will be triggered when a payment has been received and the callback
url has accepted the payment.
The payment
argument will be a Payment object, and the status
should be checked to ensure the payment has succeeded. Note, however, that the payment will only fail if the callback
rejects the payment (see: Webhook Expected Response).
For example:
Payment
A payment is created when SpankPay receives a user's payment in response to a Purchase.
Attribute
Description
id
The payment's ID, assigned by SpankPay.
timestamp
The timestamp when the payment was first received. ISO 8601 format.
status
One of "pending"
, "failed"
, or "succeeded"
.
"pending"
if the payment is still being verified (either waiting for an onchain transaction, or waiting for result of the callback).
"failed"
if the webhook callback returns a failure, or if the user navigates away from the payment page before completing the payment.
"succeeded"
if the payment has been confirmed onchain and the callback has returned success.
purchaseId
The ID of the corresponding Purchase.
purchase
The corresponding Purchase object (see above)
amount
The Purchase amount
currency
The Purchase's currency
inputAmount
The amount of the input currency that was paid (ex, "0.6969").
inputCurrency
The input currency selected by the user (ex, "ETH").
inputTx
An object describing the input transaction
inputTx.hash
The transaction hash.
receipt
The result of the webhook callback.
receipt.type
Always "webhook"
receipt.url
The URL which was called
receipt.status
One of "pending"
, "failed"
, or "succeeded"
.
receipt.calledOn
The timestamp of the last call. ISO 8601 format.
receipt.responseStatus
The HTTP status code of the last request.
The request will be considered successful if the status code is 2XX
, permanently failed if it is 4XX
, and otherwise the callback will be retried.
A responseStatus
of 999
indicates a network or other non-HTTP error.
receipt.response
The content of the HTTP response.
A JSON object if the response has Content-Type: application/json
, and a string otherwise.
Truncated to 128kb.
The callback
URL is provided when the Purchase is created, and we recommend including some metadata in the URL which your application can use to credit the appropriate order.
For example, if you assign each order an ID, the callback
URL might be https://your-site.com/api/spankpay/callback?order-id=sc696969
.
Webhook Format
Webhook messages will take the following format:
The type
field will always be "payment"
, although there may be other types in the future. The rest of the body will be a Payment object.
Note: the Content-Type
will be text/plain
instead of application/json
as might be expected. This is to ensure that web frameworks like Express do not attempt to parse the request body as JSON, and instead make the raw string available to the request handler so it can more easy check the signature.
Expected Response
The webhook endpoint must return an HTTP 200 response with a JSON object containing { "received": true }
. Other metadata may optionally be included in the JSON object, and it will be returned verbatim in the Payment's receipt.response
field.
A payment will be considered failed if the response contains either { "received": false }
, or an HTTP status code of 4XX
. On a failed payment, the user will be refunded their cryptocurrency (less standard transaction fees) and the payment will be marked "failed"
.
If the webhook endpoint returns a non-200 response, or a body that does not contain { "received": true }
, the webhook will be retried according to the following rules:
10 times, each 30 seconds apart (ie, every 30 seconds for 5 minutes)
10 times, each 5 minutes apart (ie, every 5 minutes for 50 minutes)
10 times, each 60 minutes apart (ie, every 1 hour for 10 hours)
If all retries fail, the API key administrator will be notified. A webhook can be manually retried at any point through the administrative UI.
Testing Webhooks
The Webhook Test Page (not yet available) can be used to send simulated webhooks.
(this will be a page with inputs for URL, public key, secret key, various payment fields, and a button which - when clicked - will trigger a webhook call to the provided URL).
Note: the webhook test page can only be used with testing keys (ie, keys prefixed with "test_"), and all currencies will be "TEST-" currencies.
Additionally, we recommend that developers use ngrok to create a public URL which can route to their local development server. During development, your application can be configured to automatically query ngrok for the developer's current public URL:
Security
To verify that webhooks are authentically from SpankPay, the content can be verified using the X-SpankPay-Signature
header.
We strongly recommend validating webhook signatures, otherwise it could be possible for an attacker to create fake payment confirmations.
Validating Webhook Signatures
Preventing Replay Attacks
To ensure your application only processes each webhook once, we recommend using the signature as a nonce. For example:
Last updated