LocalBitcoins API Documentation

You can use the LocalBitcoins API to automate trading activities and built apps.

Not a programmer?

API stands for Application Programmer Interface. As such, this document only really makes sense if you are, in fact, a programmer.

Here's a good Python tutorial to get you started. You'll also need to know how to make HTTP requests and read JSON responses to get any use out of the API.

Table of Contents

Getting started

Available clients and example projects

You can find several LocalBitcoins API clients for different programming languages (PHP, Ruby, Go, Java) on Github.

Authentication

The core of the API is authentication. LocalBitcoins API has two options how to authenticate API calls and manage their access permissions.

  • The first option is HMAC - recommended if you are automatizing trading activities. HMAC authentication is used by many Bitcoin exchanges. It is secure option, as every request is signed separately making it immune access token leak attacks.
  • The second option is OAuth 2 - recommended if you want to distribute your applications to third party (e.g. mobile apps). Popular social networks as well as other Web heavyweights use OAuth 2. There are many OAuth2 tutorials out there for most use cases.
  • There are public listing and market data APIs which do not need authentication. Please refer to them at the end of this documentation.

Creating authentication, app and permissions

Using the LocalBitcoins Apps Dashboard Login required you can create the necessary credentials for HMAC or OAuth2 to configure your application and begin using our API.

There are the following permissions you can request as the scope:

  • read - read user-owned data.
  • write - make changes to ads, contacts, etc. but do not send or release bitcoins.
  • money - spend and release bitcoins on behalf of the user, at any time.
  • money_pin - spend and release bitcoins on behalf of the user, authorized with a PIN code.

In OAuth 2, you can always reauthorize with the user if you need a larger scope, so please prefer using low-scope tokens as much as possible. Especially the money scope should be handled with caution: it allows draining the user's wallet.

Apps that don't need to initiate spending bitcoins when the API user is offline should prefer the money_pin scope, which enforces that the user's currently active PIN code is provided at the call time.

You can request multiple scopes at the same time by concatenating them together with spaces separating them, e.g. read write.

Keep the OAuth 2 client secret actually secret!

If you're making a mobile or browser-based app, make sure to never place the client secret in the hands of your user.

You can (and really, should ASAP) regenerate a new secret if the old one leaks out.

Calling

