This document describes the API calls available as part of the Paytunia v1 API.
The API is shared by both Bitcoin-Central.net and Paytunia.com. Both apps run against the same database, therefore using the API against one of them is equivalent to using the API against the other.
If your language of choice is Ruby we recommend using the Paytunia gem instead of writing your own client.
- [Authentication](#authentication) - [Base URL](#base-url) - [Formats and required HTTP request headers](#formats-and-required-http-request-headers) - [Rate-limiting](#rate-limiting) - [Pagination](#pagination) - [HTTP response header](#http-response-header) - [Controlling pagination](#controlling-pagination) - [Localization](#localization) - [Error handling](#error-handling) - [Successful calls](#successful-calls) - [Account](#account) - [Get balances (A)](#get-balances-a) - [Account operations](#account-operations) - [Get the detail of an account operation (A)](#get-the-details-of-an-account-operation-a) - [Get a list of account operations (A,P)](#get-a-list-of-account-operations-ap) - [Send money](#send-money) - [Send Bitcoins (A)](#send-bitcoins-a) - [Send money to an e-mail address (A)](#send-money-to-an-e-mail-address-a) - [Quotes](#quotes) - [Create a quote (A)](#create-a-quote-a) - [View a quote (A)](#view-a-quote-a) - [List quotes (A,P)](#list-quotes) - [Pay a quote (A)](#pay-a-quote-a) - [Execute a quote (A)](#execute-a-quote-a) - [Invoices](#invoices) - [View an invoice (A)](#view-an-invoice-a) - [View an invoice (Public)](#view-an-invoice-public) - [List invoices (A,P)](#list-invoices-ap) - [Create an invoice (A)](#create-an-invoice-a) - [Payment buttons and creation through signed GET request](#payment-buttons-and-creation-through-signed-get-request) - [Payment callbacks](#payment-callbacks) - [Trading](#trading) - [Place an order (A)](#place-an-order-a) - [Cancel an order (A)](#cancel-an-order-a) - [View trades for an order (A)](#view-trades-for-an-order-a) - [View an order (A)](#view-an-order-a) - [List active orders (A,P)](#list-active-orders-ap) - [List all orders (A,P)](#list-all-orders-ap) - [Read the ticker](#read-the-ticker) - [Read the market depth](#read-the-market-depth) - [Read historical trades](#read-historical-trades-p) - [Coupons](#coupons) - [Create a coupon (A)](#create-a-coupon-a) - [View a coupon](#view-a-coupon) - [Redeem a coupon (A)](#redeem-a-coupon-a)Calls that require authentication are marked with "A" in the call description title.
Authentication and authorization may be done with :
- HTTP Basic
- OAuth2
OAuth2 is useful when it is not desirable for client apps to handle the user's credentials directly or when it is necessary to have access to an account with limited privileges.
Each API call description mentions the OAuth2 scope required to use it.
The available OAuth2 scopes are :
Scope | Description |
---|---|
read | Read transaction history, balances and profile information |
withdraw | Perform API calls that result in money being sent or withdrawn from the account |
trade | Manage trade orders (create, read, cancel) |
merchant | Manage invoices, read merchant dashboard and data |
devices | Manage devices |
In order to test OAuth2 integration a test app is available.
Application parameter | Value |
---|---|
Application ID | 6fcf1c32f6e14cd773a7a6640832bdbf83a5b2b8d4382e839c6aff83a8f1bb3b |
Application secret | 55554ecad5627f0465034c4a116e59a38d9c3ab272487a18404078ccc0b64798 |
Callback URL | urn:ietf:wg:oauth:2.0:oob |
After authorization the authorization token will be directly displayed in your browser (that's what the special test callback URL is for).
Example authorization link : https://bitcoin-central.net/oauth/authorize?client_id=6...pe=code
Full usage example :
This example uses the OAuth2 Ruby gem.
require 'oauth2'
client = OAuth2::Client.new('6fcf1c32f6e14cd773a7a6640832bdbf83a5b2b8d4382e839c6aff83a8f1bb3b', '55554ecad5627f0465034c4a116e59a38d9c3ab272487a18404078ccc0b64798', site: 'https://bitcoin-central.net')
client.auth_code.authorize_url(redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', scope: 'read trade')
=> "https://bitcoin-central.net/oauth/authorize?response_type=code&client_id=6fcf1c32f6e14cd773a7a6640832bdbf83a5b2b8d4382e839c6aff83a8f1bb3b&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=read+trade"
# Visit this URL in your browser, approve the request and copy the authorization code
authorization_code = '...'
token = client.auth_code.get_token(authorization_code, redirect_uri: 'urn:ietf:wg:oauth:2.0:oob')
token.get('/api/v1/trade_orders/active').body
=> [{"uuid":"148ab996-ab63-45cc-b240-99c78bb18a11","instructed_amount":300.0,"amount":268.70563158,"state":"active","created_at":"2013-02-07T19:09:44+01:00","updated_at":"2013-02-14T13:12:00+01:00","price":15.9199,"type":"buy"}]
If you encounter SSL certificate errors while trying this example it's probably because your Ruby install doesn't know where to find the CA certificates. In development you can use an incredibly ugly hack to temporarily skip SSL certificate validation : OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
. You should never do this in production.
The base URL for all calls is https://bitcoin-central.net
. A complete URL would look like this https://bitcoin-central.net/api/v1/quotes/3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d
.
The API will only answer with JSON or empty responses. It expects parameters to be passed in JSON with the correct Content-Type: application/json
being set.
API calls are rate-limited by IP to 5000 calls per day. Information about the status of the limit can be found in the X-RateLimit-Limit
and X-RateLimit-Remaining
HTTP headers.
Example response with rate-limit headers
HTTP/1.1 200
Content-Type: application/json; charset=utf-8
X-Ratelimit-Limit: 5000
X-Ratelimit-Remaining: 4982
Date: Wed, 30 Jan 2013 12:08:58 GMT
Some API calls returning collections may be paginated. In this case the call description title mentions it.
Calls that return paginated data are marked with "P" in the call description title.
Calls that return paginated collections will add a Pagination
HTT header to the response. It will contain a pagination meta-data JSON object.
Pagination header example
{
// Whether the current page is the first of the collection
"first_page": true,
// Total amount of available pages
"total_pages": 1,
// Previous page number
"previous_page": null,
// Total number of items in the collection
"total": 1,
// Next page number
"next_page": null,
// Whether the current page is the last available one
"last_page": true,
// Record collection offset
"offset": 0
}
Optional pagination parameters may be passed in the request URI in order to control the way the collection gets paginated. If parameters are incorrect a HTTP 400 Bad request status is returned along with an empty body.
Parameter | Default | Acceptable values |
---|---|---|
page | 1 | Positive integer >0 |
per_page | 20 | Positive integer >=5 and <=100 |
The relevant results and error messages will be localized to the language associated to the user, currently English and French are supported.
Datetime values will be returned as regular JSON format and Unix timestamps, the timestamps are suffixed with _int
.
Whenever an error is encountered, the answer to a JSON API call will have :
- An HTTP 422 status (Unprocessable entity) or HTTP 400 (Bad request),
- A JSON array of localized error messages as body
If the API call was successful, the platform will answer with :
- An HTTP 200 status (OK) or HTTP 201 (Created),
- A JSON representation of the entity being created or updated if relevant
This call will return the balances in all currencies.
This call requires the read
OAuth2 scope.
Request path : /api/v1/balances
Request method : GET
Request parameters
None
Response
A JSON object with the following attributes is returned :
Name | Type | Description |
---|---|---|
EUR | Decimal | EUR balance |
USD | Decimal | USD balance |
GBP | Decimal | GBP balance |
BTC | Decimal | BTC balance |
Example request : GET /api/v1/balances
Example response :
{
"EUR" : 1.0,
"BTC" : 1.42,
"USD" : 0.0,
"GBP" : 0.0
}
An account operation is any ledger operation that changes the account's balance.
These calls require the read
OAuth2 scope.
This call will return the details of a single account operation, the response contains : the UUID identifying the operation, the amount of this particular operation, its currency, its creation timestamp, its state (if relevant), a string indicating the type of the operation and the account balance that this operation led to (the sum of all transactions in the same currency including this one but not the ones that came after it).
Request path : /api/v1/account_operations/{uuid}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | UUID of the account operation |
Response
A JSON object with the following attributes is returned :
Name | Type | Description |
---|---|---|
uuid | UUID | UUID of the account operation |
amount | Decimal | Amount of the operation (1) |
currency | String | Currency of the operation (2) |
created_at | Datetime | Timestamp of operation creation |
state | String | Operation state if relevant, null otherwise (3) |
type | String | Operation type (4) |
balance | Decimal | Balance this operation led to |
- Credits are expressed as positive amounts, debits are expressed as negative amounts
- See currencies table
- See states table
- See operation types table
Example request : GET /api/v1/account_operations/3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"amount" : 50.0,
"currency" : "EUR",
"created_at" : "2013-01-14T16:28:57Z",
"created_at_int" : 1363858355,
"state" : null,
"type" : "wire_deposit",
"balance" : 550.0
}
This call will return a paginated list of account operations relative to the authenticated account.
Request path : /api/v1/account_operations
Request method : GET
Request parameters
None
Response
A JSON array of account operations is returned. The structure collection elements is detailed at "Get the details of an account operation".
Example request : GET /api/v1/account_operations
Example response :
[
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"amount" : 50.0,
"currency" : "EUR",
"created_at" : "2013-01-14T16:28:57Z",
"created_at_int" : 1363858355,
"state" : null,
"type" : "wire_deposit",
"balance" : 550.0
},
{
"uuid" : "b3c08962-4dc3-9ffc-4dc3-3a7bc1b2ff4d",
"amount" : 500.0,
"currency" : "EUR",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"state" : null,
"type" : "wire_deposit",
"balance" : 500.0
}
]
These calls require the withdraw
OAuth2 scope.
This call will perform a Bitcoin transaction.
Request path : /api/v1/transfers/send_bitcoins
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
amount | Decimal | Amount to send |
address | String | Recipient's Bitcoin address |
Response
An UUID
is returned after the request is queued for execution. It enables the client to make subsequent status check requests.
Example request : POST /api/v1/transfers/send_bitcoins
{
"amount" : 10.0,
"address" : "1KfNzSKFAmpC4kNYaGLqj8LGPHxGmRG2nZ"
}
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d"
}
This call will move money to the account identified with the given e-mail address. If no such account is found an e-mail gets sent inviting its recipient to create an account, or sign-in to one to retrieve the sent funds. If the amount isn't claimed after a week the funds are returned to the sender.
Request path : /api/v1/transfers/send_to_email
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
amount | Decimal | Amount to send |
currency | String | Currency in which the amount is expressed |
address | String | Recipient's e-mail address |
Response
An UUID
is returned after the request is queued for execution. It enables the client to make subsequent status check requests.
Example request : POST /api/v1/transfers/send_bitcoins
{
"amount" : 10.0,
"currency" : "EUR",
"address" : "[email protected]"
}
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d"
}
Quotes are a mechanism for clients to send funds or exchange them to other currencies. They provide clients with a guaranteed fixed-rate at which the system will convert their funds before crediting them to their account or send them out.
The canonical use of a quote is to pay in currency to a Bitcoin invoice, materialized as a QR code :
- User scans Bitcoin QR code
- Client app extracts requested Bitcoin amount
- Client app requests a quote for this Bitcoin amount to the API and provides the currency in which debit upon quote payment
- A guaranteed rate is returned by the API
- Client app shows price expressed in the user's currency
- After user confirmation the client app instructs the API to pay the quote to a specific Bitcoin address
- The merchant receives the payment in Bitcoin and the user is debited in his native currency
These calls require the trade
OAuth2 scope, the Pay a quote action requires the withdraw
scope.
This call will create a quote. When doing so clients must specify a currency (the other currency is always assumed to be "BTC") an amount they are requesting and a direction. Combining these parameters in various ways will have the system address a wide array of use cases.
For example a client can request :
- How much BTC would need to be sold to get exactly 10 EUR
- How much BTC could be bought with 10 EUR
- How much EUR would the sale of 1 BTC get
- How much EUR would be required to buy 1 BTC
To obtain the relevant quote a client would pass the following parameters :
Case | Currency | direction | requested_btc_amount | requested_currency_amount |
---|---|---|---|---|
1 | EUR | sell | N/A | 10 |
2 | EUR | buy | N/A | 10 |
3 | EUR | sell | 1 | N/A |
4 | EUR | buy | 1 | N/A |
Request path : /api/v1/quotes
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
requested_currency_amount | Decimal | Constrain on the currency amount (1) |
requested_btc_amount | Decimal | Constrain on the Bitcoin amount (1) |
direction | String | Whether the quote should apply to a sale or a purchase of Bitcoins (2) |
currency | String | Currency in which the requested_amount is expressed |
- Exactly one of the currencies must be constrained, the other parameter may be omitted
- Acceptable values are
buy
andsell
Response
A JSON object with the following parameters is returned. If the current market depth or volatility does not allow for a quote to be given an error will be returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
requested_currency_amount | Decimal | The instructed currency amount or null |
requested_btc_amount | Decimal | The instructed Bitcoin amount or null |
direction | String | The direction you provided |
currency_amount | Decimal | The quoted currency amount or null |
btc_amount | Decimal | The quoted Bitcoin amount or null |
rate | Decimal | The quoted exchange rate |
valid_until | Datetime | The timestamp at which this quote will be invalidated |
created_at | Datetime | The creation date timestamp |
executed | Boolean | Whether this quote has already been settled or paid |
Example request : POST /api/v1/quotes
This demonstrates how to obtain a quote as described in the example use case #1.
{
"requested_amount" : 10.0,
"currency" : "EUR",
"direction" : "sell"
}
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"currency" : "EUR",
"direction" : "sell",
"rate" : 10.65
"currency_amount" : null,
"btc_amount" : 0.93896714
"requested_currency_amount" : 10,
"requested_btc_amount" : null,
"valid_until" : "2013-01-10T13:00:50Z",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"executed" : false
}
This call will return a JSON object representing a quote
Request path : /api/v1/quotes/{uuid}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
Response
A JSON object with the following parameters is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
requested_currency_amount | Decimal | The instructed currency amount or null |
requested_btc_amount | Decimal | The instructed Bitcoin amount or null |
direction | String | The direction you provided |
currency_amount | Decimal | The quoted currency amount or null |
btc_amount | Decimal | The quoted Bitcoin amount or null |
rate | Decimal | The quoted exchange rate |
valid_until | Datetime | The timestamp at which this quote will be invalidated |
created_at | Datetime | The creation date timestamp |
executed | Boolean | Whether this quote has already been settled or paid |
Example request : GET /api/v1/quotes/3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"currency" : "EUR",
"direction" : "sell",
"rate" : 10.65
"currency_amount" : null,
"btc_amount" : 0.93896714
"requested_currency_amount" : 10,
"requested_btc_amount" : null,
"valid_until" : "2013-01-10T13:00:50Z",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"executed" : false
}
This call will return a paginated list of quotes for the client account.
Request path : /api/v1/quotes
Request method : GET
Request parameters
N/A
Response
A JSON array of quote objects is returned.
Example request : GET /api/v1/quotes
Example response :
[
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"currency" : "EUR",
"direction" : "sell",
"rate" : 10.65
"currency_amount" : null,
"btc_amount" : 0.93896714
"requested_currency_amount" : 10,
"requested_btc_amount" : null,
"valid_until" : "2013-01-10T13:00:50Z",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"executed" : true
},
{
"uuid" : "4dc33a7bc1b2-9b7e-3a7b-9ffc-b3c08962ff4d",
"currency" : "EUR",
"direction" : "sell",
"rate" : 10.65
"currency_amount" : null,
"btc_amount" : 0.93896714
"requested_currency_amount" : 10,
"requested_btc_amount" : null,
"valid_until" : "2013-01-10T13:00:50Z",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"executed" : true
}
]
This action applies only to quotes for buying BTC.
It will perform the exchange creating a user account debit of the calculated currency_amount
or instructed requested_currency_amount
and send out the calculated btc_amount
or instructed requested_btc_amount
to the Bitcoin address in the address
field.
Calling this method queues the quote for payment if possible. The quote status can later be queried using the view a quote call.
Request path : /api/v1/quotes/{uuid}/pay
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
address | String | Valid Bitcoin address |
Response
The quote as it was when the payment was requested is returned.
Example request : GET /api/v1/quotes/3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d/pay
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"currency" : "EUR",
"direction" : "sell",
"rate" : 10.65
"currency_amount" : null,
"btc_amount" : 0.93896714
"requested_currency_amount" : 10,
"requested_btc_amount" : null,
"valid_until" : "2013-01-10T13:00:50Z",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"executed" : false
}
This action applies to quotes for buying and selling BTC. It will perform the exchange creating user account debit and credit operations depending on the quote requested.
Calling this method queues the quote for execution if possible. The quote status can later be queried using the view a quote call.
Request path : /api/v1/quotes/{uuid}/execute
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
Response
The quote as it was when the execution was requested is returned.
Example request : POST /api/v1/quotes/3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d/execute
Example response :
{
"uuid" : "3a7bc1b2-9b7e-4dc3-9ffc-b3c08962ff4d",
"currency" : "EUR",
"direction" : "sell",
"rate" : 10.65
"currency_amount" : null,
"btc_amount" : 0.93896714
"requested_currency_amount" : 10,
"requested_btc_amount" : null,
"valid_until" : "2013-01-10T13:00:50Z",
"created_at" : "2013-01-10T12:45:50Z",
"created_at_int" : 1363858355,
"executed" : false
}
Invoices are requests for payment. They can be expressed in any arbitrary currency. They all get a unique Bitcoin payment address assigned and a Bitcoin amount calculated from the requested currency amount.
Payment can be made by sending the btc_amount
amount of Bitcoins to the payment_address
address or directly in the requested currency from another account. The invoice payment will trigger a POST
to the callback_url
.
These calls require the merchant
OAuth2 scope.
This call will return a JSON object representing an invoice
Request path : /api/v1/invoices/{uuid}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
Response
A JSON object with the following parameters is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Invoice identifier |
state | String | Invoice state (see appendix) |
payment_address | String | Bitcoin payment address |
payment_bitcoin_\uri | String | Payment URI, should be used to generate QR codes |
amount | Decimal | Requested amount to be credited upon payment |
btc_amount | Decimal | Payable amount expressed in BTC |
amount_to_pay | Decimal | Amount left to pay |
btc_amount_to_pay | Decimal | Bitcoin amount amount left to pay |
currency | String | Currency in which the amount is expressed |
merchant_reference | String | Merchant reference |
merchant_memo | String | Merchant memo |
callback_url | String | URL to which a callback should be made when the invoice is paid |
item_url | String | Order-related URL |
paid_at | Datetime | Payment timestamp |
created_at | Datetime | Creation timestamp |
updated_at | Datetime | Update timestamp |
expires_at | Datetime | Expiration timestamp |
settled | Boolean | Has this invoice already been credited ? |
notification_email_sent | Boolean | Has the notification e-mail already been sent ? |
public_url | String | The URL at which this invoice is publicly visible and payable |
Example request : GET /api/v1/invoices/70c7936b-f8ce-443a-8338-3762de0a1e92
Example response :
{
"uuid": "70c7936b-f8ce-443a-8338-3762de0a1e92",
"amount": 10.0,
"amount_to_pay": 10.0,
"btc_amount": 1.021732,
"btc_amount_to_pay": 1.021732,
"notification_email_sent": false,
"callback_url": null,
"created_at": "2013-01-21T10:20:07Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"expires_at": "2013-01-21T10:40:07Z",
"item_url": null,
"merchant_memo": null,
"merchant_reference": null,
"paid_at": null,
"payment_address": "1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz",
"payment_bitcoin_uri" : "bitcoin:1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz?amount=100.0&label=&x-pay-curamt=100.0&x-pay-cur=BTC&x-pay-id=7653453d-6372-4ffa-bc56-1e3182ef7f35",
"settled": false,
"state": "pending",
"updated_at": "2013-01-21T10:20:07Z",
"public_url": "https://paytunia.com/invoices/70c7936b-f8ce-443a-8338-3762de0a1e92"
}
It is the same call as the above one, except this call will return a subset of the JSON object representing an invoice.
Request path : /api/v1/invoices/{uuid}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Quote identifier |
Response
A JSON object with the following parameters is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Invoice identifier |
state | String | Invoice state (see appendix) |
payment_address | String | Bitcoin payment address |
amount | Decimal | Requested amount to be credited upon payment |
btc_amount | Decimal | Payable amount expressed in BTC |
currency | String | Currency in which the amount is expressed |
merchant_reference | String | Merchant reference |
merchant_memo | String | Merchant memo |
item_url | String | Order-related URL |
paid_at | Datetime | Payment timestamp |
created_at | Datetime | Creation timestamp |
updated_at | Datetime | Update timestamp |
expires_at | Datetime | Expiration timestamp |
Example request : GET /api/v1/invoices/70c7936b-f8ce-443a-8338-3762de0a1e92
Example response :
{
"uuid": "70c7936b-f8ce-443a-8338-3762de0a1e92",
"amount": 10.0,
"btc_amount": 1.021732,
"callback_fired": false,
"callback_url": null,
"created_at": "2013-01-21T10:20:07Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"expires_at": "2013-01-21T10:40:07Z",
"item_url": null,
"merchant_memo": null,
"merchant_reference": null,
"paid_at": null,
"payment_address": "1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz",
"payment_bitcoin_uri" : "bitcoin:1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz?amount=100.0&label=&x-pay-curamt=100.0&x-pay-cur=BTC&x-pay-id=7653453d-6372-4ffa-bc56-1e3182ef7f35",
"settled": false,
"state": "pending",
"updated_at": "2013-01-21T10:20:07Z"
}
This call will return a paginated list of invoices for the client account.
Request path : /api/v1/invoices
Request method : GET
Request parameters
N/A
Response
A JSON array of invoice objects is returned.
Example request : GET /api/v1/quotes
Example response :
[
{
"uuid": "8338936b-f8ce-443a-70c7-3762de0a1e92",
"amount": 10.0,
"btc_amount": 1.021732,
"callback_fired": false,
"callback_url": null,
"created_at": "2013-01-21T10:20:07Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"expires_at": "2013-01-21T10:40:07Z",
"item_url": null,
"merchant_memo": null,
"merchant_reference": null,
"paid_at": null,
"payment_address": "1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz",
"settled": false,
"state": "pending",
"updated_at": "2013-01-21T10:20:07Z"
},
{
"uuid": "70c7936b-f8ce-443a-8338-3762de0a1e92",
"amount": 10.0,
"btc_amount": 1.021732,
"callback_fired": false,
"callback_url": null,
"created_at": "2013-01-21T10:20:07Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"expires_at": "2013-01-21T10:40:07Z",
"item_url": null,
"merchant_memo": null,
"merchant_reference": null,
"paid_at": null,
"payment_address": "1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz",
"settled": false,
"state": "pending",
"updated_at": "2013-01-21T10:20:07Z"
}
]
This call creates an invoice
Request path : /api/v1/invoices
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
amount | Decimal | Requested amount to be credited upon payment |
currency | String | Currency in which the amount is expressed |
merchant_reference | String | Merchant reference (optional) |
merchant_memo | String | Merchant memo (optional) |
callback_url | String | URL to which a callback should be made when the invoice is paid (optional) |
item_url | String | Order-related URL (optional) |
Response
An invoice JSON object is returned.
Example request : POST /api/v1/invoices
{
"amount" : 10.0,
"currency" : "EUR"
}
Example response :
{
"uuid": "70c7936b-f8ce-443a-8338-3762de0a1e92",
"amount": 10.0,
"btc_amount": 1.021732,
"callback_fired": false,
"callback_url": null,
"created_at": "2013-01-21T10:20:07Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"expires_at": "2013-01-21T10:40:07Z",
"item_url": null,
"merchant_memo": null,
"merchant_reference": null,
"paid_at": null,
"payment_address": "1JnjJNhdKSgvMKr6xMbqVEudB3eACsGJSz",
"settled": false,
"state": "pending",
"updated_at": "2013-01-21T10:20:07Z"
}
This approach can be used when it is not desirable to create invoices before presenting them to the user, to create payment buttons, or when the previous flow is not practical.
The approach will let a merchant securely redirect a customer to a the payment page that will generate an invoice on the fly for this particular request.
The URL includes :
- The merchant's account number,
- A
query
parameter describing the payment, - A unique token used to make these invoice creations non-replayable,
- A signature string created by hashing a shared secret along with the invoice data
The current value of the shared secret for each account is available on the account details page.
All parameters are passed in the query-string.
Request path : /api/v1/invoices/create_unauthenticated
Request method : GET
Request parameters
Name | Value |
---|---|
merchant | Merchant account number |
token | A globally unique token, a random UUID is recommended |
query | The invoice parameters |
signature | The SHA256 hash of merchant + shared_secret + token + query |
Building the query parameter
The query
parameter is created by building a string with parameters separated with the pipe character "|". Optional parameters may use a blank value.
The parameters should be concatenated according to the following model :
AMOUNT_IN_CENTS|CURRENCY|MERCHANT_REFERENCE|MERCHANT_MEMO|CALLBACK_URL|ITEM_URL
For example, to create a payment for 12.58 EUR with the "123456" reference and https://example.com/callback
callback URL the query should look like this :
1258|EUR|123456||https://example.com/callback|
A merchant wishes to display a link redirecting to a Paytunia payment page, his shared secret is 792fae4f81c12764c4e4f570920fbe89
, he wishes to create an invoice for 10 EUR with the reference "SALE-42" and a "Hello world" merchant memo, his account number is "PY-123456". The URLs are https://example.com/callback
and https://merchant.com/orders/SALE-42
First, the query
parameter must be constructed, it should look like :
1000|EUR|SALE-42|Hello world|https://example.com/callback|https://merchant.com/orders/SALE-42
Then a unique token should be generated, a random UUID is perfect, we'll use 46113b61-1590-447a-9bab-ceb4a5586aa9
The signature should then be generated by hashing the following string with SHA256 :
# Hashed string
PY-123456792fae4f81c12764c4e4f570920fbe8946113b61-1590-447a-9bab-ceb4a5586aa91000|EUR|SALE-42|Hello world|https://example.com/callback|https://merchant.com/orders/SALE-42
# Signature generated in command-line
$ echo -n "PY-123456792fae4f81c12764c4e4f570920fbe8946113b61-1590-447a-9bab-ceb4a5586aa91000|EUR|SALE-42|Hello world|https://example.com/callback|https://merchant.com/orders/SALE-42" | sha256sum
-> 8e26068a13cbf81dac5ddca203897bbafc5a227411b36771cebcf7aad693d0ab
Finally, the full URL can be generated by appending the URL-encoded parameters as following :
https://bitcoin-central.net/api/v1/invoices/create_unauthenticated?merchant=PY-123456&token=46113b61-1590-447a-9bab-ceb4a5586aa9&signature=8e26068a13cbf81dac5ddca203897bbafc5a227411b36771cebcf7aad693d0ab&query=PY-123456792fae4f81c12764c4e4f570920fbe8946113b61-1590-447a-9bab-ceb4a5586aa91000%7CEUR%7CSALE-42%7CHello+world%7Chttps%3A%2F%2Fexample.com%2Fcallback%7Chttps%3A%2F%2Fmerchant.com%2Forders%2FSALE-42
When a payment is received for an invoice the backend will perform an HTTP POST to the URL given as callback_url
. The content-type for the request will be application/x-www-form-urlencoded
.
The parameters sent are the exact same as the ones returned by a view invoice.
The callback is not guaranteed to be fired and may be fired multiple times, the receiver must take it into account when designing a proper handling logic.
A X-Paytunia-Signature
header is added to all callback requests. Its purpose is to authenticate the call from the backend to the callback URL, this signature must be properly checked by the receiving server in order to ensure that the request is legitimate and hasn't been tampered with.
The signature is computed by concatenating the raw request body with the client's shared secret and applying a SHA256 hash function to it.
Example signed callback request :
In this example the client secret is 792fae4f81c12764c4e4f570920fbe89
.
POST / HTTP/1.1
Accept: */*
User-Agent: Ruby
Content-Type: application/x-www-form-urlencoded
X-Paytunia-Signature: ab9c3b33631e40d2880b2c4cf5bdf894bf42d6ea115dd2de71277e4382aaaeab
Connection: close
Host: lvh.me:3000
Content-Length: 642
uuid=cbfb237f-dd9e-47bd-b18b-73b2f4ccdb51&state=paid&btc_amount=100.0&payment_address=1FXWhKPChEcUnSEoFQ3DGzxKe44MDbat0.42903373550437307&payment_bitcoin_uri=bitcoin%3A1FXWhKPChEcUnSEoFQ3DGzxKe44MDbatz%3Famount%3D0.0%26label%3D%26x-pay-cur%3DBTC%26x-pay-id%3Dcbfb237f-dd9e-47bd-b18b-73b2f4ccdb51&callback_url=http%3A%2F%2Flvh.me%3A3000%2F&paid_at=2013-02-08+12%3A22%3A39+UTC&created_at=2013-02-08+12%3A22%3A39+UTC&updated_at=2013-02-08+12%3A22%3A39+UTC&merchant_reference&merchant_memo&item_url¬ification_email_sent=true¤cy=BTC&amount=100.0&settled=false&expires_at=2013-02-08+12%3A42%3A39+UTC&amount_to_pay=0.0&btc_amount_to_pay=0.0
In Ruby this signature can be easily checked by doing Digest::SHA2.hexdigest(data + secret)
where data
is the raw request body and secret
is the client's shared secret.
Account specific calls require the trade
OAuth2 scope.
This call will place a trade order and queue it for execution.
Request path : /api/v1/trade_orders
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
amount | Decimal | Amount of Bitcoins to trade |
currency | String | Currency to trade against |
price | Decimal | Price (may be omitted to place a market order) |
type | String | Must be buy (bid) or sell (ask) |
Response
An trade order JSON object is returned with the following parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Trade order identifier |
amount | Decimal | Remaining Bitcoin amount to trade |
instructed_amount | Decimal | Amount of Bitcoins to trade |
currency | String | Currency to trade against |
price | Decimal | Price (null for a market order) |
type | String | Either buy or sell |
created_at | Datetime | Creation timestamp |
updated_at | Datetime | Update timestamp |
Example request : POST /api/v1/trade_orders
{
"amount" : 10.0,
"type" : "buy",
"currency" : "EUR"
}
Example response :
{
"amount": 10.0,
"currency": "EUR",
"type": "buy",
"created_at": "2013-01-21T22:07:15Z",
"created_at_int" : 1363858355,
"instructed_amount": 10.0,
"price": null,
"currency": "EUR",
"state": "pending_execution",
"updated_at": "2013-01-21T22:07:15Z",
"uuid": "8b3c3446-9c5d-48a8-8044-08622cd4607b"
}
This call will enqueue a cancel order job to remove it from the order book.
Request path : /api/v1/trade_orders/{uuid}
Request method : DELETE
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Trade order identifier |
Example request : DELETE /api/v1/trade_orders/8b3c3446-9c5d-48a8-8044-08622cd4607b
Example response :
N/A
This call will return a collection of trades that were executed for a particular order.
Request path : /api/v1/trade_orders/{uuid}/trades
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Trade order identifier |
Response
An array of trade JSON objects is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Trade identifier |
traded_currency | Decimal | Amount traded, expressed in currency |
traded_btc | Decimal | Amount of Bitcoins traded |
currency | String | Currency in which traded_currency is expressed |
price | Decimal | Price at which the exchange was made |
created_at | Datetime | Creation timestamp |
Example request : GET /api/v1/trade_orders/8b32ddf1-1675-4ed3-b1bb-b4efc4ecd98c/trades
Example response :
[
{
"created_at": "2013-01-22T08:19:41Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"price": 5.0,
"traded_btc": 980.0,
"traded_currency": 4940.0,
"uuid": "1c86abf0-170a-4101-84d1-cdad913c95dd"
},
{
"created_at": "2013-01-22T08:19:41Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"price": 6.0,
"traded_btc": 10.0,
"traded_currency": 60.0,
"uuid": "170aabf0-1c86-4101-84d1-cdad913c95dd"
}
]
This call will return a trade order JSON object.
Request path : /api/v1/trade_orders/{uuid}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
uuid | UUID | Order identifier |
Response
A JSON object with the following parameters is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Trade order identifier |
amount | Decimal | Remaining Bitcoin amount to trade |
instructed_amount | Decimal | Amount of Bitcoins to trade |
currency | String | Currency to trade against |
price | Decimal | Price (null for a market order) |
type | String | Either buy or sell |
created_at | Datetime | Creation timestamp |
updated_at | Datetime | Update timestamp |
Example request : GET /api/v1/trade_orders/8b32ddf1-1675-4ed3-b1bb-b4efc4ecd98c
Example response :
{
"amount": 10.0,
"type": "buy",
"created_at": "2013-01-22T08:19:37Z",
"created_at_int" : 1363858355,
"instructed_amount": 1000.0,
"currency": "EUR",
"price": 11.0,
"state": "active",
"updated_at": "2013-01-22T08:19:41Z",
"uuid": "8b32ddf1-1675-4ed3-b1bb-b4efc4ecd98c"
}
This call will return a paginated list of the client's executable trade orders (pending_execution
, active
or insufficient_funds
states).
Request path : /api/v1/trade_orders/active
Request method : GET
Request parameters
N/A
Example request : GET /api/v1/trade_orders/active
Example response :
[
{
"amount": 10.0,
"currency": "EUR",
"type": "buy",
"created_at": "2013-01-21T22:15:38Z",
"created_at_int" : 1363858355,
"instructed_amount": 10.0,
"price": null,
"state": "pending_execution",
"updated_at": "2013-01-21T22:15:38Z",
"uuid": "52823408-972f-4551-acc5-e7d3f032c6d5"
}
]
This call will return a paginated list of the client's trade orders.
Request path : /api/v1/trade_orders
Request method : GET
Request parameters
N/A
Example request : GET /api/v1/trade_orders
Example response :
[
{
"amount": 10.0,
"currency": "EUR",
"type": "buy",
"created_at": "2013-01-21T22:15:38Z",
"created_at_int" : 1363858355,
"instructed_amount": 10.0,
"price": null,
"state": "pending_execution",
"updated_at": "2013-01-21T22:15:38Z",
"uuid": "52823408-972f-4551-acc5-e7d3f032c6d5"
},
{
"amount": 10.0,
"currency": "EUR",
"type": "buy",
"created_at": "2013-01-21T22:15:40Z",
"created_at_int" : 1363858355,
"instructed_amount": 10.0,
"price": null,
"state": "canceled",
"updated_at": "2013-01-21T22:15:40Z",
"uuid": "6e3ea778-9ef7-4e4f-9910-85e735f7b42a"
}
]
This call will return the ticker.
Request path : /api/v1/ticker/{currency}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
currency | String | Show the ticker for the given currency, default to EUR if ommitted |
Example request : GET /api/v1/ticker/eur
Alternate example : GET /api/v1/ticker
Example response :
{
"ask": 20.4,
"at": 1361056527,
"bid": 20.1,
"currency": "EUR",
"high": 20.74,
"low": 20.2,
"midpoint": 20.25,
"price": 20.2,
"variation": -1.4634,
"volume": 148.80193218
}
This call will return the full sorted market depth. If the currency
parameter is omitted, the currency defaults to EUR.
The asks are sorted by ascending price and the bids by descending price.
Request path : /api/v1/depth
or /api/v1/depth/{currency}
Request method : GET
Request parameters
N/A
Example request : GET /api/v1/depth/eur
Example response :
{
"asks": [
{
"amount": 0.48762,
"currency": "EUR",
"price": 24.48996,
"timestamp": 1361925287
},
{
"amount": 12.96657232,
"currency": "EUR",
"price": 24.49,
"timestamp": 1361924964
}
],
"bids": [
{
"amount": 0.77372456,
"currency": "EUR",
"price": 24.05,
"timestamp": 1361902889
},
{
"amount": 0.40491093,
"currency": "EUR",
"price": 24.001,
"timestamp": 1361887469
}
]
}
This call will return the most recent trades
Request path : /api/v1/trades/{currency}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
currency | String | Currency filter, defaults to EUR if omitted |
Response
An array of trade JSON objects is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Trade identifier |
traded_currency | Decimal | Amount traded, expressed in currency |
traded_btc | Decimal | Amount of Bitcoins traded |
currency | String | Currency in which traded_currency is expressed |
price | Decimal | Price at which the exchange was made |
created_at | Datetime | Creation timestamp |
Example request : GET /api/v1/trades/eur
Example response :
[
{
"created_at": "2013-01-22T08:19:41Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"price": 5.0,
"traded_btc": 980.0,
"traded_currency": 4940.0,
"uuid": "1c86abf0-170a-4101-84d1-cdad913c95dd"
},
{
"created_at": "2013-01-22T08:19:41Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"price": 6.0,
"traded_btc": 10.0,
"traded_currency": 60.0,
"uuid": "170aabf0-1c86-4101-84d1-cdad913c95dd"
}
]
Coupons are a way to easily move money between accounts, they are debited from the issuer's account upon creation and may be redeemed at anytime against any account (including the issuer).
They are materialized by a unique redemption code. This code should be kept private as anyone having knowledge of it can redeem the funds.
Creating a coupon requires the withdraw
OAuth2 scope, other actions require the read
scope.
This call issues a coupon
Request path : /api/v1/coupons
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
amount | Decimal | Currency value for the issued coupon |
currency | String | Currency in which the amount is expressed |
Response
A coupon code is returned
Example request : POST /api/v1/coupons
{
"amount" : 12.0,
"currency" : "EUR"
}
Example response :
{
"code": "BP-EUR-9660407B43799CCED320"
}
This call will return a JSON object representing a coupon
Request path : /api/v1/coupons/{code}
Request method : GET
Request parameters
Name | Type | Description |
---|---|---|
code | String | Coupon code |
Response
A JSON object with the following parameters is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Coupon account operation identifier |
code | String | Coupon code |
state | String | Coupon state (see appendix) |
amount | Decimal | Coupon value |
currency | String | Currency in which the amount is expressed |
created_at | Datetime | Creation timestamp |
Example request : GET /api/v1/coupons/BP-EUR-9660407B43799CCED320
Example response :
{
"amount": -12.0,
"code": "BP-EUR-9660407B43799CCED320",
"created_at": "2013-01-30T11:52:36Z",
"created_at_int" : 1363858355,
"currency": "EUR",
"state": "pending",
"uuid": "c21adaf6-f5a2-4d93-a762-a63b89b52265"
}
This call will a redeem a coupon to the client's account. It returns an UUID
, this identifier can be used to request details about the account operation created for the client's account by the redemption of the coupon (credit of the coupon value).
This call may be used to void a coupon by redeeming it against the account that issued it.
Request path : /api/v1/coupons/redeem
Request method : POST
Request parameters
Name | Type | Description |
---|---|---|
code | String | Coupon code |
Response
A JSON object with the following parameters is returned.
Name | Type | Description |
---|---|---|
uuid | UUID | Redemption account operation identifier |
Example request : POST /api/v1/coupons
{
"code": "BP-EUR-9660407B43799CCED320"
}
Example response :
{
"uuid": "3e0004cd-158c-40d6-b8f9-f4b672e86308"
}
The following currencies are available :
Symbol | Currency |
---|---|
BTC | Bitcoin |
EUR | Euro |
GBP | Pound Sterling |
USD | US Dollar |
Type | Description |
---|---|
fee | Trading fee |
coupon | Issue of a redeemable code |
bitcoin_transfer | Bitcoin withdrawal |
wire_transfer | Wire transfer withdrawal |
email_transfer | Transfer of funds to an e-mail address |
coupon_redemption | Redemption of a redeemable code |
email_transfer_redemption | Redemption of an e-mail transfer |
charge | Generic charge |
bank_charge | Bank charge |
invoice_credit | Payment of an invoice you issued (credits your account) |
invoice_payment | Payment for an invoice (debits your account) |
wire_deposit | Deposit by bank wire |
trade | Trade |
reversal | Reversal |
The state of a transfer lets you check whether it has been sent out to the underlying network (banking network or Bitcoin network).
State | Description |
---|---|
pending | The transfer hasn't been sent out yet |
processed | The transfer has been sent out |
State | Description |
---|---|
pending | The coupon is valid and may be redeemed |
redeemed | The coupon has already been redeemed |
canceled | The coupon was redeemed to the issuer |
State | Description |
---|---|
pending_collection | The recipient hasn't claimed the e-mail transfer amount yet |
canceled | The e-mail transfer was canceled |
expired | The transfer has expired |
unreachable_receiver | An error occurred while sending the e-mail notification to its recipient |
processed | The recipient has collected the sent amount |
State | Description |
---|---|
pending | The invoice is pending payment |
partially_paid | The invoice has a partially confirmed payment |
confirming | A full or over-payment is confirming |
paid | The invoice has a confirmed payment |
overpaid | The invoice has a confirmed over-payment |
error | The payment could not be converted as requested |
State | Description |
---|---|
pending_execution | The order has been queued for execution |
active | The order has been executed but not filled it is visible in the order book (1) |
filled | The order has been filled |
canceled | The order has been canceled |
insufficient_funds | The order cannot execute further due to lack of funds (2) |
- The amount shown in the order book is the amount that is actually executable given your balance, not necessarily the instructed amount
- Order execution resumes as soon as more funds are available
- Document the socket.io API
- Get an estimate (unsaved quote)
- Add a
/me
API call - Add a call for account balances
- Add order lag