Introduction

We have organized our API around REST and utilize object/resource orientated URLs that are predictable. All endpoint responses are returned as JSON, although any official API library uses the language appropriate representation of an object. We also offer a webhook event system which follows the same guide as endpoint responses and all object attributes will be exactly the same.

We require and force all requests to any of Selly's services, including the API, to be served over HTTPS

The Selly API is designed for those interested in developing their products utilizing our platform. Due to the nature of this platform, we rate limit it heavily. The universal rate limit is 150 requests an hour. We plan to offer cheap developer plans to greatly expand the number of requests you can do. Contact us for a quote.

The Selly API Endpoint

https://selly.gg/api

Authentication

You need to be authenticated for all API requests. You can find your API token in your settings page located here.

Headers
X-Auth-Email
string
Your email address
X-Auth-Key
string
API token located here
curl 'https://selly.gg/api/' \
-H 'X-Auth-Email:youremail@email.com' \
-H 'X-Auth-Key:YourKeyHere'

If authentication fails, it will respond with the following and a 403 status.

{
  "status":false,
  "error":["Invalid authentication"]
}

Errors

The error attribute is an array due to some errors being stacked

CodeNameDescription
200OKSuccess
201CreatedCreation successful
400Bad RequestWe could not process that action
401UnauthorizedWe could not authorize/authenticate you
404Not FoundRecord/page could not be found
422UnprocessableParamaters missing/invalid
429Rate LimitedYou have done too many requests
500Internal server errorWe've been notified of an issue

All errors will be returned in a standard format

{
  "status":false,
  "error":["Error message"]
}

Rate Limiting

We use two types of rate limiting. Overall requests are limited to 150 an hour. When hitting this limit you'll have to wait an hour before being able to send a request again. Our other rate limiting is for authentication. Some specific actions will be rate limited separately as well. All rate limits can be expanded by contacting us for a quote for a development plan.

Pagination is available for the index of a object's endpoint, for example https://selly.gg/api/products. Pagination is accomplished by having a page parameter of the wanted page number. The total number of pages will be returned in the header X-Total-Pages

/products

List all products

All products that are not product_type 2 will have a string stating "∞" as the stock.

URL Parameters
page
integer
Paginates 20 results at a time

Lists all your products and their respective details.

curl 'https://selly.gg/api/products' \
-H 'X-Auth-Email:youremail@email.com' \
-H 'X-Auth-Key:YourKeyHere'
[
  {
    "id": "7b84a62b",
    "title": "My awesome product",
    "description": "This is the description",
    "stock": 0,
    "price": "3.99",
    "currency": "USD",
    "product_type": 2,
    "private": false,
    "unlisted": false,
    "seller_note": "",
    "maximum_quantity": null,
    "minimum_quantity": 1,
    "custom": {
      "0": {
        "type": "2",
        "name": "Username",
        "required": true
      }
    },
    "created_at": "2017-03-14T23:27:54.000Z",
    "updated_at": "2017-03-20T16:48:20.000Z"
  },
  {
    "id": "dd834c",
    "title": "This is my awesome product",
    "description": "And the description",
    "stock": 0,
    "price": "3.99",
    "currency": "USD",
    "product_type": 2,
    "private": false,
    "unlisted": false,
    "seller_note": "",
    "maximum_quantity": null,
    "minimum_quantity": 1,
    "custom": {},
    "created_at": "2016-04-08T15:39:48.000Z",
    "updated_at": "2016-11-26T01:13:25.000Z"
  }
]

/products/:id

Get a product's details

Parameters
id
integer
Identity number
curl 'https://selly.gg/api/products/7b84a62b' \
-H 'X-Auth-Email:youremail@email.com' \
-H 'X-Auth-Key:YourKeyHere'
{
    "id": "7b84a62b",
    "title": "My awesome product",
    "description": "This is the description",
    "stock": 0,
    "price": "3.99",
    "currency": "USD",
    "product_type": 2,
    "private": false,
    "unlisted": false,
    "seller_note": "",
    "maximum_quantity": null,
    "minimum_quantity": 1,
    "custom": {
      "0": {
        "type": "2",
        "name": "Username",
        "required": true
      }
    },
    "created_at": "2017-03-14T23:27:54.000Z",
    "updated_at": "2017-03-20T16:48:20.000Z"
}

