Authentication

Selly's API uses Basic authentication with your account email and API key. This is usually done via the Authorization header.

Your API key can be accessed and re-generated here

All API requests must be made over HTTPS.

Setup Authentication
require 'selly'
Selly.api_key = 'api key'
Selly.api_email = 'email'

Pagination

Selly offers the ability to paginate any list endpoint. The X-Total-Pages header returns the total number of pages for the resources at the specific endpoint you're using.

By default, 20 resources are displayed per page.

Parameters


  • integer
    The page number. Defaults to 1
  • integer
    Records per page. Defaults to 20. Allowed values are >= 10 and <= 50
Paginating Orders Example
# Page 10
Selly::Orders::List(page: 10)
# Page 10 and 50 per page
Selly::Orders::List(page: 10, per_page: 50)

Errors

Errors will only ever be present with a 400 to 503 HTTP response status. All errors will include a message attribute detailing the error message.

Validation errors will feature a errors attribute containing an array of error message strings.

The Selly API uses the following error codes:

StatusMeaning
400Bad Request - Invalid parameters
401Unauthorized - Unable to authenticate
403Forbidden - The request is not allowed
404Not Found - The specified resource could not be found.
406Not Acceptable - You requested a format that isn't json.
429Too Many Requests - You have reached the rate limit
500Internal Server Error - We had a problem with our server. Try again later. These are rare.
503Service Unavailable - We're temporarily offline for maintenance. Please try again later.
Authentication Error
401
{
"message": "Unable to authenticate"
}
Authorization Error
403
{
"message": "You are not authorized to perform this action"
}
Validation Error
400
{
"message": "Validation failed",
"errors": [
"Title can't be blank",
"Title is too short (minimum is 2 characters)",
"Title must be present"
]
}

Webhooks

Selly provides a webhooks system allowing you to subscribe to to events with Webhook Endpoints, alongside Product/Payment Order status webhooks and Dynamic Product webhooks.

A webhook simulator is available allowing you to simulate webhooks to a URL. It can be accessed here.

Signing/Validating

To verify the authenticity of a webhook request and its payload, each webhook request includes a X-Selly-Signature header with a HMAC signature comprised of the JSON encoded request body and your webhook secret. Your webhook secret can be changed in your settings page.

Events

Each webhook request will feature a X-Selly-Event header containing the webhook event type. A list of supported events from Webhook Endpoints can be found below.

Event
feedback:updated
order:created
order:updated
order:paid
product:out_of_stock
query:created
query:replied

Logs

Each webhook request will create a Webhook Log. The object is created by the request has been sent. Before the request response has actually been received, the response_code will be 0, indicating it is pending.

Each webhook request will also include a X-Selly-Webhook request header containing the Webhook Log id.

Validating Signed Webhook Signature
require 'openssl'
require 'active_support'
secret = 'your webhook secret'
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha512'), secret, payload.to_json)
is_valid_signature = ActiveSupport::SecurityUtils.secure_compare(request.headers['X-Selly-Signature'], signature)
if is_valid_signature
# Webhook is valid
end

Blacklist Object

Attributes


  • string
    Unique identifier for the object.
  • integer
    1 for Email. 2 for IP address. 3 for Country Code
  • string
    Blocked data. Either country code, email or IP address
  • string
    Internal note for the reasoning of the blacklist
  • datetime
    The date and time that the resource was created.
  • datetime
    The date and time that the resource was last updated. If never updated, it will be equal to created_at.
The Blacklist Object
{
"id": "bGYSEexV",
"blocked_data": "ZW",
"blacklist_type": 3,
"note": "This is a demo blacklist",
"created_at": "2019-12-28T16:47:01.000+00:00",
"updated_at": "2019-12-28T16:47:01.000+00:00"
}

Get a Blacklist

GET
/api/v2/blacklist/:id

Retrieves a Blacklist by ID

Get a blacklist
Selly::Blacklist.retrieve('bGYSEexV')
Response
200
{
"id": "bGYSEexV",
"blocked_data": "ZW",
"blacklist_type": 3,
"note": "This is a demo blacklist",
"created_at": "2019-12-28T16:47:01.000+00:00",
"updated_at": "2019-12-28T16:47:01.000+00:00"
}

List all Blacklist

GET
/api/v2/blacklist

Returns a list of the Blacklist. The blacklist are sorted by creation date, with the most recently created blacklist being first.

  • integer
    Page number for use in pagination
List all blacklist
Selly::Blacklist.list
Response
200
[
{
"id": "bGYSEexV",
"blocked_data": "ZW",
"blacklist_type": 3,
"note": "This is a demo blacklist",
"created_at": "2019-12-28T16:47:01.000+00:00",
"updated_at": "2019-12-28T16:47:01.000+00:00"
}
]

Create a Blacklist

POST
/api/v2/blacklist

Creates a Blacklist and return the created Blacklist

