NAV Navbar
Shell JavaScript
  • Introduction
  • Digital Goods API
  • HTML Tags
  • Retrieving Goods
  • Content Types
  • Testnet Sandbox
  • 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:

    SatoshiPay and You

    To understand how SatoshiPay works you need to know the following:

    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:

    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:

    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

    Image types

    Audio types

    Video types

    Download types

    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.