/orders

List all orders

URL Parameters
page
integer
Paginates 20 results at a time

Lists all your orders and their respective details.

curl 'https://selly.gg/api/orders' \
-H 'X-Auth-Email:youremail@email.com' \
-H 'X-Auth-Key:YourKeyHere'
[
    {
    "id": "89ac7499-efc3-4f5b-a2fd-c00fec6aa480",
    "product_id": "ac24a3",
    "email": "132.26.9.4",
    "ip_address": "80.41.8.199",
    "country_code": "US",
    "user_agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
    "value": "0.03",
    "currency": "USD",
    "gateway": "Bitcoin",
    "risk_level": 9,
    "status": 0,
    "delivered": "Unpaid",
    "crypto_value": null,
    "crypto_address": null,
    "referral": "Direct",
    "usd_value": "0.03",
    "exchange_rate": "1.0",
    "custom": {
      "0": "MyUsername"
    },
    "created_at": "2015-06-11T18:32:01.000Z",
    "updated_at": "2017-02-14T17:47:27.000Z"
  },
  {
    "id": "fd87d909-fbfc-466c-964a-5478d5bc066a",
    "product_id": "upgrade",
    "email": "alishia@yahoo.com",
    "ip_address": "88.96.129.5",
    "country_code": "US",
    "user_agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
    "value": "0.03",
    "currency": "USD",
    "gateway": "Bitcoin",
    "risk_level": 10,
    "status": 100,
    "delivered": "SERIAL-12345-12345",
    "crypto_value": null,
    "crypto_address": null,
    "referral": "Direct",
    "usd_value": "0.03",
    "exchange_rate": "1.0",
    "custom": {
      "0": "SomeInput"
    },
    "created_at": "2016-11-27T14:20:34.000Z",
    "updated_at": "2016-12-05T21:31:15.000Z"
  }
]

/orders/:id

Get a order's details

Parameters
id
string
The id of the order

Lists details about the specified order.

curl 'https://selly.gg/api/orders/79e118b9-ce58-4952-a1c7-467ca152d8f5' \
-H 'X-Auth-Email:youremail@email.com' \
-H 'X-Auth-Key:YourKeyHere'
{
    "id": "fd87d909-fbfc-466c-964a-5478d5bc066a",
    "product_id": "upgrade",
    "email": "alishia@yahoo.com",
    "ip_address": "88.96.129.5",
    "country_code": "US",
    "user_agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
    "value": "0.03",
    "currency": "USD",
    "gateway": "Bitcoin",
    "risk_level": 10,
    "status": 100,
    "delivered": "SERIAL-12345-12345",
    "crypto_value": null,
    "crypto_address": null,
    "referral": "Direct",
    "usd_value": "0.03",
    "exchange_rate": "1.0",
    "custom": {
      "0": "SomeInput"
    },
    "created_at": "2016-11-27T14:20:34.000Z",
    "updated_at": "2016-12-05T21:31:15.000Z"
  }

/exchange/rates

List exchange rates

List current exchange rates used by Selly. All exchange rates are based off United Stated Dollars (USD $) and are updated every 5 minutes.

curl 'https://selly.gg/api/exchange/rates' \
-H 'X-Auth-Email:youremail@email.com' \
-H 'X-Auth-Key:YourKeyHere'
{
  "USD": 1,
  "GBP": 0.80488,
  "EUR": 0.93897,
  "SEK": 8.8712,
  "SGD": 1.4165,
  "AUD": 1.3044,
  "CAD": 1.3079,
  "CHF": 0.99878,
  "CNY": 6.867,
  "BRL": 3.1311
}

Payment Forwarding

Payment forwarding is how Selly's crypto currency payments work. In essence, a temporary address is created, then incoming transactions and their confirmations are able to be tracked and notified to a webhook URL. Once a transaction is detected to the temporary address, the entire balance will then be forwarded to the specified "forward to" address.

For each incoming transaction, you will receive a total of 7 webhook calls, one for each confirmation starting at 0 and ending at 6

As the forwarding transaction will occur as soon as incoming transaction is received and is dependent on the incoming transaction's inputs, we recommend you await at least 1 confirmation before concluding the forwarding transaction to be completed.