Arguments


  • integerRequired
    1 for Email. 2 for IP address. 3 for Country Code
  • stringRequired
    Blocked data. Either country code, email or IP address
  • string
    Internal note for the reasoning of the blacklist
Create a blacklist
Selly::Blacklist.create(
blocked_data: 'ZW',
blacklist_type: 3
)
Response
201
{
"id": "bGYSEexV",
"blocked_data": "ZW",
"blacklist_type": 3,
"note": "This is a demo blacklist",
"created_at": "2019-12-28T16:47:01.000+00:00",
"updated_at": "2019-12-28T16:47:01.000+00:00"
}

Update a Blacklist

PUT
/api/v2/blacklist/:id

Update a Blacklist by ID and return the updated Blacklist

Arguments


  • integer
    1 for Email. 2 for IP address. 3 for Country Code
  • string
    Blocked data. Either country code, email or IP address
  • string
    Internal note for the reasoning of the blacklist
Update a blacklist
Selly::Blacklist.update('bGYSEexV',
blocked_data: 'GR'
)
Response
200
{
"id": "bGYSEexV",
"blocked_data": "GR",
"blacklist_type": 3,
"note": "This is a demo blacklist",
"created_at": "2019-12-28T16:47:01.000+00:00",
"updated_at": "2019-12-28T16:48:02.000+00:00"
}

Destroy a Blacklist

DELETE
/api/v2/blacklist/:id

Destroys a Blacklist by ID

Destroy a blacklist
Selly::Blacklist.destroy('bGYSEexV')
Response
204
// No Content: 204 HTTP status

Category Object

Attributes


  • string
    Unique identifier for the object.
  • title
    Display title of the category
  • array
    Array of product IDs in the category
  • boolean
    Whether the category will show up in public listings. If true, the category can only be found via a direct URL
  • object
    Category image
    Show child attributes
  • datetime
    The date and time that the resource was created.
  • datetime
    The date and time that the resource was last updated. If never updated, it will be equal to created_at.
