Introduction
Welcome to the SatoshiPay API! You can use this API to make digital goods like articles, images, videos and downloadable files available for purchase using the SatoshiPay widget. This documentation covers:
- Digital Goods API - Register and manage digital goods with SatoshiPay
- HTML Tags - How to embed digital goods into your website
- Retrieving Goods - How to deliver paid digital goods to your users
- Content Types - Complete list of supported content types
SatoshiPay and You
To understand how SatoshiPay works you need to know the following:
- You need to register your digital goods with SatoshiPay
- You need to embed the digital goods and the SatoshiPay widget into your website
- SatoshiPay handles the payments
- You need to deliver the digital goods to your users via HTTP
The following diagram illustrates how your website and SatoshiPay interact with each other:
The SatoshiPay backend manages a registry of your digital goods. This registry contains pricing and some meta information, but not the content itself. You can register and manage these goods using the Digital Goods API.
The goods can be embedded on your web page using HTML Tags with special data attributes. The location of the HTML tag determines the position of the digital good on the page, or if the good hasn't been paid yet, the position of its placeholder.
The special HTML tags are recognised by the SatoshiPay widget, which needs to be included on every page that contains digital goods for sale. When a user buys a digital good, the widget handles the payment process by communicating to the SatoshiPay backend using a WebSocket connection. After successful payment the widget receives a payment receipt, which in turn is used to fetch the content of the good from a special HTTP Endpoint provided by you (see Retrieving Goods).
The SatoshiPay Widget
Include SatoshiPay Widget
<script src="https://wallet.satoshipay.io/satoshipay.js"></script>
The SatoshiPay website widget floats at the bottom right of the page and looks like this:
The widget displays a user's current balance in lumens and, when clicked, a menu where a user can top-up, manage their wallet, and learn more about the tool.
The SatoshiPay widget can be included anywhere on any web page and will automatically transform SatoshiPay HTML Tags into digital goods. See it in action at the SatoshiPay website.
The widget performs the following tasks:
- Generate a Stellar wallet and keep it in the user's LocalStorage
- Communicate with SatoshiPay servers
- Control digital goods on the web page
- Interact with the user via menus and messages
Digital Goods API
Digital Goods API Endpoint
https://api.satoshipay.io/v2/
The Digital Goods API allows developers to interact with SatoshiPay using HTTP REST calls and JSON. Digital goods merchants communicate with the API in order to register individual goods for sale – either directly or through plugins and libraries provided by SatoshiPay or 3rd parties. The digital goods merchant hosts complementary HTTP Endpoints that deliver the goods to the user.
General
API Authentication
Basic Authentication
curl https://api.satoshipay.io/v2/goods/ \
-u <api-key>:<api-secret>
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/",
auth: {
user: "<api-key>",
password: "<api-secret>"
}
}, callback);
Every request to the API must be authenticated with your API credentials. These credentials can be obtained in the SatoshiPay Dashboard after creating an account. Before you can access your credentials, you need to set a Stellar address for payouts. Your API key and secret can then be found at Settings > API Access.
The API uses Basic Authentication, where the user name is your API key, and the password is your API secret.
The example uses Basic Authentication to receive the list of your goods. The result will be an empty array []
if you didn't add any goods yet.
If authorization fails, a JSON object with an error message will be returned as a response (along with the HTTP status 401
) .
Valid JSON
curl https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559 \
-X PATCH \
-u apikey:apisecret \
-H 'Content-Type: application/json' \
-d '{ "sharedSecret": "xyz" }'
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559",
auth: {
user: "apikey",
password: "apisecret"
},
method: "PATCH",
json: {
sharedSecret: "xyz"
}
}, callback);
All endpoints respond with JSON objects.
For POST
, PUT
or PATCH
requests, the request body needs to be valid JSON. Also make sure to include a Content-Type: application/json
header in your requests.
Errors
Example Error Object
{
"name": "unauthorized",
"message": "Unauthorized Request",
"statusCode": 401,
"errorCode": 401
}
If an error occurs while handling the request, a JSON error object will be returned along with a corresponding HTTP status code. The object contains status and error codes, the name of the error, as well as the error message.
Goods
The API resource goods
allows a merchant to manage their digital goods. A good in the API represents a merchant's digital good (e.g. news article, image, audio/video or file download) and holds all information needed for SatoshiPay to handle payments. This includes pricing information and other metadata, but not the content itself.
List Goods
Definition
GET https://api.satoshipay.io/v2/goods/
Example Request
curl https://api.satoshipay.io/v2/goods/ \
-u apikey:apisecret
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/",
auth: {
user: "apikey",
password: "apisecret"
},
json: true
}, callback);
Example Response
[
{
"id": "56c5a2a4f1cc5c0448c429f2",
"price": 100000000,
"asset": "XLM",
"sharedSecret": "n1hLnMiJwAwB",
"url": "https://example.info",
"title": "Tempora accusamus maxime similique veritatis magni."
},
{
"id": "56c5a2a52362b70448a589b4",
"price": 50000000,
"asset": "XLM",
"sharedSecret": "m1btHMWJ6O6g",
"url": "http://example.name",
"title": "Saepe voluptatibus tempore pariatur atque quia corrupti nisi dolores.",
"purchaseValidityPeriod": 86400000
}
]
GET goods
Get a list of all goods a merchant has created.
Response
Returns an array of 'good' objects. Every object has the following properties:
Property | Type | Description |
---|---|---|
id |
string | Unique identifier of the good. |
price |
integer | Gross price of good in stroops. One lumen is 10^7 (10,000,000) stroops. |
asset |
string | Asset of good's price. Only "XLM" is currently supported. |
sharedSecret |
string | Shared secret information which will be used to sign the paymentReceipt used to authenticate user during digital goods retrieval. |
url |
string | URL of the web page which contains the good. Used as a reference in the Dashboard. |
title |
string | Title of the good for reference in the provider dashboard. |
purchaseValidityPeriod |
string | Time until the good's payment expiry. |
Create a Good
Definition
POST https://api.satoshipay.io/v2/goods
Example Request
curl https://api.satoshipay.io/v2/goods/ \
-u apikey:apisecret \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"sharedSecret": "DLDwYsQGromi",
"price": 200000000,
"asset": "XLM",
"title": "Nihil placeat sapiente ut eaque assumenda et reprehenderit quos ab.",
"url": "http://example.org/post1",
"purchaseValidityPeriod": "1h"
}'
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/",
auth: {
user: "apikey",
password: "apisecret"
},
method: "POST",
json: {
"sharedSecret": "DLDwYsQGromi",
"price": 200000000,
"asset": "XLM",
"title": "Nihil placeat sapiente ut eaque assumenda et reprehenderit quos ab.",
"url": "http://example.org/post1",
"purchaseValidityPeriod": "1h"
}
}, callback);
Example Response
{
"id": "5b61b65c96fec50010512cf6",
"sharedSecret": "DLDwYsQGromi",
"asset": "XLM",
"price": 200000000,
"title": "Nihil placeat sapiente ut eaque assumenda et reprehenderit quos ab.",
"url": "http://example.org/post1",
"purchaseValidityPeriod": 3600000
}
POST goods
Create a new good.
Request
Provide a 'good' object with the following properties:
Property | Type | Required | Description |
---|---|---|---|
price |
integer | yes | Gross price of good in stroops. One lumen is 10^7 (10,000,000) stroops. |
asset |
string | yes | Asset of good's price. Only "XLM" is currently supported. |
sharedSecret |
string | yes | Shared secret information which will be used to sign the paymentReceipt used to authenticate user during digital goods retrieval. |
url |
string | yes | URL of the web page which contains the good. Used as a reference in the Dashboard. |
title |
string | yes | Title of the good for reference in the provider dashboard. |
purchaseValidityPeriod |
string | no | Time until the good's payment expiry. |
Response
As a confirmation, the handler returns the an object representing the good from the request, augmented by an id
property, which holds the ID that has been assigned to the good as a string.
Retrieve a Good
Definition
GET https://api.satoshipay.io/v2/goods/<id>
Example Request
curl https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559 \
-u apikey:apisecret
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559",
auth: {
user: "apikey",
password: "apisecret"
},
json: true
}, callback);
Example Response
{
"id": "558bcdbb1309c59725bdb559",
"sharedSecret": "m1btHMWJ6O6g",
"price": 50000000,
"asset": "XLM",
"title": "Saepe voluptatibus tempore pariatur atque quia corrupti nisi dolores.",
"url": "http://example.name",
"purchaseValidityPeriod": 60000
}
GET goods/<id>
Retrieve a specific good identified by <id>
. If no good with the given ID can be found, an error object with status code 404
is returned.
Request
Insert the ID of the good into the request URL.
Response
A 'good' object with the following properties:
Property | Type | Description |
---|---|---|
id |
string | Unique identifier of the good. |
price |
integer | Gross price of good in stroops. One lumen is 10^7 (10,000,000) stroops. |
asset |
string | Asset of good's price. Only "XLM" is supported. |
sharedSecret |
string | Shared secret information which will be used to sign the paymentReceipt used to authenticate user during digital goods retrieval. |
url |
string | URL of the web page which contains the good. Used as a reference in the Dashboard. |
title |
string | Title of the good for reference in the provider dashboard. |
purchaseValidityPeriod |
interger | Time in milliseconds until the good's payment expires. |
Replace a Good
Definition
PUT https://api.satoshipay.io/v2/goods/<id>
Example Request
curl https://api.satoshipay.io/v2/goods/56c5a91265e80b7c51afad23 \
-u apikey:apisecret \
-H 'Content-Type: application/json' \
-X PUT \
-d '{
"sharedSecret": "RLC43wvCcmcs",
"price": 200000000,
"asset": "XLM",
"title": "Veritatis impedit mollitia nam ipsum laudantium quam quidem.",
"url": "https://example.net",
"purchaseValidityPeriod": "60000"
}'
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559",
auth: {
user: "apikey",
password: "apisecret"
},
method: "PUT",
json: {
"sharedSecret": "RLC43wvCcmcs",
"price": 200000000,
"asset": "XLM",
"title": "Veritatis impedit mollitia nam ipsum laudantium quam quidem.",
"url": "https://example.net",
"purchaseValidityPeriod": "60000"
}
}, callback);
Example Response
{
"id": "5b61b76d66fec50010514cf7",
"sharedSecret": "RLC43wvCcmcs",
"asset": "XLM",
"price": 200000000,
"title": "Veritatis impedit mollitia nam ipsum laudantium quam quidem.",
"url": "https://example.net",
"purchaseValidityPeriod": 60000
}
PUT goods/<id>
Replace the good given by <id>
. If no good with the given ID exists, an error object with status code 404
will be returned.
Request
Insert the ID of the good that should be replaced into the request URL and provide a 'good' object that will replace the old good with the given id
. The object has the following properties:
Property | Type | Required | Description |
---|---|---|---|
price |
integer | yes | Gross price of good in stroops. One lumen is 10^7 (10,000,000) stroops. |
asset |
string | yes | Asset of good's price. Only "XLM" is currently supported. |
sharedSecret |
string | yes | Shared secret information which will be used to create paymentReceipt used to authenticate user during digital goods retrieval. |
url |
string | yes | URL of the web page which contains the good. Used as a reference in the Dashboard. |
title |
string | yes | Title of the good for reference in the provider dashboard. |
purchaseValidityPeriod |
string | no | Time until the good's payment expiry. |
Response
As a confirmation, the handler returns an object representing the good from the request, including the id
property with type string.
Update a Good
Definition
PATCH https://api.satoshipay.io/v2/goods/<id>
Example Request
curl https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559 \
-u apikey:apisecret \
-H 'Content-Type: application/json' \
-X PATCH \
-d '{
"url": "http://example.com/changed"
}'
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559",
auth: {
user: "apikey",
password: "apisecret"
},
method: "PATCH",
json: {
"url": "http://example.com/changed"
}
}, callback);
Example Response
{
"id": "56c5a82328383fe54f841a60",
"sharedSecret": "XyZtFohL7",
"price": 150000000,
"asset": "XLM",
"title": "Beatae ab autem delectus dolorem est fugiat.",
"url": "http://example.com/changed"
}
PATCH goods/<id>
Partially update a good, i.e. send only those properties that are to be updated.
Request
Insert the ID of the good that should be updated into the request URL and provide an 'update' object that has any subset of the following properties. The specified properties will then overwrite the properties of the good with the given id in the request URL.
Property | Type | Required | Description |
---|---|---|---|
price |
integer | no | Gross price of good in stroops. One lumen is 10^7 (10,000,000) stroops. |
asset |
string | yes | Asset of good's price. Only "XLM" is currently supported. |
sharedSecret |
string | no | Shared secret information which will be used to create paymentReceipt used to authenticate user during digital goods retrieval. |
url |
string | no | URL of the web page which contains the good. Used as a reference in the Dashboard. |
title |
string | no | Title of the good for reference in the provider dashboard. |
purchaseValidityPeriod |
string | no | Time until the good's payment expiry. |
Response
The updated 'good' object.
Delete a Good
Definition
DELETE https://api.satoshipay.io/v2/goods/<id>
Example Request
curl https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559 \
-u apikey:apisecret \
-X DELETE
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/goods/558bcdbb1309c59725bdb559",
auth: {
user: "apikey",
password: "apisecret"
},
method: "DELETE"
}, callback);
DELETE goods/<id>
Delete a good.
Request
Insert the ID of the good to be deleted into the request URL.
Batch Requests
Definition
POST https://api.satoshipay.io/v2/batch/
Example Request
curl https://api.satoshipay.io/v2/batch/ \
-u apikey:apisecret \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"requests": [
{
"method": "POST",
"path": "/goods",
"body": {
"sharedSecret": "NSKLDspUuo_V",
"price": 50000000,
"asset": "XLM",
"title": "Aliquam sit nisi quia ut rerum.",
"url": "https://example.com/post1"
}
},
{
"method": "POST",
"path": "/goods",
"body": {
"sharedSecret": "NSfg1elotk_R",
"price": 180000000,
"asset": "XLM",
"title": "Vitae facere ea totam hic",
"url": "https://example.com/post2"
}
}
]
}'
var request = require("request");
request({
url: "https://api.satoshipay.io/v2/batch/",
auth: {
user: "apikey",
password: "apisecret"
},
method: "POST",
json: {
"requests": [
{
"method": "POST",
"path": "/goods",
"body": {
"sharedSecret": "NSKLDspUuo_V",
"price": 50000000,
"asset": "XLM",
"title": "Aliquam sit nisi quia ut rerum.",
"url": "https://example.com/post1"
}
},
{
"method": "POST",
"path": "/goods",
"body": {
"sharedSecret": "NSfg1elotk_R",
"price": 180000000,
"asset": "XLM",
"title": "Vitae facere ea totam hic",
"url": "https://example.com/post2"
}
}
]
}
}, callback);
Example Response
{
"responses": [
{
"status": 200,
"body": {
"id": "56c59f4092d316b1419591eb",
"sharedSecret": "NSKLDspUuo_V",
"price": 50000000,
"asset": "XLM",
"title": "Aliquam sit nisi quia ut rerum.",
"url": "https://example.com/post1"
}
},
{
"status": 200,
"body": {
"id": "56c59f4092d316b1419591ec",
"sharedSecret": "NSfg1elotk_R",
"price": 180000000,
"asset": "XLM",
"title": "Vitae facere ea totam hic.",
"url": "https://example.com/post2"
}
}
]
}
POST batch
Execute a batch of requests at once.
Request
Provide an array of 'request' objects in the body. Each request object has the following properties:
Property | Type | Required | Description |
---|---|---|---|
method |
string | yes | The method of the query. Has to be one of POST, PUT, PATCH or DELETE. |
path |
string | yes | The path of the resource. For example: /goods/<id> |
body |
json value | depending on method |
JSON value that represents the body of the request. |
Response
Returns an array of 'response' objects that each correspond to the respective request from the request array. Each response object has the following properties:
Property | Type | Description |
---|---|---|
status |
integer | HTTP status code of the respective request. |
body |
json value | JSON value that represents the response body from the respective request. |
Payment Expiry
Digital goods can have a payment expiry. After a successful payment, a good will be in its paid state until the defined expiry time interval has passed, after which the payment will no longer be valid.
Setting Payment Expiry
During the registration of a good, the optional purchaseValidityPeriod
property can be set with an arbitrary, positive time period. The time format is translated by the "ms" NPM package, which converts various time formats to milliseconds. See examples below.
Examples:
Value | Milliseconds |
---|---|
"5s" |
5000 |
"60000" |
60000 |
"1m" |
60000 |
"2.5 hrs" |
9000000 |
"2 days" |
172800000 |
"1y" |
31557600000 |
HTML Tags
Digital goods can be included on a web page by defining special HTML tags, which will then be controlled by the SatoshiPay widget. Content types for text, images, audio files, videos and downloads are supported. Find a complete list of supported types in the reference section.
Before purchase, a digital good is represented on the merchant's website by a placeholder. These placeholders are injected by the SatoshiPay widget, which scans the current page for placeholder tags on initialization. The placeholder tags are identified by a CSS class name starting with satoshipay-placeholder
and contain details about the good they replace in their data
attributes (see the text tag example).
Goods placeholder:
The data attributes specify where the good can be downloaded from by the SatoshiPay client once the payment has been successfully completed, which specific type of good is displayed, and other content type specific properties like length or size. See below for a detailed description of the data attributes for different content types.
During page load placeholders will appear in a simplified form (grey boxes) to make them recognizable while the SatoshiPay widget is being initialized. Placeholder styling can not be modified by the surrounding website.
Text
Text Example
<div class="satoshipay-placeholder"
data-sp-type="text/html"
data-sp-src="/paid-content/1.html"
data-sp-id="558bcdbb1309c59725bdb559"
data-sp-length="800"
data-sp-currency="GBP"
></div>
This tag type represents text or HTML code that is loaded into the web page via an AJAX call after successful payment.
Data Attributes
Data Attribute | Required | Description |
---|---|---|
data-sp-type |
yes | Content type (MIME), must be either text/html or text/plain for this type of digital good. See supported types. |
data-sp-src |
yes | HTTP endpoint as absolute or relative URL, e.g. /paid-content/1.html . |
data-sp-id |
yes | Unique identifier for the good in SatoshiPay's registry. Consists of a hex string, e.g. 558bcdbb1309c59725bdb559 . |
data-sp-length |
no | Number of content characters (excluding HTML tags and other invisible characters), e.g. 800 . The length will be used to determine how much area the placeholder will cover. Default value: 500 . |
data-sp-currency |
no | The XLM price converted to US Dollars, Euro, or UK Pounds. Use currency code: 'USD', 'EUR', or 'GBP' |
Image
Image Example
<div class="satoshipay-placeholder-image"
data-sp-type="image/png"
data-sp-src="/paid-content/2.png"
data-sp-id="558bcdbb1309c59725bdb560"
data-sp-width="450"
data-sp-height="300"
data-sp-placeholder="/placeholders/2.png"
data-sp-currency="GBP"
></div>
This tag type represents an image that is loaded by injection of an img
tag after successful payment.
Data Attributes
Data Attribute | Required | Description |
---|---|---|
data-sp-type |
yes | Content type (MIME), must start with "image/" for this type of digital good, e.g. image/png . See supported types. |
data-sp-src |
yes | HTTP endpoint as absolute or relative URL, e.g. /paid-content/2.png . |
data-sp-id |
yes | Unique identifier for the good in SatoshiPay's registry. Consists of a hex string, e.g. 558bcdbb1309c59725bdb559 . |
data-sp-width |
yes | Width of image in pixels, e.g. 450 . |
data-sp-height |
yes | Height of image in pixels, e.g. 300 . |
data-sp-placeholder |
no | Absolute or relative URL to placeholder/preview image. This will be displayed if the image has not been paid yet. E.g. /placeholders/2.png . |
data-sp-currency |
no | The XLM price converted to US Dollars, Euro, or UK Pounds. Use currency code: 'USD', 'EUR', or 'GBP' |
Audio
Audio Example
<div class="satoshipay-placeholder-audio"
data-sp-type="audio/mpeg"
data-sp-src="/paid-content/5.mp3"
data-sp-id="558bcdbb1309c59725bdb555"
data-sp-autoplay="true"
data-sp-length="28007040"
data-sp-title="Podcast: Interview with Satoshi Nakamoto"
data-sp-currency="GBP"
></div>
This tag type represents an audio file that is displayed by injecting an audio
tag after successful payment.
Data Attributes
Data Attribute | Required | Description |
---|---|---|
data-sp-type |
yes | Content type (MIME), must start with "audio/" for this type of digital good, e.g. audio/mpeg . See supported types. |
data-sp-src |
yes | HTTP endpoint for audio as absolute or relative URL, e.g. /paid-content/5.mp3 . |
data-sp-id |
yes | Unique identifier for the good in SatoshiPay's registry. Consists of a hex string, e.g. 558bcdbb1309c59725bdb555 . |
data-sp-autoplay |
no | Value for automatic audio playback, where available. E.g. true , default: false . |
data-sp-length |
yes | HTTP content-length i.e. file size of audio in bytes. This value is used to indicate the audio file size next to the audio payment button. E.g. 28007040 . |
data-sp-title |
no | Short title of audio file, e.g. Podcast: Interview with Satoshi Nakamoto . If no title is given, File will be used. |
data-sp-currency |
no | The XLM price converted to US Dollars, Euro, or UK Pounds. Use currency code: 'USD', 'EUR', or 'GBP' |
Video
Video Example
<div class="satoshipay-placeholder-video"
data-sp-type="video/mp4"
data-sp-src="/paid-content/4.mp4"
data-sp-id="558bcdbb1309c59725bdb562"
data-sp-width="640"
data-sp-height="360"
data-sp-autoplay="true"
data-sp-placeholder="/placeholders/4.png"
data-sp-currency="GBP"
></div>
This tag type represents a video that is displayed by injecting a video
tag after successful payment.
Data Attributes
Data Attribute | Required | Description |
---|---|---|
data-sp-type |
yes | Content type (MIME), must start with "video/" for this type of digital good, e.g. video/mp4 . See supported types. |
data-sp-src |
yes | HTTP endpoint for video as absolute or relative URL, e.g. /paid-content/4.mp4 . |
data-sp-id |
yes | Unique identifier for the good in SatoshiPay's registry. Consists of a hex string, e.g. 558bcdbb1309c59725bdb559 . |
data-sp-height |
yes | Height of video in pixels, e.g. 360 . |
data-sp-width |
yes | Width of video in pixels, e.g. 640 . |
data-sp-autoplay |
no | Value for automatic video playback, where available. E.g. true , default: false . |
data-sp-placeholder |
no | Absolute or relative URL to placeholder/preview image. This will be displayed if the video has not been paid yet. E.g. /placeholders/4.png . |
data-sp-currency |
no | The XLM price converted to US Dollars, Euro, or UK Pounds. Use currency code: 'USD', 'EUR', or 'GBP' |
Download
Download Example
<div class="satoshipay-placeholder-download"
data-sp-type="application/pdf"
data-sp-src="/paid-content/3.pdf"
data-sp-id="558bcdbb1309c59725bdb561"
data-sp-length="835669"
data-sp-title="Book: What's the Deal with Bitcoins?"
data-sp-currency="GBP"
></div>
This tag type represents a secure download link that is displayed after successful payment.
Data Attributes
Data Attribute | Required | Description |
---|---|---|
data-sp-type |
yes | Content type (MIME), must start with "application/" for this type of digital good, e.g. application/pdf . See supported types. |
data-sp-src |
yes | HTTP endpoint for download as absolute or relative URL, e.g. /paid-content/3.pdf . |
data-sp-id |
yes | Unique identifier for the good in SatoshiPay's registry. Consists of a hex string, e.g. 558bcdbb1309c59725bdb559 . |
data-sp-length |
yes | HTTP content-length i.e. file size of download in bytes. This value is used to indicate the download size next to the download link. E.g. 835669 . |
data-sp-title |
no | Short title of download, e.g. Research Report 2016 . If no title is given, File will be used. |
data-sp-currency |
no | The XLM price converted to US Dollars, Euro, or UK Pounds. Use currency code: 'USD', 'EUR', or 'GBP' |
Donation
Donation Example
<div class="satoshipay-placeholder-donation"
data-sp-type="donation"
data-sp-id="558bcdbb1309c59725bdb561"
data-sp-currency="GBP"
data-sp-show-thankyou="true"
data-sp-placeholder="/placeholders/4.png"
data-sp-width="450"
data-sp-height="300"
></div>
This tag type allows for a one-time payment.
Data Attributes
Data Attribute | Required | Description |
---|---|---|
data-sp-type |
yes | Must be "donation" |
data-sp-id |
yes | Unique identifier for the good in SatoshiPay's registry. Consists of a hex string, e.g. 558bcdbb1309c59725bdb559 . |
data-sp-currency |
no | The XLM price converted to US Dollars, Euro, or UK Pounds. Use currency code: 'USD', 'EUR', or 'GBP' |
data-sp-show-thankyou |
no | If set to true , a "Thank you" notice will be shown permanently after successful donation. Default: false . |
data-sp-placeholder |
no | Absolute or relative URL to placeholder/preview image. This will be displayed if the image has not been paid yet. E.g. /placeholders/2.png . |
data-sp-height |
no | Height of placeholder/preview image in pixels, e.g. 360 . |
data-sp-width |
no | Width of placeholder/preview image in pixels, e.g. 640 . |
Retrieving Goods
The merchant needs to provide public endpoints to allow the SatoshiPay widget to retrieve a good once it has successfully been paid for. The URL of an endpoint is defined as the data-sp-src
attribute in the HTML tag.
In the example, assuming the special HTML tags are defined in https://example.org/index.html
, the data-sp-src
attribute has been set to /satoshipay-content/5
(another possibility would be the absolute URL https://example.org/satoshipay-content/5
).
Content delivery for text, images, audio files, videos and downloads needs to be supported.
Request Format
Example Request
curl https://example.org/satoshipay-content/5?paymentReceipt=eyJleHAiOjE1MDM1NzY4NDksIml0byI6IjAyZmNmZWNiZGFiMTExMmY0MjRiYzc2MTVmZDY2NjkzNzBhMjc3Njg1MjgxMjc3MWM2YWQ1Y2RmZTU3MTgzNDNkNSIsImp0aSI6ImNRNkROa1dUdjU3NGVLb2NoQnZlZWFtRzY2WE9lSUx4In0.13c5d97f6ac3b0d2412962437066ca22ada3cafad1aefad85a2e261a98b2ee14e0ca8f3c7772c78fd8fed9cfb0b51b4b4c154c078a1a0b36a5c19185c84b6281
var request = require("request");
request({
url: "https://example.org/satoshipay-content/5",
qs: {
paymentReceipt: "eyJleHAiOjE1MDM1NzY4NDksIml0byI6IjAyZmNmZWNiZGFiMTExMmY0MjRiYzc2MTVmZDY2NjkzNzBhMjc3Njg1MjgxMjc3MWM2YWQ1Y2RmZTU3MTgzNDNkNSIsImp0aSI6ImNRNkROa1dUdjU3NGVLb2NoQnZlZWFtRzY2WE9lSUx4In0.13c5d97f6ac3b0d2412962437066ca22ada3cafad1aefad85a2e261a98b2ee14e0ca8f3c7772c78fd8fed9cfb0b51b4b4c154c078a1a0b36a5c19185c84b6281"
}
}, callback);
The endpoint will be called with a GET
request that has the following query parameters:
Query Parameter | Description |
---|---|
paymentReceipt |
Receipt for payment. This parameter should be used by the endpoint to authenticate the request (see authentication below). |
Authentication
Authentication is implemented on the merchant's HTTP endpoint without connecting to the SatoshiPay API. It is done by verifying the value of the query parameter paymentReceipt
, which consists of the Base64 encoded JSON payload and a signature split by a dot.
Example URL
https://example.org/satoshipay-content/5?paymentReceipt=eyJleHAiOjE1MDM1NzY4NDksIml0byI6IjAyZmNmZWNiZGFiMTExMmY0MjRiYzc2MTVmZDY2NjkzNzBhMjc3Njg1MjgxMjc3MWM2YWQ1Y2RmZTU3MTgzNDNkNSIsImp0aSI6ImNRNkROa1dUdjU3NGVLb2NoQnZlZWFtRzY2WE9lSUx4In0.13c5d97f6ac3b0d2412962437066ca22ada3cafad1aefad85a2e261a98b2ee14e0ca8f3c7772c78fd8fed9cfb0b51b4b4c154c078a1a0b36a5c19185c84b6281
PAYLOAD_BASE64="eyJleHAiOjE1MDM1NzY4NDksIml0byI6IjAyZmNmZWNiZGFiMTExMmY0MjRiYzc2MTVmZDY2NjkzNzBhMjc3Njg1MjgxMjc3MWM2YWQ1Y2RmZTU3MTgzNDNkNSIsImp0aSI6ImNRNkROa1dUdjU3NGVLb2NoQnZlZWFtRzY2WE9lSUx4In0"
SIGNATURE="13c5d97f6ac3b0d2412962437066ca22ada3cafad1aefad85a2e261a98b2ee14e0ca8f3c7772c78fd8fed9cfb0b51b4b4c154c078a1a0b36a5c19185c84b6281"
http://example.org/path?paymentReceipt=${payloadBase64}.${signature}
Query Parameter | Description |
---|---|
payloadBase64 |
Base64 encoded payload describes the user and expiration time. |
signature |
Signature is the SHA-512 hash of string resulting from concatenating payloadBase64 and the good's sharedSecret known only by the merchant. |
Payload
payloadBase64
is a Base64 encoded JSON structure allowing to identify to whom the receipt was issued to and defining the time it expires.
Example
payloadBase64
eyJleHAiOjE1MDM1NzY4NDksIml0byI6IjAyZmNmZWNiZGFiMTExMmY0MjRiYzc2MTVmZDY2NjkzNzBhMjc3Njg1MjgxMjc3MWM2YWQ1Y2RmZTU3MTgzNDNkNSIsImp0aSI6ImNRNkROa1dUdjU3NGVLb2NoQnZlZWFtRzY2WE9lSUx4In0
Example Payload
{
"exp": 1503576849,
"ito": "02fcfecbdab1112f424bc7615fd6669370a2776852812771c6ad5cdfe5718343d5",
"jti": "cQ6DNkWTv574eKochBveeamG66XOeILx"
}
Example
signature
The correct signature for the above example payload and a sharedSecret
value of "jsbicjttovhgtkdtsthduxg"
is
text
"13c5d97f6ac3b0d2412962437066ca22ada3cafad1aefad85a2e261a98b2ee14e0ca8f3c7772c78fd8fed9cfb0b51b4b4c154c078a1a0b36a5c19185c84b6281"
Field | Name | Description |
---|---|---|
exp |
Expiration time | Expiration time (UNIX time in seconds) after which the payment receipt MUST NOT be accepted for processing. |
ito |
Issued To | Identifies a user to whom the receipt was issued to. |
jti |
JWT ID | Case sensitive unique identifier of the token. |
Validating request
Validation procedure
const SHA512 = require('crypto-js/sha512')
const base64url = require('base64url');
function validate (sharedSecret, paymentReceipt) {
const receipt = paymentReceipt.split('.')
const payloadBase64 = receipt[0]
const payload = base64url.decode(payloadBase64)
const payloadParsed = JSON.parse(payload)
const signature = receipt[1]
const hash = SHA512(payloadBase64 + sharedSecret).toString()
return (hash === signature && payloadParsed.exp > Date.now() / 1000)
}
Validating paymentReceipt
means verifying the signature and expiration time. The signature is the SHA-512 hash of the string resulting from concatenating payloadBase64
and the good's sharedSecret
known only by merchant.
The merchant is responsible for generating a unique sharedSecret
for every good and storing it in the merchant's own database.
Response Format
Example Response
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
<strong>OH HAI!</strong> You've <em>nanopaid</em> me.
The response needs to have HTTP status 200 set and contain the correct Content-Type
header for the digital good. In most cases simply passing on the MIME media type returned by the file system should be sufficient, but make sure to check the list of content types that are supported.
The HTTP header is followed by the content of the digital good, for example HTML code.
Cross-Domain
Required Headers
Access-Control-Allow-Origin: *
If you are serving digital goods from a different hostname the website containing SatoshiPay widget is served from, you need to work around the same-origin policy by adding these headers to your response:
Range Requests
Standard Response Header
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 1000
Partial Content Response Header
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Length: 500
Content-Range: bytes 0-499/1000
For goods with a larger file size it is recommended to process HTTP range requests and serve partial content. This will allow browsers and download managers to resume a transfer or to transfer file segments in parallel.
To make skipping to a certain position (seeking) in an audio file or video possible, support for range requests is required. Most browsers or players won't allow seeking if the HTTP source does not support partial content.
We will publish sample digital goods servers written in PHP and Node with support for range requests soon. Contact us if you would like to get early access.
Content Types
SatoshiPay uses the MIME media type standard to identify the content of digital goods. Media types (also "content types") influence the way digital goods are retrieved and displayed. Here is a complete list of supported types.
Text types
text/html
text/plain
Image types
image/bmp
image/gif
image/jpeg
image/png
image/svg+xml
image/tiff
Audio types
audio/mpeg
audio/mp4
audio/ogg
audio/webm
audio/wav
Video types
video/avi
video/mp4
video/mpeg
video/msvideo
video/ogg
video/quicktime
video/x-msvideo
Download types
application/bzip2
application/java-archive
application/mac-binhex40
application/msword
application/octet-stream
application/pdf
application/postscript
application/rdf
application/rdf+xml
application/rtf
application/vnd.ms-excel
application/vnd.ms-powerpoint
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.openxmlformats-officedocument.presentationml.slide
application/vnd.openxmlformats-officedocument.presentationml.slideshow
application/vnd.openxmlformats-officedocument.presentationml.template
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.openxmlformats-officedocument.spreadsheetml.template
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/vnd.openxmlformats-officedocument.wordprocessingml.template
application/x-compressed-zip
application/x-gzip
application/x-shockwave-flash
application/x-tar
application/xml
application/zip
Testnet Sandbox
To faciliate easier development, the SatoshiPay client is available in a sandbox environment which connects to the Stellar testnet. Testnet funds are free. Please note that the testnet may arbitrarily reset.
To get started, you must register a test account on the URL below:
dashboard.satoshipay.io/testnet
To get the account upgraded for use, please write an email to api@satoshipay.io from the email you used to create the account.
Endpoints
Testnet API Endpoint
https://api.satoshipay.io/testnet/v2/
The testnet version follows the same structure and logic as the Digital Goods API, except it is accessed through different endpoints.
The root endpoint is:
https://api.satoshipay.io/testnet/v2/
Testnet Widget
Include Testnet Widget
<script src="https://wallet.satoshipay.io/testnet/satoshipay.js"></script>
In order to use the testnet version of the widget on your web page, call the javascript below:
https://wallet.satoshipay.io/testnet/satoshipay.js
Testnet Funds
To get testnet funds, find a Stellar friendbot which sends free testnet lumens to a testnet account. Solar wallet is free and comes with a friendbot feature. Download the wallet from solarwallet.io.