A processing fee can be set for forwarded transactions. An example use case may be a marketplace fee or affiliate split. The processing fee is percentage based and currently has a max limit of 50%.

Miner fees are calculated dynamically to provider the quickest confirmation at the cheapest rate. Miner fees will be removed from the forward to address output, not the processing fee output if one was to be set.

Payment forward API requests are rate limited independently of the rest of the API's rate limiting. Each request, regardless of whether it is successful or not, will increment the number of requests used.

A paid development plan is required for payment forwarding API access. You can purchase a development plan based on your rate limiting needs here
Transactions that fail to send due to the miner fee being larger than the output won't be recoverable and will not be processable by our systems.

/payment/bitcoin

Create a Bitcoin payment forwarding request

Parameters
address
string
The Bitcoin address to forward transactions to
webhook_url
string
The URL to receive confirmation webhook requests
processing_fee_percent (optional)
number
The percentage processing fee to be applied. Max is 50
processing_fee_address (optional)
string
The Bitcoin address to forward processing fees to

Webhooks

Webhooks are a HTTP callback event that is sent to the Webhook URL specified for the affected order. All webhook requests are sent as a POST request and are handled independently from the event, asynchronously.

We recommend when setting the webhook URL on a product, you add a secret parameter to verify the request is genuinely from Selly. An example URL with a secret added in may be https://requestb.in/15rrszg2?secret=thisischeckedbyyou.

The content sent in the webhook is a JSON object of whatever the webhook is related to. If it was a order webhook, the content received would be the same as the individual order API call that can be found here.

Each webhook request contains a webhook_type attribute to identify what the request is for. As we expand our system, more webhook events/types will be added. We plan to offer events for query's being created/replied to, feedback being left and more.

CodeDescription
1Order paid
2Order chargeback
3Dynamic product
4Product out of stock
5Product reached warning stock

Dynamic Products

Dynamic products is a new product type intended for developers. It's built on top of the webhook system and it's purpose is for "dynamic stock".

It works by sending a POST (webhook) request with a order object to the specified dynamic URL and the response body will be what is delivered to the customer. This allows for a whole new subset of products to be completely automated and delivered to the seller immediately. The response body will be truncated to 500 characters.

This obviously will not send files, only the response body. If we detect a invalid URL, we will automatically remove the product's dynamic URL ability.

An example application of this may be generating serials. The seller's dynamic URL endpoint processes the order object and generates a unique serial code and returns it in the response body.

To ensure that webhooks requests sent to the dynamic URL endpoint is legitimate, make sure you append parameters onto it that can be verified in the endpoint. A example dynamic URL may be https://mywebsite.com/endpoint?secret=ThisIsASecret&secret_two=TwoTimesSecretIsTwoTimesAsFunwhere both secret and secret_two are verified by your endpoint.

You will only receive requests to the dynamic URL when the order has already been marked as having a status of complete a.k.a 100.

Lets say the following URL is our Dynamic URL
http://www.mocky.io/v2/58dfa2e81000004001cc15ba
When we go there (POST request) we get the following in plain text:
This is generated server side.
The above is what would be sent to the buyer. We only send what that page displays hence you cannot use a dynamic product for files. Any HTML would also be sent to the buyer as it would consider it as plain text, so make sure you do not render anything but good old plain text.

Examples

Although not much example code can be provided right now, here are a few ideas for how webhooks can be used and have been used by Selly's merchants.

  • Discord/slack bot to notify when a product is low/out of stock or a order is paid/chargedback
  • Keeping track of stock

Small example of notifying about orders via Discord

require 'sinatra'
require 'discordrb'

post '/webhook-url' do

  bot = Discordrb::Bot.new token: 'PUTTOKENHERE', client_id: 168123456789123456
  type = params[:webhook_type].to_i

  case type
    # Order paid
    when 1
      bot.send_message(
        'channel-id',
        "#{params[:id]} has been paid - #{params[:value]}"
      )
    # Order chargeback
    when 2
      bot.send_message(
        'channel-id',
        "#{params[:id]} has chargedback - #{params[:value]}"
      )
    else
      # Do nothing
  end

  bot.run
end