The second core part of our API is actually calling the API. While each API call has some special considerations (we'll come to them later) every call has common conventions.

  1. All arguments are given application/x-www-form-urlencoded. Most programming languages know how to urlencode with standard functions.

    In Python one can use urllib.urlencode. Example: urllib.urlencode({"foo": "bar", "baz": "quux"} to get ?foo=bar&baz=quux.

  2. Every API call must be either signed with HMAC or provided with OAuth 2 access_token argument.
  3. If there are any signing problems with HMAC, an error code from 41 to 43 is returned.
  4. If the access_token is expired or revoked, the API will return with an error code of 3. Your application should try to get a new access token and retry. Other error codes are generally unrecoverable unless specified. How is the error returned? Please sit tight, we'll deal with return values next.

Return values

Finally, for closure. Return values are UTF-8 encoded JSON with the following metadata structure, which corresponds to an API call with the message return value:

{
  "data": {"message": "Hello World!"}
}

On the top level JSON object metadata fields may show up in the future.

If the API call ended in an unrecoverable error, there is no data top level field. This helps against accidentally using an error message as legitimate data, creating confusing situations. Errors will also return with an appropriate HTTP error code. Typically if the API is called with invalid data a 400 Bad Request response is returned, but other HTTP error codes can be returned as well.

Instead there is an error field that contains an object with the fields error_code and message. The error object can contain more fields if specified on the error documentation. The error_code field is meant to be read by the application, the message field is meant to be human readable. An example error return object:

{
  "error": {
    "message": "A strange error occurred!",
    "error_code": 7
  }
}

Error list

The full list of errors is here.

Pagination

Sometimes there are too many values to return at once. In this case all values are still available using pagination.

Pagination lives in the pagination field of the returned JSON object. If there are no other pages, the field is undefined. If this page is the first one, the pagination field only defines a next field. If this page is the last one, there is only a prev field defined likewise. On intermediate pages the pagination object contains both next and prev fields.

The next and prev fields are URLs pointing to the respective page. They are usable as is. Example paginated return value:

{
  "data": {
    "ad_list": ...
  },
  "pagination": {
    "next": "https://localbitcoins.com/api/ads/?id__gt=50"
  }
}

It is not possible to configure the maximum amount of items returned at a time. There is no concept of page numbers either, beside that one page is the first one, another the last one, and the rest are intermediate.

Limiting Returned Fields

In APIs returning contacts or ads, the data fields returned can be specified. Use a request parameter of fields, which is a comma-separated list of field names. Only those fields will be returned in the data.

If the fields parameter is not given, all fields are returned. If an empty fields parameter is given, no data fields are returned. If specifying fields that do not exist in the source data, no error is given: those fields just aren't returned.

The fields specified only affect the data structure, actions, pagination etc. are not affected.

HMAC Signatures to requests

HMAC is based on a secret code that only you and LocalBitcoins knows. This secret is used to sign your API calls, so we can be sure it's really you who is making the calls. You also need to add a nonce to your request. Nonce is a special integer number, that needs to increase in every API call. It causes identical API calls to have different signature thus making impossible to copy your calls and execute them later.

You can use Apps Dashboard Login required to create API authentications. They are pairs of key and secret with permission information. You are encouraged to create multiple API authentications, for example one for each of your applications that needs to have an access to your LocalBitcoins account.

Calculating signature

In HMAC, a message is signed with secret using some hashing algorithm to get signature. Message is formed by concatenating these four strings:

  1. Nonce. A 63 bit positive integer, for example unix timestamp as milliseconds.
  2. API authentication key. This is the first one of a key/secret pair.
  3. Relative path, for example /api/wallet/.
  4. GET or POST parameters in their URL encoded format, for example foo=bar&baz=quux.
Secret is got from Apps Dashboard along with the key. Hashing algorithm is SHA256.

A Python example of this can be seen below:

  message = str(nonce) + api_auth_key + relative_path + get_or_post_params_urlencoded
  signature = hmac.new(api_auth_secret, msg=message, digestmod=hashlib.sha256).hexdigest().upper()

Sending signature

Signature is sent via HTTP headers. A total of three fields are needed:

  1. Apiauth-Key: API authentication key.
  2. Apiauth-Nonce: The nonce in this particular request.
  3. Apiauth-Signature: HMAC signature.

OAuth 2: Server-Side Web Application Authorization Flow

This section describes how to integrate your Web application with LocalBitcoins API. This is just basic three-way OAuth2, it works the same way everywhere.

Errors that can occur can be referenced from the OAuth2 RFC.

/oauth2/authorize/

Context: User's Browser

Required arguments: client_id, response_type=code

Optional arguments: state, scope

Access token scope: None

The currently logged in LocalBitcoins user is asked to authorize the client identified by client_id. If the user allows the authorization, the user is redirected to your client's redirect_uri property. Set a proper user-accessible redirect_uri in the Apps Dashboard Login required.

To the redirect endpoint, two extra query parameters are given: state and code. It is highly recommended to use the state parameter for csrf protection. You need the code value for the next step.

/oauth2/access_token/

Context: Client's Web Server

Required arguments: code, grant_type=authorization_code, client_id, client_secret

Access token scope: None

On success, a JSON response is returned to the client:

{
  "access_token": a valid access token,
  "scope": scope as given in authorize,
  "expires_in": seconds to expiry,
  "refresh_token": a token that can be used to get a new access token
}

You should keep using the access_token for expires_in seconds.

/oauth2/access_token/ (Refresh token usage)

Context: Client's Web Server

Required arguments: refresh_token, grant_type=refresh_token, client_id, client_secret

Access token scope: None

On success, a JSON response is returned to the client:

{
  "access_token": a valid access token,
  "scope": scope as given in authorize,
  "expires_in": seconds to expiry,
  "refresh_token": a token that can be used to get a new access token
}

Consuming a refresh token will immediately expire the related access token. Refresh tokens are single-use. A new refresh token is returned from this call, ready for consumption later.

OAuth 2: Browser Application Authorization Flow

Native, browser and mobile applications run on the user's hardware. This flow does not use a client secret. This API is therefore called only from the user's context.

The user visits the LocalBitcoins site to authorize, first doing whatever steps necessary to log in. If everything goes well, the user is redirected to the app's redirect_uri.

Errors that can occur can be referenced from the OAuth2 RFC.

/oauth/authorize/

Required arguments: response_type=token, client_id, redirect_uri

Optional arguments: scope

If the user chooses to authorize, the user is redirected to redirect_uri with the token available in the fragment, urlencoded to the access_token key. The flow ends here, the token can be collected and used for up to expires_in seconds, also in the fragment.

OAuth 2: Console Application Authorization Flow

There is also a username+password auth flow available at /oauth2/authorize/. It's not recommended for anything but simple console agents because the application itself can access the username and password and do anything with them, for example sending them to the author. It's standard Oauth2 though.

/oauth2/access_token/

Required arguments: client_id, client_secret, username, password, grant_type=password

Optional arguments: None

If successful, JSON like so will be returned immediately:

{
  "access_token": the access token,
  "scope": "read",
  "expires_in": seconds to expiry,
  "refresh_token": a refresh token
}

Authenticated API reference

Now that you have an access token handy, we can finally get to the actual API.

API Table of Contents

/api/account_info/{username}/

Required arguments: None

Access token scope: Public

Returns public user profile information as follows:

{
  "data": {
     "username": "bitcoinbaron",
     "trading_partners_count": 0,
     "feedbacks_unconfirmed_count": 0,
     "trade_volume_text": "Less than 25 BTC",
     "has_common_trades": false,
     "confirmed_trade_count_text": "0",
     "blocked_count": 0,
     "feedback_count": 0,
     "url": "https://localbitcoins.com/p/bitcoinbaron/",
     "trusted_count": 0
   }
}

Errors in the new values are reported in the errors key.

    {"error": {"message": "Invalid username."}}

/api/myself/

Required arguments: None

Access token scope: Read

HTTP Method: GET

Return the information of the currently logged in user (the owner of authentication token). The format is the same as in account_info method.

{
  "data": {
     "username": "bitcoinbaron",
     "trading_partners_count": 0,
     "feedbacks_unconfirmed_count": 0,
     "trade_volume_text": "Less than 25 BTC",
     "has_common_trades": false,
     "confirmed_trade_count_text": "0",
     "blocked_count": 0,
     "feedback_count": 0,
     "url": "https://localbitcoins.com/p/bitcoinbaron/",
     "trusted_count": 0
   }
}

/api/pincode/

Required arguments: pincode

Access token scope: Read

HTTP Method: POST

Checks the given PIN code against the user's currently active PIN code. You can use this method to ensure the person using the session is the legitimate user.

Due to only requiring the read scope, the user is not guaranteed to have set a PIN code. If you protect your application using this call, please make the user input his valid PIN code in order to enable the feature.

/api/dashboard/

Required arguments: None

Access token scope: Read

HTTP Method: GET

Produces a list of contacts on the data key: contact_list. This collection of APIs mirrors the website's dashboard, allowing access to contacts in different states.

URL Contacts returned
/api/dashboard/ Open and active contacts
/api/dashboard/released/ Released (successful) contacts
/api/dashboard/canceled/ Canceled contacts
/api/dashboard/closed/ Closed contacts, both released and canceled

In addition all of these listings have buyer/ and seller/ sub-listings to view contacts where the token owner is either buying or selling, respectively. E.g. /api/dashboard/buyer/. Normally all contacts where the token owner is participating are returned.

Structure of common values to all contacts is follows:

{
  "data": {
    "created_at": "2013-12-06T15:23:01.61",
    "buyer": {
        "username": "hylje",
        "trade_count": "30+",
        "feedback_score": "100",
        "name": "hylje (30+; 100)",
        "last_seen_on": "2013-12-19T08:28:16+00:00"
    }
    "seller": {
        "username": "jeremias",
        "trade_count": "100+",
        "feedback_score": "100",
        "name": "jeremias (100+; 100)",
        "last_seen_on": "2013-12-19T06:28:51+00:00"
    }
    "reference_code": "123",
    "currency": "EUR",
    "amount": "105.55",
    "amount_btc": "190",
    "exchange_rate_updated_at": "2013-06-20T15:23:01+00:00",
    "advertisement": {
       "id": 123,
       "trade_type": "ONLINE_SELL"
       "advertiser": {
           "username": "jeremias",
           "trade_count": "100+",
           "feedback_score": "100",
           "name": "jeremias (100+; 100)",
           "last_seen_on": "2013-12-19T06:28:51.604754+00:00"
       }
    },
    "contact_id": 1234
    "canceled_at": null,
    "escrowed_at": "2013-12-06T15:23:01+00:00",
    "funded_at": "2013-12-06T15:23:01+00:00",
    "disputed_at": null,
    "closed_at": null,
    "released_at": null,
    "is_buying": true,
    "is_selling": false,
    "account_details": ! see below
  },
  "actions": {
    "mark_as_paid_url": "/api/contact_mark_as_paid/1/",
    "advertisement_public_view": "/ads/123",
    "message_url": "/api/contact_messages/1234",
    "message_post_url": "/api/contact_message_post/1234"
  }
}

Notes on common fields

The created_at field is an ISO formatted UTC datetime.

The amount (denominated in currency) and amount_btc fields are string representations of Decimals, both set at the time of creation of the escrow. The exchange rate between the two fields was last looked up at exchange_rate_updated_at.

is_buying and is_selling are shortcuts that indicate that the token owner is the buyer or seller in this contact.

canceled_at, escrowed_at, funded_at, disputed_at, closed_at and released_at are all either datetimes or null, reflecting the progress of the contact along the trade. Once a trade enters a state (a datetime is set) it will never unset the state.

Extra fields by contact trade type / user role

Contact trade type(s) Buyer/seller Key path About
Online sell and online buy Buyer and seller data.advertisement.payment_method Online payment method. See /api/payment_methods/ for up-to-date options. E.g. SEPA
Online buy Buyer and seller data.account_details
{
  "receiver_name": "John Doe",
  "iban": iban account number
  "swift_bic": bank identification code
  "reference": "789"
}

See more on the Account Details heading below.

Online buy Buyer only actions.mark_as_paid_url URL to API that marks this contact as paid.
All contacts with escrow enabled and funded Seller only actions.release_url URL to API that releases this contact's escrow
All contacts with escrow enabled but not funded Seller only actions.fund_url URL to API that attempts to fund this contact's escrow
Buyer and seller data.is_funded

Boolean signaling if the escrow is enabled and not funded.

Note: If escrow is not enabled, this value is unset.

Conditional fields for all contacts

In all contacts, actions key may also have dispute_url available if the contact is eligible for dispute. Or a cancel_url if the contact is eligible for canceling.

About account_details

account_details contains a payment method specific set of payment information supplied by the seller.

See the current list of payment details information supported on LocalBitcoins

Pagination

All dashboard contact listings paginate. See the section on pagination.

Old API

This API replaces an old API that only worked on active contacts. The old API will work for the foreseeable future, but it is undocumented. Please migrate to this API first if you need to change things around the old API.

/api/contact_release/{contact_id}/

Required arguments: None

Access token scope: Money

HTTP Method: POST

Releases the escrow of contact specified by ID {contact_id}. On success there's a complimentary message on the data key. The flow ends here.

/api/contact_release_pin/{contact_id}/

Required arguments: pincode

Access token scope: Money_pin

HTTP Method: POST

Releases the escrow of contact specified by ID {contact_id}. On success there's a complimentary message on the data key. The flow ends here.

/api/contact_mark_as_paid/{contact_id}/

Required arguments: None

Optional arguments: None

Access token scope: Read+Write

Marks a contact as paid. It is recommended to access this API through /api/online_buy_contacts/ entries' action key.

/api/contact_messages/{contact_id}/

Required arguments: None

Optional arguments: None

Access token scope: Read

Reads all messaging from the contact. Messages are on the message_list key. The structure of a message is as follows:

{
    "msg": "message body",
    "sender": {
        "id": 123,
        "name": "bitcoinbaron (0)",
        "username": "bitcoinbaron",
        "trade_count": 0,
        "last_seen_on": "2013-12-17T03:31:12.382862+00:00"
    },
    "created_at": "2013-12-19T16:03:38.218039",
    "is_admin": false,
    "attachment_name": "cnXvo5sV6eH4-some_image.jpg",
    "attachment_type": "image/jpeg",
    "attachment_url": "https://localbitcoins.com/api/..."
}

attachment_* fields exist only if there is an attachment. Downloading attachments require Read scope and GET method.

/api/contact_message_post/{contact_id}/

Required arguments: msg

Optional arguments: None

Access token scope: Read+Write

HTTP Method: POST

Posts a message to the contact. No file uploads, sorry.

/api/contact_dispute/{contact_id}/

Required arguments: None

Optional arguments: None

Access token scope: Read+Write

HTTP Method: POST

Starts a dispute with the contact, if possible

/api/contact_cancel/{contact_id}/

Required arguments: None

Optional arguments: None

Access token scope: Read+Write

HTTP Method: POST

Cancels the contact, if possible

/api/contact_fund/{contact_id}

Required arguments: None

Optional arguments: None

Access token scope: Read+Write

HTTP Method: POST

Attempts to fund an unfunded local contact from the seller's wallet.

/api/contact_create/{ad_id}/

Required arguments: amount

Optional arguments: message

Access token scope: Read+Write

HTTP Method: POST

Attempts to create a contact to trade bitcoins.

Amount is a number in the advertisement's fiat currency.

Returns the API URL to the newly created contact at actions.contact_url. Whether the contact was able to be funded automatically is indicated at data.funded. Only non-floating LOCAL_SELL may return unfunded, all other trade types either fund or fail.

ONLINE_BUY may have additional fields you need to provide depending on the advertisement's payment method.

/api/contact_info/{contact_id}/

Required arguments: None

Optional arguments: None

Access token scope: Read

HTTP Method: GET

Gets information about a single contact you are involved in. Same fields as in /api/contacts/.

/api/contact_info/

Required arguments: contacts

Optional arguments: None

Access token scope: Read

HTTP Method: GET

contacts is a comma-separated list of contact IDs that you want to access in bulk. The token owner needs to be either a buyer or seller in the contacts, contacts that do not pass this check are simply not returned.

A maximum of 50 contacts can be requested at a time.

The contacts are not returned in any particular order.

/api/wallet/

Required arguments: None

Optional arguments: None

Access token scope: Read

Gets information about the token owner's wallet balance. The information is as follows:

{
  "message": "OK",
  "total": {
    "balance": "0.05",
    "sendable": "0.05"
  },
  "sent_transactions_30d": [
    {"txid": ...
     "amount": "0.05",
     "description": "Internal send",
     "tx_type": 5,
     "created_at": "2013-12-20T15:27:36+00:00"
  }
  ],
  "received_transactions_30d": [...],
  "receiving_address_count": 1,
  "receiving_address_list": [{
    "address": "15HfUY9LwwewaWwrKRXzE91tjDnHmye1hc",
    "received": "0.0"
  }]
}

The transaction lists are for the last 30 days. There is no LocalBitcoins API to fetch older transactions than that.

Transaction types

Transactions in the Wallet API have several types. Currently the more elaborate types cover sends. All received transactions are of type 3.

Type Summary Extra fields
1 Send to_address: the recipient Bitcoin address
2 Pending Send. The transaction processor has not yet published a transaction containing this send to the Bitcoin network, but will do so as quickly as possible. to_address: the to-be-recipient Bitcoin address
3 Other transactions, e.g. received transactions. See the description field.
4 Bitcoin network fees
5 Internal send to another LocalBitcoins wallet

/api/wallet-balance/

Required arguments: None

Optional arguments: None

Access token scope: Read

Same as /api/wallet/ above, but only returns the message, receiving_address_list and total fields. (There's also a receiving_address_count but it is always 1: only the latest receiving address is ever returned by this call.)

Use this instead if you don't care about transactions at the moment.

/api/wallet-send/

Required arguments: address and amount

Optional arguments: None

Access token scope: Money

HTTP Method: POST

Sends amount bitcoins from the token owner's wallet to address.

Note that this API requires its own API permission called Money.

On success, this API returns just a message indicating success.

It is highly recommended to minimize the lifetime of access tokens with the money permission. Call /api/logout/ to make the current token expire instantly.

/api/wallet-send-pin/

Required arguments: address, amount and pincode

Optional arguments: None

Access token scope: Money_PIN

HTTP Method: POST

As above, but needs the token owner's active PIN code to succeed.

Look before you leap. You can check if a PIN code is valid without attempting a send with /api/pincode/.

Security concern: To get any security beyond the above API, do not retain the PIN code beyond a reasonable user session, a few minutes at most. If you are planning to save the PIN code anyway, please save some headache and get the real no-pin-required money permission instead.

/api/wallet-addr/

Access token scope: Money

HTTP Method: POST

Gets an unused receiving address for the token owner's wallet, its address given in the address key of the response. Note that this API may keep returning the same (unused) address if called repeatedly.

/api/logout/

Access token scope: Read

HTTP Method: POST

Expires the current access token immediately. To get a new token afterwards, public apps will need to reauthenticate, confidential apps can turn in a refresh token.

/api/ads/

Required arguments: None

Optional arguments for filtering: visible (0 for false, 1 for true), trade_type (one of LOCAL_SELL, LOCAL_BUY, ONLINE_SELL, ONLINE_BUY), currency and countrycode.

Access token scope: Read

Lists the token owner's all ads on the data key ad_list, optionally filtered. If there's a lot of ads, the listing will be paginated. Refer to the ad editing pages for the field meanings. List item structure is like so:

{
    "data": {
         "visible": boolean,
         "email": valid e-mail string or null,
         "location_string": human-readable location identifier string,
         "countrycode": countrycode string, two letters,
         "city": city name,
         "trade_type": string, often one of LOCAL_SELL, LOCAL_BUY, ONLINE_SELL, ONLINE_BUY,
         "online_provider": payment method string e.g. NATIONAL_BANK,
         "first_time_limit_btc": string representation of a decimal or null,
         "volume_coefficient_btc": string repr of a decimal,
         "age_days_coefficient_limit": string repr of a decimal,
         "sms_verification_required": boolean
         "reference_type": string, e.g. SHORT,
         "currency": three letter string,
         "account_info": string,
         "lat": float,
         "lon": float,
         "min_amount": string repr of a decimal or null,
         "max_amount": string repr of a decimal or null,
         "ad_id": primary key of the ad,
         "temp_price_usd": current price per BTC in USD,
         "profile": {
             "username": advertisement owner's profile username,
             "name": username, trade count and feedback score combined,
             "last_seen_on": user last seen, ISO formatted date,
             "trade_count": number of trades for user,
             "feedback_score": int
         }
         "require_feedback_score": 50,
         "require_trade_volume": null,
         "bank_name": string,
         "track_max_amount": boolean,
         "atm_model": string or null,
    },
    "actions": {
         "public_view": URL to view this ad's public HTML page
    }
}

If the advertisement's owner is the same user as the token owner, there are more fields in addition to the above:

{
    "data": {
        ...
        "price_equation": string
    },
    "actions": {
        ...
        "html_edit": URL to view this ad's HTML edit page
                     that has more options than the API change_form does
        "change_form": URL to change this ad
    }
}

If the token owner can create a contact on the advertisement, the contact form URL is also given.

{
    ...
    "actions": { "contact_form": URL to contact form API for this ad }
}

Note that ATM advertisements are also returned by the API. Contacts cannot generally be created on ATM ads. You should check for the existence of a contact_form action.

For ONLINE_BUY ads a is_low_risk value is given. If true, the ad has the green thumb.

min_amount and max_amount are in denominated in currency.

/api/ad-get/{ad_id}/

Required arguments: None

Optional arguments: None

Gets a single ad based on ID, with the same fields as above.

If ad is found, returns the ad within a list structure like above. However, returns an error if the ad is not viewable for any reason instead of returning an empty list.

/api/ad-get/

Required arguments: ads

Optional arguments: None

HTTP method: GET

Gets all visible ads from the comma-separated list of ad IDs. Invisible ads are simply not returned here. Otherwise works the same way as above.

Max 50 ads returned at a time.

The ads are not returned in any particular order.

/api/ad/{ad_id}/ Editing
/api/ad-create/ Creation

Required arguments: min_amount, max_amount, price_equation, lat, lon, city, location_string, countrycode, currency, account_info, bank_name, msg, sms_verification_required, track_max_amount, require_trusted_by_advertiser, require_identification
For creation only: trade_type and online_provider
For editing only: visible

HTTP method: POST

Updates the ad with given information. Note that only the listed fields above can be updated with the API, use the web site to change the rest of them.

NOTE Omitting field keys, such as min_amount or max_amount, will unset them. There is no other way to unset the values. You may want to pass through all fields from the /api/ads/ records you're editing.

Errors in the new values are reported in the errors key. If there are any errors, no changes will be made to the ad.

/api/ad-delete/{ad_id}/

Required arguments: None

Access token scope: Read+Write

HTTP method: POST

Deletes ad.

/api/merchant/new_invoice/

Required arguments: currency, amount, description

Optional arguments: return_url

Access token scope: Read

HTTP method: POST

Creates new invoice. currency is a three letter currency code, for example USD. For more information how invoices work, check Merchant dashboard. You can check response structure from API call /api/merchant/invoice/{invoice_id}/

After invoice has been created, you need to deliver its URL to your customer or redirect him/her to it.

You can use return_url to redirect customers automatically back to your site. Redirection happens after invoice has been paid.

If redirecting fails for some reason, the customer can also click return link manually. Make sure it does not cause problems if the return_url is visited multiple times.

Also note, that return_url is not guaranteed to stay secret from the customer, so do not consider the invoice been paid when the URL is being visited. Instead use API call /api/merchant/invoice/{invoice_id}/ to check payment.

/api/merchant/invoice/{invoice_id}/

Required arguments: None

Access token scope: Read

HTTP method: GET

Shows information about specific invoice you have created. Example result can be seen below:

{
    "data": {
        "invoice": {
            "description": "Stuff",
            "created": "2014-09-11T09:34:30.867980",
            "url": "https://localbitcoins.com/merchant/invoice/VD1j3VP7MSjTJjxaptjnFN",
            "amount": "4.99",
            "currency": "EUR",
            "state": "NOT_OPENED",
            "id": "VD1j3VP7MSjTJjxaptjnFN",
            "btc_amount": null,
            "deleting_allowed": true
        }
    }
}

State is one of these: NOT_OPENED, WAITING_FOR_PAYMENT, PAID, DIDNT_PAID, PAID_IN_LATE, PAID_PARTLY, PAID_AND_CONFIRMED, PAID_IN_LATE_AND_CONFIRMED.

/api/merchant/invoices/

Required arguments: None

Access token scope: Read

HTTP method: GET

Lists all invoices. If there is a lot of invoices, the listing will be paginated. Data structure is described below. invoice_list contains objects that are identical to those in API call /api/merchant/invoice/{invoice_id}/.

{
    "data": {
        "invoice_list": ...
    },
    "pagination": {
       "next": "https://localbitcoins.com/api/invoices/?..."
    }
}

/api/merchant/delete_invoice/{invoice_id}/

Required arguments: None

Access token scope: Read+Write

HTTP method: POST

Deletes specific invoice, if it is possible. Deleting invoices is possible when it is sure that receiver cannot accidentally pay the invoice at the same time when merchant is deleting it. You can use API call /api/merchant/invoice/{invoice_id}/ to check if deleting is possible.

Public market data API

LocalBitcoins.com provides public trade data available for market chart services and tickers. The API is in bitcoincharts.com format.

Currently supported currencies: ARS, AUD, BRL, CAD, CHF, CZK, DKK, EUR, GBP, HKD, ILS, INR, MXN, NOK, NZD, PLN, RUB, SEK, SGD, THB, USD, ZAR

Tickers for all currencies

https://localbitcoins.com/bitcoinaverage/ticker-all-currencies/

Trades

https://localbitcoins.com/bitcoincharts/{currency}/trades.json
  • All closed trades in online buy and online sell categories, updated every 15 minutes
  • The maximum batch size is of a fetch is 500 entries. Use ?since= parameter with the last tid to iterate more.

Orderbook

https://localbitcoins.com/bitcoincharts/{currency}/orderbook.json
  • Buy and sell bitcoin online advertisements. Amount is the maximum amount available for the trade request. Price is the hourly updated price. The price is based on the price equation and commission % entered by the ad author.
  • No batching

Public ad listing API

To search for ads, please see the Public API docs.