The Category Object
{
"id": "1dd671f4",
"title": "Demo category",
"product_ids": [
"100bcf1e"
],
"image": {
"id": "55e68f9900c08f1dea6aec2ffc9c153856a91d5c/b65fcd4508226e9774445ebb4495048756750738",
"storage": "cdn",
"metadata": {
"size": 3463,
"filename": "logo.png",
"mime_type": "image/png"
},
"url": "https://cdn.selly.io/cd2de339c0a605dedf29aecd44d3feb002842e60/68747470733a2f2f73656c6c792e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f63616368652f353565363866393930306330386631646561366165633266666339633135333835366139316435632f6236356663643435303832323665393737343434356562623434393530343837353637"
},
"unlisted": true,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

List all Categories

GET
/api/v2/categories

Returns a list of the Categories. The categories are sorted by creation date, with the most recently created categories being first.

  • integer
    Page number for use in pagination
List all categories
Selly::Categories.list
Response
200
[
{
"id": "1dd671f4",
"title": "Demo category",
"product_ids": [
"100bcf1e"
],
"image": {
"id": "55e68f9900c08f1dea6aec2ffc9c153856a91d5c/b65fcd4508226e9774445ebb4495048756750738",
"storage": "cdn",
"metadata": {
"size": 3463,
"filename": "logo.png",
"mime_type": "image/png"
},
"url": "https://cdn.selly.io/cd2de339c0a605dedf29aecd44d3feb002842e60/68747470733a2f2f73656c6c792e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f63616368652f353565363866393930306330386631646561366165633266666339633135333835366139316435632f6236356663643435303832323665393737343434356562623434393530343837353637"
},
"unlisted": true,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}
]

Get a Category

GET
/api/v2/categories/:id

Retrieves a Category by ID

Get a category
Selly::Categories.retrieve('1dd671f4')
Response
200
{
"id": "1dd671f4",
"title": "Demo category",
"product_ids": [
"100bcf1e"
],
"image": {
"id": "55e68f9900c08f1dea6aec2ffc9c153856a91d5c/b65fcd4508226e9774445ebb4495048756750738",
"storage": "cdn",
"metadata": {
"size": 3463,
"filename": "logo.png",
"mime_type": "image/png"
},
"url": "https://cdn.selly.io/cd2de339c0a605dedf29aecd44d3feb002842e60/68747470733a2f2f73656c6c792e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f63616368652f353565363866393930306330386631646561366165633266666339633135333835366139316435632f6236356663643435303832323665393737343434356562623434393530343837353637"
},
"unlisted": true,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

Create a Category

POST
/api/v2/categories

Creates a Category and return the created Category

Arguments


  • titleRequired
    Display title of the category
  • arrayRequired
    Array of product IDs in the category
  • boolean
    Whether the category will show up in public listings. If true, the category can only be found via a direct URL
Create a category
Selly::Category.create(
title: 'Demo category',
product_ids: ['100bcf1e']
)
Response
201
{
"id": "1dd671f4",
"title": "Demo category",
"product_ids": [
"100bcf1e"
],
"image": null,
"unlisted": true,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

Update a Category

PUT
/api/v2/categories/:id

Update a Category by ID and return the updated Category

Arguments


  • title
    Display title of the category
  • array
    Array of product IDs in the category
  • boolean
    Whether the category will show up in public listings. If true, the category can only be found via a direct URL
Update a category
Selly::Categories.update('1dd671f4',
title: 'Updated title'
)
Response
200
{
"id": "1dd671f4",
"title": "Updated title",
"product_ids": [
"100bcf1e"
],
"image": null,
"unlisted": true,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

Destroy a Category

DELETE
/api/v2/categories/:id

Destroys a Category by ID

Destroy a category
Selly::Categories.destroy('1dd671f4')
Response
204
// No Content: 204 HTTP status

Order Object

Attributes


  • string
    Unique identifier for the object.
  • string
    Unique identifier for the product associated to the order.
  • string
    Customer's email address.
  • string
    Customer's IP address.
  • string
    Customer's ISO 3166-1 Alpha-2 country code.
  • float
    The value of the order in the specified currency.
  • float
    The value of the order in USD.
  • string
    The ISO 4217 currency code used for this order.
  • string
    The gateway used for this order. E.g Bitcoin, PayPal.
  • integer
    Quantity of the product purchased. Default is 1.
  • integer
    Status of the order.
  • string
    The delivered product that the customer purchased. Default is null.
  • string
    The HTTP referrer for the product page. Default is null.
  • string
    The crypto currency address presented to the customer
  • integer
    The crypto value in satoshis that the customer is required to send
  • integer
    The crypto value in satoshis that the customer has sent
  • datetime
    The date and time that the resource was created.
  • datetime
    The date and time that the resource was last updated. If never updated, it will be equal to created_at.
The Order Object
{
"id": "d73cf5fc-466d-433e-a109-f8de4d4c70fc",
"product_id": "b3cadd729499",
"email": "[email protected]",
"ip_address": "41.117.222.111",
"country_code": "US",
"product_title": "Side Direct Filter",
"user_agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"risk_level": 0,
"status": 0,
"delivered": null,
"crypto_value": null,
"crypto_address": null,
"crypto_channel": null,
"crypto_received": 0,
"crypto_confirmations": 0,
"referral": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"coupon_id": null,
"custom": {},
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

List all Orders

GET
/api/v2/orders

Returns a list of the orders. The orders are sorted by creation date, with the most recently created orders being first.

  • integer
    Page number for use in pagination
List all orders
Selly::Orders.list
Response
200
[
{
"id": "d73cf5fc-466d-433e-a109-f8de4d4c70fc",
"product_id": "b3cadd729499",
"email": "[email protected]",
"ip_address": "41.117.222.111",
"country_code": "US",
"product_title": "Side Direct Filter",
"user_agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"risk_level": 0,
"status": 0,
"delivered": null,
"crypto_value": null,
"crypto_address": null,
"crypto_channel": null,
"crypto_received": 0,
"crypto_confirmations": 0,
"referral": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"coupon_id": null,
"custom": {},
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}
]

Get a Order

GET
/api/v2/orders/:id

Retrieves a Order by ID

Get a order
Selly::Orders.retrieve('d73cf5fc-466d-433e-a109-f8de4d4c70fc')
Response
200
{
"id": "d73cf5fc-466d-433e-a109-f8de4d4c70fc",
"product_id": "b3cadd729499",
"email": "[email protected]",
"ip_address": "41.117.222.111",
"country_code": "US",
"product_title": "Side Direct Filter",
"user_agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"risk_level": 0,
"status": 0,
"delivered": null,
"crypto_value": null,
"crypto_address": null,
"crypto_channel": null,
"crypto_received": 0,
"crypto_confirmations": 0,
"referral": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"coupon_id": null,
"custom": {},
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

Product Object

Attributes


  • string
    Unique identifier for the object.
  • string
    The title of the product
  • string
    The raw markdown description of the product
  • integer/string
    Current product stock stock. If product_type is 1 (unless stock_amount is set), 3 or 4, the stock will return a string of ∞
  • float
    Price of the product in the currency for 1 quantity
  • integer
    The product type. Determines the stock
  • array
    Array containing the snake case name of the gateways enabled for this product
  • string
    The ISO 4217 currency code used during checkout for this product.
  • boolean
    Product will not show up in any listings on the shop
  • boolean
    If VPNs/Proxies will be blocked during checkout
  • integer
    Maximum quantity an order can have. Defaults to null, meaning the max quantity will be as high as the stock
  • integer
    Minimum quantity an order can have. Defaults to 1
  • string
    The delimiter used to derive stock for the info attribute. Defaults to a comma
  • integer
    Current stock amount for the file product type (1). If null, the stock will be unlimited
  • object
    Product image
    Show child attributes
  • integer
    Crypto currency confirmations required for the transaction to be considered completed. Default is 1
  • integer
    Max risk level that a customer can have before the order will be blocked. Default is 30
  • string
    Dynamic URL called for dynamic product generation with the dynamic product type (3)
  • string
    The "goods" for the stock of the product. For a product_type of 2, this string is delimited by the stock_delimiter
  • object
    File that is used if the product_type is 1
    Show child attributes
  • array
    Custom input fields for the checkout form
    Show child attributes
  • string
    Webhook URL called for all order status updates for this product's orders
  • datetime
    The date and time that the resource was created.
  • datetime
    The date and time that the resource was last updated. If never updated, it will be equal to created_at.
The Product Object
{
"id": "06e53c79",
"title": "Example Product",
"description": "This is a _example_ description",
"stock": "∞",
"price": "12.99",
"currency": "USD",
"product_type": 1,
"gateways": [
"paypal",
"bitcoin",
"ethereum",
"stripe"
],
"private": false,
"unlisted": false,
"vpn_block": false,
"seller_note": null,
"maximum_quantity": null,
"minimum_quantity": 1,
"stock_delimiter": ",",
"stock_amount": null,
"image": {
"id": "363d570e0192844b7b3abcdc8a0918dc694959b3/fab7a5c54420114cc6edc2ce8336f000dc04153c",
"storage": "products",
"metadata": {
"size": 26192,
"filename": "logo.png",
"mime_type": "image/png"
},
"url": "https://cdn.selly.io/93b04f18b27b01a9dbdfa3179e7b5/68747470733a2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336663030306463303431353363"
},
"theme": 1,
"crypto_confirmations": 1,
"max_risk_level": 30,
"dynamic_url": null,
"info": null,
"file": {
"id": "73065303139323834346237623361626364633861303931386/2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336?Signature=c0f7b0155e794fab53a7769fb2cdfe24ecedf83a58fb02b81545691925ff234e",
"storage": "product_files",
"metadata": {
"size": 225894,
"mime_type": "application/zip",
"filename": "my product.zip"
},
"url": "https://cdn.selly.io/73065303139323834346237623361626364633861303931386/2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336?Signature=c0f7b0155e794fab53a7769fb2cdfe24ecedf83a58fb02b81545691925ff234e"
},
"paypal_email_delivery": false,
"webhook_url": null,
"custom": {},
"created_at": "2019-12-27T18:23:56.000+00:00",
"updated_at": "2019-12-27T18:27:15.000+00:00"
}

List all Products

GET
/api/v2/products

Returns a list of the Products. The products are sorted by creation date, with the most recently created products being first.

  • integer
    Page number for use in pagination
List all products
Selly::Products.list
Response
200
[
{
"id": "06e53c79",
"title": "Example Product",
"description": "This is a _example_ description",
"stock": "∞",
"price": "12.99",
"currency": "USD",
"product_type": 1,
"gateways": [
"paypal",
"bitcoin",
"ethereum",
"stripe"
],
"private": false,
"unlisted": false,
"vpn_block": false,
"seller_note": null,
"maximum_quantity": null,
"minimum_quantity": 1,
"stock_delimiter": ",",
"stock_amount": null,
"image": {
"id": "363d570e0192844b7b3abcdc8a0918dc694959b3/fab7a5c54420114cc6edc2ce8336f000dc04153c",
"storage": "products",
"metadata": {
"size": 26192,
"filename": "logo.png",
"mime_type": "image/png"
},
"url": "https://cdn.selly.io/93b04f18b27b01a9dbdfa3179e7b5/68747470733a2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336663030306463303431353363"
},
"theme": 1,
"crypto_confirmations": 1,
"max_risk_level": 30,
"dynamic_url": null,
"info": null,
"file": {
"id": "73065303139323834346237623361626364633861303931386/2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336?Signature=c0f7b0155e794fab53a7769fb2cdfe24ecedf83a58fb02b81545691925ff234e",
"storage": "product_files",
"metadata": {
"size": 225894,
"mime_type": "application/zip",
"filename": "my product.zip"
},
"url": "https://cdn.selly.io/73065303139323834346237623361626364633861303931386/2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336?Signature=c0f7b0155e794fab53a7769fb2cdfe24ecedf83a58fb02b81545691925ff234e"
},
"paypal_email_delivery": false,
"webhook_url": null,
"custom": {},
"created_at": "2019-12-27T18:23:56.000+00:00",
"updated_at": "2019-12-27T18:27:15.000+00:00"
}
]

Get a Product

GET
/api/v2/products/:id

Retrieves a Product by ID

Get a product
Selly::Products.retrieve('06e53c79')
Response
200
{
"id": "06e53c79",
"title": "Example Product",
"description": "This is a _example_ description",
"stock": "∞",
"price": "12.99",
"currency": "USD",
"product_type": 1,
"gateways": [
"paypal",
"bitcoin",
"ethereum",
"stripe"
],
"private": false,
"unlisted": false,
"vpn_block": false,
"seller_note": null,
"maximum_quantity": null,
"minimum_quantity": 1,
"stock_delimiter": ",",
"stock_amount": null,
"image": {
"id": "363d570e0192844b7b3abcdc8a0918dc694959b3/fab7a5c54420114cc6edc2ce8336f000dc04153c",
"storage": "products",
"metadata": {
"size": 26192,
"filename": "logo.png",
"mime_type": "image/png"
},
"url": "https://cdn.selly.io/93b04f18b27b01a9dbdfa3179e7b5/68747470733a2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336663030306463303431353363"
},
"theme": 1,
"crypto_confirmations": 1,
"max_risk_level": 30,
"dynamic_url": null,
"info": null,
"file": {
"id": "73065303139323834346237623361626364633861303931386/2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336?Signature=c0f7b0155e794fab53a7769fb2cdfe24ecedf83a58fb02b81545691925ff234e",
"storage": "product_files",
"metadata": {
"size": 225894,
"mime_type": "application/zip",
"filename": "my product.zip"
},
"url": "https://cdn.selly.io/73065303139323834346237623361626364633861303931386/2f2f73656c6c792d6465762e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f70726f64756374732f333633643537306530313932383434623762336162636463386130393138646336393439353962332f66616237613563353434323031313463633665646332636538333336?Signature=c0f7b0155e794fab53a7769fb2cdfe24ecedf83a58fb02b81545691925ff234e"
},
"paypal_email_delivery": false,
"webhook_url": null,
"custom": {},
"created_at": "2019-12-27T18:23:56.000+00:00",
"updated_at": "2019-12-27T18:27:15.000+00:00"
}

Create a Product

POST
/api/v2/products

Creates a Product and return the created Product

Arguments


  • stringRequired
    The title of the product
  • stringRequired
    The raw markdown description of the product
  • floatRequired
    Price of the product in the currency for 1 quantity
  • integerRequired
    The product type. Determines the stock
  • arrayRequired
    Array containing the snake case name of the gateways enabled for this product
  • stringRequired
    The ISO 4217 currency code used during checkout for this product.
  • boolean
    Product will not show up in any listings on the shop
  • boolean
    If VPNs/Proxies will be blocked during checkout
  • integer
    Maximum quantity an order can have. Defaults to null, meaning the max quantity will be as high as the stock
  • integer
    Minimum quantity an order can have. Defaults to 1
  • string
    The delimiter used to derive stock for the info attribute. Defaults to a comma
  • integer
    Current stock amount for the file product type (1). If null, the stock will be unlimited
  • integer
    Crypto currency confirmations required for the transaction to be considered completed. Default is 1
  • integer
    Max risk level that a customer can have before the order will be blocked. Default is 30
  • string
    Dynamic URL called for dynamic product generation with the dynamic product type (3)
  • string
    The "goods" for the stock of the product. For a product_type of 2, this string is delimited by the stock_delimiter
  • array
    Custom input fields for the checkout form
    Show child attributes
  • string
    Webhook URL called for all order status updates for this product's orders
Create a product
Selly::Products.create(
title: 'Example product',
description: 'Example description with _markdown_ support',
price: '9.99',
currency: 'USD',
gateways: ['bitcoin', 'ethereum', 'paypal'],
product_type: 2,
info: 'SERIAL1, SERIAL2, SERIAL3',
stock_delimiter: ','
)
Response
201
{
"id": "1a1ffd89",
"title": "Example product",
"description": "Example description with _markdown_ support",
"stock": 1,
"price": "9.99",
"currency": "USD",
"product_type": 2,
"gateways": [
"bitcoin",
"ethereum",
"paypal"
],
"private": false,
"unlisted": false,
"vpn_block": false,
"seller_note": null,
"maximum_quantity": null,
"minimum_quantity": 1,
"stock_delimiter": ",",
"stock_amount": null,
"image": null,
"theme": 2,
"crypto_confirmations": 1,
"max_risk_level": 30,
"dynamic_url": null,
"info": "SERIAL1, SERIAL2, SERIAL3",
"file": null,
"paypal_email_delivery": false,
"webhook_url": null,
"custom": null,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

Update a Product

PUT
/api/v2/products/:id

Update a Product by ID and return the updated Product

Arguments


  • string
    The title of the product
  • string
    The raw markdown description of the product
  • float
    Price of the product in the currency for 1 quantity
  • integer
    The product type. Determines the stock
  • array
    Array containing the snake case name of the gateways enabled for this product
  • string
    The ISO 4217 currency code used during checkout for this product.
  • boolean
    Product will not show up in any listings on the shop
  • boolean
    If VPNs/Proxies will be blocked during checkout
  • integer
    Maximum quantity an order can have. Defaults to null, meaning the max quantity will be as high as the stock
  • integer
    Minimum quantity an order can have. Defaults to 1
  • string
    The delimiter used to derive stock for the info attribute. Defaults to a comma
  • integer
    Current stock amount for the file product type (1). If null, the stock will be unlimited
  • integer
    Crypto currency confirmations required for the transaction to be considered completed. Default is 1
  • integer
    Max risk level that a customer can have before the order will be blocked. Default is 30
  • string
    Dynamic URL called for dynamic product generation with the dynamic product type (3)
  • string
    The "goods" for the stock of the product. For a product_type of 2, this string is delimited by the stock_delimiter
  • array
    Custom input fields for the checkout form
    Show child attributes
  • string
    Webhook URL called for all order status updates for this product's orders
Update a product
Selly::Products.update('1a1ffd89',
title: 'Updated title',
price: '19.49',
currency: 'EUR',
gateways: ['paypal', 'stripe']
)
Response
200
{
"id": "1a1ffd89",
"title": "Updated title",
"description": "Example description with _markdown_ support",
"stock": 1,
"price": "19.49",
"currency": "EUR",
"product_type": 2,
"gateways": [
"paypal",
"stripe"
],
"private": false,
"unlisted": false,
"vpn_block": false,
"seller_note": null,
"maximum_quantity": null,
"minimum_quantity": 1,
"stock_delimiter": ",",
"stock_amount": null,
"image": null,
"theme": 2,
"crypto_confirmations": 1,
"max_risk_level": 30,
"dynamic_url": null,
"info": "SERIAL1, SERIAL2, SERIAL3",
"file": null,
"paypal_email_delivery": false,
"webhook_url": null,
"custom": null,
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
}

Destroy a Product

DELETE
/api/v2/products/:id

Destroys a Product by ID

Destroy a product
Selly::Products.destroy('b47e307a7283')
Response
204
// No Content: 204 HTTP status

Webhook Endpoint Object

Attributes


  • string
    Unique identifier for the object.
  • string
    Webhook Endpoint URL webhooks are sent to
  • boolean
    Enabled by default. May automatically be disabled due to abuse or high error rate
  • array
    Array of events the endpoint is subscribed to
  • datetime
    The date and time that the resource was created.
  • datetime
    The date and time that the resource was last updated. If never updated, it will be equal to created_at.
The Webhook Endpoint Object
{
"id": "1206995986220584961",
"url": "https://example.com/5f68b177",
"enabled": true,
"events": [
"feedback:created",
"order:paid",
"order:updated"
],
"created_at": "2019-12-17T17:54:02.667+00:00",
"updated_at": "2019-12-17T17:54:02.667+00:00"
}

List all Endpoints

GET
/api/v2/webhooks/endpoints

Returns a list of the webhook endpoints. The webhook endpoints are sorted by creation date, with the most recently created webhook endpoints being first.

  • integer
    Page number for use in pagination
List all webhook endpoints
Selly::Webhooks::Endpoints.list
Response
200
[
{
"id": "1206995986220584961",
"url": "https://example.com/5f68b177",
"enabled": true,
"events": [
"feedback:created",
"order:paid",
"order:updated"
],
"created_at": "2019-12-17T17:54:02.667+00:00",
"updated_at": "2019-12-17T17:54:02.667+00:00"
}
]

Get a Endpoint

GET
/api/v2/webhooks/endpoints/:id

Retrieves a Webhook Endpoint by ID

Get a webhook endpoint
Selly::Webhook::Endpoints.retrieve(1206995986220584961)
Response
200
{
"id": "1206995986220584961",
"url": "https://example.com/5f68b177",
"enabled": true,
"events": [
"feedback:created",
"order:paid",
"order:updated"
],
"created_at": "2019-12-17T17:54:02.667+00:00",
"updated_at": "2019-12-17T17:54:02.667+00:00"
}

Create a Webhook Endpoint

POST
/api/v2/webhooks/endpoints

Creates a Webhook Endpoint and return the created Webhook Endpoint

Arguments


  • stringRequired
    Webhook Endpoint URL webhooks are sent to
  • arrayRequired
    Array of events the endpoint is subscribed to
Create a webhook endpoint
Selly::Webhooks::Endpoints.create(
url: 'https://example.com/5f68b177',
events: [
'feedback:created',
'order:paid',
'order:updated'
]
)
Response
201
{
"id": "1206995986220584961",
"url": "https://example.com/5f68b177",
"enabled": true,
"events": [
"feedback:created",
"order:paid",
"order:updated"
],
"created_at": "2019-12-17T17:54:02.667+00:00",
"updated_at": "2019-12-17T17:54:02.667+00:00"
}

Update a Webhook Endpoint

PUT
/api/v2/webhooks/endpoints/:id

Updates a Webhook Endpoint by ID and return the updated Webhook Endpoint

Arguments


  • string
    Webhook Endpoint URL webhooks are sent to
  • array
    Array of events the endpoint is subscribed to
Update a webhook endpoint
Selly::Webhooks::Endpoints.update(
1206995986220584961,
events: [
'order:created',
'order:paid',
'query:updated'
]
)
Response
200
{
"id": "1206995986220584961",
"url": "https://example.com/5f68b177",
"enabled": true,
"events": [
"order:created",
"order:paid",
"query:created"
],
"created_at": "2019-12-17T17:54:02.667+00:00",
"updated_at": "2019-12-17T17:54:02.667+00:00"
}

Destroy a Endpoint

DELETE
/api/v2/webhooks/endpoints/:id

Destroys a Webhook Endpoint by ID

Destroy a webhook endpoint
Selly::Webhooks::Endpoints.destroy(1206995986220584961)
Response
204
// No Content: 204 HTTP status

Webhook Log Object

Attributes


  • string
    Unique identifier for the object.
  • string
    URL the webhook is sent to
  • object
    Payload that is sent in the webhook request
  • string
    Response body
  • integer
    HTTP response status code. Will be 0 if pending
  • object
    A object containing the header name as the key and header value as the value of the response headers
  • integer
    Number of current retries
  • string
    Webhook event. Sent in all webhooks as the X-Selly-Event request header
  • integer
    Max number of retries for this webhook request
  • datetime
    Next automatic retry if a retry is required.
  • datetime
    The date and time that the resource was created.
  • datetime
    The date and time that the resource was last updated. If never updated, it will be equal to created_at.
The Webhook Log Object
{
"id": "67bLhmkZ",
"url": "https://example.com/5f68b177",
"payload": {
"id": "d73cf5fc-466d-433e-a109-f8de4d4c70fc",
"product_id": "b3cadd729499",
"email": "[email protected]",
"ip_address": "41.117.222.111",
"country_code": "US",
"product_title": "Side Direct Filter",
"user_agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"risk_level": 0,
"status": 0,
"delivered": null,
"crypto_value": null,
"crypto_address": null,
"crypto_channel": null,
"crypto_received": 0,
"crypto_confirmations": 0,
"referral": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"coupon_id": null,
"custom": {},
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
},
"response": "{\"success\":true}",
"response_code": 200,
"response_headers": {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json; charset=utf-8",
"Date": "Sat, 21 Dec 2019 18:41:54 UTC",
"X-Pd-Status": "sent to primary",
"X-Powered-By": "Express",
"Content-Length": "16",
"Connection": "Close"
},
"retries": 8,
"event": "order:created",
"retry_limit": 10,
"next_retry_at": "2019-12-21T18:51:54.000+00:00",
"created_at": "2019-12-14T17:33:36.000+00:00",
"updated_at": "2019-12-21T18:41:54.000+00:00"
}

List all Logs

GET
/api/v2/webhooks/logs

Returns a list of the webhook logs. The webhook logs are sorted by creation date, with the most recently created webhook logs being first.

  • integer
    Page number for use in pagination
List all webhook logs
Selly::Webhooks::Logs.list
Response
200
[
{
"id": "67bLhmkZ",
"url": "https://example.com/5f68b177",
"payload": {
"id": "d73cf5fc-466d-433e-a109-f8de4d4c70fc",
"product_id": "b3cadd729499",
"email": "[email protected]",
"ip_address": "41.117.222.111",
"country_code": "US",
"product_title": "Side Direct Filter",
"user_agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"risk_level": 0,
"status": 0,
"delivered": null,
"crypto_value": null,
"crypto_address": null,
"crypto_channel": null,
"crypto_received": 0,
"crypto_confirmations": 0,
"referral": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"coupon_id": null,
"custom": {},
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
},
"response": "{\"success\":true}",
"response_code": 200,
"response_headers": {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json; charset=utf-8",
"Date": "Sat, 21 Dec 2019 18:41:54 UTC",
"X-Pd-Status": "sent to primary",
"X-Powered-By": "Express",
"Content-Length": "16",
"Connection": "Close"
},
"retries": 8,
"event": "order:created",
"retry_limit": 10,
"next_retry_at": "2019-12-21T18:51:54.000+00:00",
"created_at": "2019-12-14T17:33:36.000+00:00",
"updated_at": "2019-12-21T18:41:54.000+00:00"
}
]

Get a Log

GET
/api/v2/webhooks/logs/:id

Retrieves a Webhook Log by ID

Get a webhook log
Selly::Webhook::Log.retrieve('67bLhmkZ')
Response
200
{
"id": "67bLhmkZ",
"url": "https://example.com/5f68b177",
"payload": {
"id": "d73cf5fc-466d-433e-a109-f8de4d4c70fc",
"product_id": "b3cadd729499",
"email": "[email protected]",
"ip_address": "41.117.222.111",
"country_code": "US",
"product_title": "Side Direct Filter",
"user_agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"risk_level": 0,
"status": 0,
"delivered": null,
"crypto_value": null,
"crypto_address": null,
"crypto_channel": null,
"crypto_received": 0,
"crypto_confirmations": 0,
"referral": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"coupon_id": null,
"custom": {},
"created_at": "2019-12-25T15:09:13.000+00:00",
"updated_at": "2019-12-25T15:31:40.000+00:00"
},
"response": "{\"success\":true}",
"response_code": 200,
"response_headers": {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json; charset=utf-8",
"Date": "Sat, 21 Dec 2019 18:41:54 UTC",
"X-Pd-Status": "sent to primary",
"X-Powered-By": "Express",
"Content-Length": "16",
"Connection": "Close"
},
"retries": 8,
"event": "order:created",
"retry_limit": 10,
"next_retry_at": "2019-12-21T18:51:54.000+00:00",
"created_at": "2019-12-14T17:33:36.000+00:00",
"updated_at": "2019-12-21T18:41:54.000+00:00"
}

Payment

Selly Payments provides a central implementation to accept a wide range of payment methods including PayPal, Bitcoin, Ethereum and Litecoin on your own platform.

For the gateway chosen in the Payment, you must have the correct information (e.g your PayPal email address) set in your shop payments settings.

Selly Payments supports a optional webhook_url paramater, but Webhook Endpoints will also receive all order related events.

Checkout Flows

Checkout options We currently support two types of checkout flows for Selly Payments, Integrated and White-label.

Integrated

With the integrated checkout option, Selly handles the checkout aspect for you by only returning a unique payment URL. This unique URL contains our realtime checkout page.

White-label

The white-label checkout flow provides the raw order created rather than a payment URL. With the raw order information, you are able to develop and integrate your own checkout experience completely separate of Selly.

This has the added downside of not having the realtime status updates that the integrated checkout flow offers, but this can of course be implemented on your side using the webhooks.

Create a Payment

POST
/api/v2/pay

Creates a Payment and return the created Payment

Arguments


  • stringRequired
    Title of the product shown on the checkout page
  • stringRequired
    Customer's email address
  • stringRequired
    The ISO 4217 currency code used for this payment
  • floatRequired
    Value/price of the payment in the currency specified
  • stringRequired
    Payment gateway. E.g PayPal, Bitcoin, Litecoin, etc.
  • integer
    Number of crypto currency confirmations required for the payment to be considered complete. 0-6. Defaults to 1
  • boolean
    If set to true, the payment will use the white label checkout flow and return the order object rather than a redirection URL
  • string
    Customer's IP address used if white_label is true
  • stringRequired
    Only required if white_label is false. The URL the customer is redirected to after payment
  • string
    Order status webhooks will be sent to this URL. Webhook Endpoints will receive any and all events regarding the order, so the webhook_url is not required
Create a payment
Selly::Pay.create(
title: 'Selly Pay Example',
gateway: 'Bitcoin',
value: 10.00,
currency: 'USD',
return_url: 'https://website.com/return'
)
Response
201
{
"url": "https://selly.io/pay/81971eae19ff0924026d7b2a7502b20372c15df5/bGU3Q09QSGtDNjR2cHJMYzhHdTd6Mm40bXpFNVdZOEtlaW9NckRySmxsVkZOSjhkb3N0SVM0cVF6UDJtU0NjejVrT0Q4ZFZKY1JVbi9ZTjJaSDhGRXc9PS0tdW5zUGptYjcrSGZSRjF5K0VmNUFNZz09--68ab83743fa057629b09bb9c7330841e54442784"
}
Create a white-label payment
Selly::Pay.create(
title: 'Selly Pay Example',
gateway: 'Bitcoin',
value: 10.00,
currency: 'USD',
white_label: true
)
Response
201
{
"id": "16d37578-ced4-4a18-90c7-596a8e472e69",
"status": 0,
"crypto_address": null,
"crypto_value": null,
"confirmations_needed": 6,
"product_id": "pay",
"email": "[email protected]",
"value": "10.0",
"quantity": 1,
"currency": "USD",
"gateway": "PayPal",
"crypto_channel": null,
"usd_value": "10.0",
"exchange_rate": "1.0",
"created_at": "2018-04-21T13:21:19.000+01:00",
"updated_at": "2018-04-21T13:21:19.000+01:00",
"url": "https://www.paypal.com/webscr?cmd=_ap-payment&paykey=AP-5U570312BD011483Y"
}

Destroy a Payment

DELETE
/api/v2/pay/:id

Destroys a Payment by ID

Destroy a payment
Selly::Pay.destroy('81971eae19ff0924026d7b2a7502b20372c15df5')
Response
204
// No Content: 204 HTTP status