HodlHodl API Documentation (v1)

Notice: in order to use API you should enable it in your account preferences.

Authorization

Use API key from your account preferences and add the following header to each request:

Authorization: Bearer <your_api_key>

The next endpoints are public and do not require API key:

  • GET /api/v1/countries

  • GET /api/v1/currencies

  • GET /api/v1/offers

  • GET /api/v1/offers/:id

  • GET /api/v1/payment_methods

“Signed request”

If you want to provide release_address in Creating contract request, you have to “sign” the request.

To sign the request:

  • Get current time as Unix timestamp (integer). Convert that number to a string (using the usual decimal representation, e.g. you should get "1596026883" if current time is 2020-07-29 12:48:03 UTC). We’ll refer to that string as nonce.
  • Retrieve Signature Key from the user (which could be obtained at “API Access” tab of “Account settings” section of the website when API access is enabled). If you want to save Signature Key for further usage (i.e. to not request user to enter Signature Key each time it’s required) you should explicitly warn the user that that would allow your service/application to directly access user’s funds. We’ll refer to Signature Key as signature_key.

Then, calculate the following: SHA256-HMAC(key = signature_key, message = "<api_key>:<nonce>"). I.e., calculate HMAC:

  • Using SHA256 as cryptographic hash function
  • Using signature_key as secret key
  • Using the concatenation of the following three strings as message/payload: <api_key> (the user’s “regular” API key, see the very top of this document), : (colon character), <nonce> (as described above in this section)

We’ll call the resultant value of this calculation hmac. Represent/digest hmac as hex string (use digits and lower case only a-f symbols).

Then, add nonce and hmac parameters to the corresponding API request (to the root of the request parameters).

Each nonce you provide must be greater (as a number) than the one provided in the previous signed request. Also, nonce must correspond to a time reasonably close to “the now”.

Notice, that you must not provide signature key as request parameter.

IMPORTANT: “signed request” procedure goal is to enable a user to select desired “trust level” for the service/application which runs API requests on the user’s behalf (by allowing the user to provide only their API key to the service/application, and not their signature key). While using “signed request” it is especially important for a service/application to ensure that direct and proper HTTPS connection with the trading platform’s servers has been established. Signed request is not aimed to reinvent internet security, and shouldn’t be considered as such, thus it fully relies on the underlying HTTPS protocols to ensure safety.

Error handling

The server will respond with JSON with error_code and relevant HTTP status.

The response is a JSON object (hash) with "status" key.

"status" is set to "success" (if the request was fulfilled) or "error" (otherwise).

"error_code" key contains error code (short string) if "status" is "error".

If the requested entity wasn’t found, the following response will be sent with 404 NOT FOUND HTTP status:

{
  "status": "error",
  "error_code": "not_found"
}

If required root parameter of the request is ommitted, the following response will be sent with 400 BAD REQUEST HTTP status:

{
  "status": "error",
  "error_code": "missing_parameter",
  "parameter": "<parameter name here>"
}

If rate limit has been exceeded, the following will be sent with 429 TOO MANY REQUESTS HTTP status:

{
  "status": "error",
  "error_code": "rate_limit_exceeded",
  "message": "rate limit is 2 per 60s"
}

If service is temporarily unavailable, the following response will be sent with 503 SERVICE UNAVAILABLE HTTP status:

{
  "status": "error",
  "error_code": "not_available"
}

(When this reponse is received the request should be repeated later.)

Validation errors

If any validation errors occur when trying to create or update an entity, then the following response will be returned with HTTP status 422:

{
  "status": "error",
  "error": "validation",
  "validation_errors": {
    "<field>": ["<error1>", "<error2>", ...]
  }
}

I.e., "validation_errors" will be returned, which is a hash. Each key of that hash corresponds to the entity’s erroneous field, and the value is an array of human-readable English strings (representing occured validation errors).

Contracts API restrictions

There is no way to create (resolve, work with, etc.) disputes or leave feedback to a counterparty via the API at the moment. Such actions currently should be performed manually via the website.

All contracts operations require payment password to be created via the website (Profile -> Trading Settings). This operation actually creates payment seed on the client (in the browser) and stores encrypted payment seed on the server. Payment seed should be created by offer’s acceptor as well as offer’s creator.

If payment password hasn’t been created on the website, validation error will be returned to “Create contract” request. Currently there is no way to create payment password/encrypted seed via the API for security reasons.

If “Bitcoin address” hasn’t been set in “Trading Settings”, validation error will be returned to “Create contract” request. Currently there is no way to set release address on a per contract basis for security reasons.

Encrypted payment seed could be retrieved via Users/Getting myself method.

Contracts API workflow

  1. Buyer or seller sends “Creating contract” request to the server
  2. Initiator sends “Getting contract” request once every 1-3 minutes until contract.escrow.address is not null (thus, waiting for offer’s creator to confirm their payment password in case they use the website)
  3. Each party verifies the escrow address locally
  4. Each party sends “Confirming contract’s escrow validity” request to the server
  5. Seller deposits cryptocurrency to escrow address
  6. Buyer checks contract status with “Getting contract” request to the server once every 1-5 minutes until contract status is "in_progress"
  7. Buyer verifies locally that correct amount of cryptocurrency has been deposited to escrow address and correct number of blockchain confirmations has been received
  8. Buyer sends fiat payment to the seller
  9. Buyer sends “Marking contract as paid” request to the server
  10. Seller verifies locally that they actually has received fiat payment
  11. Seller fetches pre-signed by the server release transaction with “Showing release transaction of contract” request
  12. Seller verifies and signs the release transaction locally
  13. Seller sends the signed release transaction to the server with “Signing release transaction of contract

If you are the seller, DO NOT SEND BITCOINS UNTIL CONTRACT STATUS IS "depositing".

If you are the buyer, DO NOT SEND PAYMENT UNTIL CONTRACT STATUS IS "in_progress".

Note: both buyer and seller could check contract status (including information on deposited cryptocurrency) at any time with “Getting contract” request.

Client-side operations

The following operations should be performed on the client (as decribed above):

  • seed encryption/decryption
  • escrow validation
  • transaction signing

References

See HodlHodl Multisig contract specification for detailed description of multisig.

See Bitcoin core documentation for detailed description of P2SH(P2WSH) addresses.

Seed encryption/decryption

The terms “seed” and “xpub” are used as defined in BIP32. Recommended seed length is 64 bytes.

To obtain public or private key for a particular contract use derivation path m/i, where i is provided by the server in as contract.escrow.index in Getting contract response.

Seed is encrypted with so called “payment password” which results in “encrypted seed”.

When user creates payment password on the trading platform’s website what actually happens is:

  • browser generates random seed
  • browser encrypts this seed with user-provided payment password
  • browser sends encrypted seed to the server
  • server stores encrypted seed with user data

This workflow allows user to seamlessly change clients without need to export/import their seed (they only need to remember payment password and provide it to the client). Encrypted seed is provided in Getting myself response, clients might save and back up that value for additional safety.

Encrypted seed is a string of the following kind:

ES1:<ciphertext_hex>:<salt_hex>:pbkdf2:10000

ES1 is the version of the algorithm used to encode the string (currently only one version exists), pbkdf2 is the name of key derivation function and 10000 is the number of iterations for PBKDF2. Clients must treat ES1, pbkdf2, 10000 as fixed values and check that encrypted seed satisfies this template.

<ciphertext_hex> is hex-encoded result of AES encryption of the seed.

<salt_hex> is hex-encoded salt, used for several purposes.

To decrypt seed use the following algorithm (pseudocode):

  1. Let payment_password be payment password of the user
  2. Check that encrypted seed satisfies regexp /^ES1:([a-f0-9]+):([a-f0-9]+):pbkdf2:10000$/
  3. Split encrypted seed with ‘:’, extract 2nd element as ciphertext_hex, 3rd element as salt_hex
  4. Let ciphertext be the hex-decoded value of ciphertext_hex, salt be the hex-decoded value of salt_hex
  5. Derive aesKey with PBKDF2-HMAC-SHA256:
    • aesKey = PBKDF2-SHA256(password = payment_password, salt = salt, derived key len = 16 bytes, iterations = 10000)
  6. Derive seed:
    1. Let iv be the first 12 bytes of ciphertext
    2. Let authTag be the last 16 bytes of ciphertext
    3. Let content be all the rest of ciphertext (without first 12 and last 16 bytes)
    4. Perform AES-128-GCM decyption
      • seed = AES-128-GCM-DECRYPT(key = aesKey, iv = iv, auth tag length = 16 bytes, auth tag = authTag, ciphertext = content)
    5. If decryption fails, consider payment_password to be wrong
  7. Verify decrypted seed
    1. Let mac be the first 16 bytes of SHA256-HMAC(key = payment_password, message = seed)
    2. Check that mac equals to salt. If not, consider payment_password to be wrong

Example

Encrypted seed

ES1:7eda9c6f743602a3175d4c522381ab8fb402a75e57cdb3af38aaa0511eac09f28ac45e6f3c368962453de190081f94311fbeab69406e8a36241f0f79bb5d81ee881c73eea3cc488f501cf0030355374f1bba0c16071a773e9e7c1879:8a4acbac1c107faf5652782d5b569a7e:pbkdf2:10000

XPub

xpub661MyMwAqRbcFRUMeZHWy6W9D7MkVbboYehf3RrDPdGFxqfHD3uWBJfMFrrMjTNEddTgYSFktearKrCnoAZV949SSNpakwMGPDeu98DZFiU

Payment password: gg5GvNZAwgWQeVS

aesKey (hex): de9bccdb2a8d14136967bc3286f0ce6a

Decrypted seed (hex)

646131227d65c6d729bc82ddc9e4d141ab69b1ee0dc840cf07183fc8b6f7faeb9ba2d9f0ad357102c578a74700c4491349cd4002991a1c4e8d41accc538d27cc

Derived private key for index 10164 (hex)

4aca31a8e38da930d260253b8c02191abf4bf40bce355712522ac369229b7ea5

Escrow validation

Client must validate witness script and escrow address using information from Getting contract request. Witness script in the response is hex-encoded.

Witness script (contract.escrow.witness_script)

  • Must follow 2-of-3 P2SH(P2WSH) multisig template
  • Must contain correct client’s public key as one of 3 public keys (derived from the client’s seed using contract.escrow.index as derivation index)

Escrow address (contract.escrow.address)

  • Must be 2-of-3 P2SH(P2WSH) multisig address
  • Must use the same three pubkeys which are used in the witness script

Notes

It is recommended to use well-tested libraries to check escrow address.

The following regexp could be used to check witness script hex string and extract public keys:

// javascript example

const twoOfThreeWitness = /^5221([a-f0-9]{66})21([a-f0-9]{66})21([a-f0-9]{66})53ae$/

const script = "522103327a0c6b641047a0a1579fe524c585bbfa79a5eb72c369e4a76f8fb31dbd69ee2102f2f4b089dcfbdf5e129c7747f4a63bfa0c503c0eaf391140998bcd7abafafeab210276f96783752ec81e2afee2b2b24f225ff04174b3d9da220c4b8a2c7a71f8689453ae"

const [_, hodlPubKey, sellerPubKey, buyerPubKey] = script.match(twoOfThreeWitness)

The following code could be used with bitcoinjs-lib to check address:

// javascript - example continues from the previous block of code

import * as bitcoin from 'bitcoinjs-lib'
import {Buffer} from 'buffer'

const correctAddress = bitcoin.payments.p2sh({
  redeem: bitcoin.payments.p2wsh({
    redeem: bitcoin.payments.p2ms({
      m: 2,
      pubkeys: [hodlPubKey, sellerPubKey, buyerPubKey].map((x) => Buffer.from(x, 'hex')),
      network: bitcoin.networks.bitcoin // or bitcoin.networks.testnet for testnet
    })
  })
}).address

// compare correctAddress with contract.escrow.address

Transaction signing

Server will return hex-encoded partially-signed transaction (i.e. instead of the user’s signature there would be several 0 symbols) with Showing release transaction of contract or Showing refund transaction of contract methods.

Using HodlHodl Multisig contract specification for reference validate that:

  • Transaction inputs are from escrow address
  • Transaction outputs contain user’s release (or refund, if this is a refund transaction) address
  • User address receives valid amount of funds (escrow amount minus applicable network and service fees)

Then sign the transaction (add user’s signature instead of 0s in the corresponding place) and post it to the server with Signing release transaction of contract or Signing refund transaction of contract request.

Contract fees breakdown

See Terms of Service for full explanation on how fees work. Below is non-binding explanation for fields seen in API responses (several Contracts and Offers methods) and how they correspond to the websites’ fields.

- Website text API field name Meaning
1 How much do you want to buy/sell? (Entered in BTC) Amount of BTC a buyer will receive/seller will give
2 How much do you want to buy/sell? (Entered in fiat currency) contract.value Amount of fiat a buyer will pay/seller will receive
3 To be deposited (BTC) contract.volume Amount of BTC a seller should pay (blockchain fee paid on top of that)
4 Goes to the buyer (BTC) contract.volume_breakdown.goes_to_buyer Amount of BTC a buyer will receive (blockchain fee paid from that)
5 Trading fee (BTC) contract.volume_breakdown.exchange_fee Amount of BTC trading platform receives (blockchain fee not applicable)
6 Fiat trading fee deduction (fiat) contract.volume_breakdown.exchange_fee_in_fiat Half of amount from previous row (#5) converted to fiat (fiat equivalent of buyer’s part of trading fee)
7 Transaction fee (estimated) (BTC) contract.volume_breakdown.transaction_fee, offer.fee.transaction_fee Estimated blockchain fee which a buyer will pay (#4)
8 Current trading fee: XX% (percent/fraction) offer.fee.author_fee_rate, offer.fee.your_fee_rate Percent (website) or the same as fraction (API) of trading fee set for particular user. Minimum among “your” (current user) and “author” (offer creator) fee rate (#9) is multiplied by contract volume (#3) and results in trading fee (#5).
9 offer.fee.exchange_fee Minimum among “your” and “author” (#8) trading fee

Backward-incompatible changes

Earlier there was filters.volume field in GET /api/v1/offers and GET /api/v1/offers/fetch_new, now it is replaced with filters.amount field (see endpoints’ description for futher details).

Chat messages

Chat messages resource

Listing chat messages for a contract

Endpoint

GET /api/v1/contracts/:contract_id/chat_messages

Parameters

Name Description
contract_id

Contract ID

Request

Route

GET /api/v1/contracts/qEdUMA4KV7bj0A54/chat_messages

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/contracts/qEdUMA4KV7bj0A54/chat_messages" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
chat_messages

Chat messages array

chat_messages[#].text

Text

chat_messages[#].author

Login of author

chat_messages[#].from_admin

Author is a trading platform’s admin? (true or false)

chat_messages[#].sent_at

Sent datetime in UTC, ISO8601 (YYYY-MM-DDThh:mm:ssZ)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "chat_messages": [
    {
      "text": "Hi!",
      "author": "test_user",
      "from_admin": false,
      "sent_at": "2024-01-12T12:11:27Z"
    },
    {
      "text": "Hi to you!",
      "author": "us4r50",
      "from_admin": false,
      "sent_at": "2024-01-12T12:11:27Z"
    }
  ]
}

Contracts

Contracts resource

Getting contract

This method could be requested at any time by either party to check contract status (including status of cryptocurrency deposit).

Endpoint

GET /api/v1/contracts/:id

Parameters

Name Description
id

Contract ID

Request

Route

GET /api/v1/contracts/6MJXl5AwCEF9X8hl

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/contracts/6MJXl5AwCEF9X8hl" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract resource

contract.id

ID

contract.your_role

Your role ("buyer" or "seller")

contract.can_be_canceled

Can be canceled in its current state by you? (true or false)

contract.offer_id

Offer ID

contract.value

Value (i.e. fiat price of contract)

contract.price

Asset price (in currency_code fiat currency, at the moment of the creation of the contract)

contract.currency_code

Currency/asset code of ‘value’ field (e.g. ‘USD’)

contract.volume

Volume (i.e. BTC price of contract)

contract.asset_code

Asset code of ‘volume’ field (‘BTC’)

contract.comment

Comment of the Contract’s initiator

contract.release_address

Release address (only shows in Getting contract method for buyer)

contract.confirmations

Blockchain confirmations required for deposit transaction in order for Contract to be considered 'Deposited'

contract.payment_window_minutes

Payment window set by the offer author for the contract, during which the buyer must transfer the payment using the agreed upon payment method.

contract.depositing_window_minutes

Depositing window set by the exchange during which the seller must deposit bitcoins into escrow

contract.payment_window_time_left_seconds

Payment window time left (in seconds)

contract.payment_window_seconds_left

Payment window time left (in seconds, alias to payment_window_time_left_seconds, which is now deprecated)

contract.depositing_window_time_left_seconds

Depositing window time left (in seconds)

contract.country_code

Contract country code

contract.status

Contract status. There are the following statuses:

  • 'pending' — awaiting confirmation from buyer and/or seller (initial status)
  • 'depositing' — awaiting deposition from seller and confirmations from the blockchain
  • 'in_progress' — deposition has been confirmed by the blockchain
  • 'paid' — buyer has confirmed they sent the payment
  • 'completed' — cryptocurrency has been released/transfered from the escrow (final status)
  • 'canceled' — contract has been canceled (final status)
  • 'disputed' — contract is disputed
  • 'resolved' — dispute has been resolved by admin (final status; voluntary resolution instead leads to 'completed' status)

If you are the seller, DO NOT SEND BITCOINS UNTIL CONTRACT STATUS IS 'depositing'.

If you are the buyer, DO NOT SEND PAYMENT UNTIL CONTRACT STATUS IS 'in_progress'.

contract.dispute_status

Contract dispute status. null unless contract status is 'resolved'.

contract.country

Country name (or 'Global')

contract.country_code

Country code (or 'Global')

contract.created_at

Creation datetime in UTC, ISO8601 (YYYY-MM-DDThh:mm:ssZ)

contract.counterparty

Counterparty information

contract.counterparty.login

Login

contract.counterparty.online_status

'online', 'recently_online' or 'offline'

contract.counterparty.rating

Rating (as fraction of 1)

contract.counterparty.trades_count

Number of conducted trades

contract.counterparty.url

Hodlhodl website URL

contract.counterparty.verified

Verified? (true or false)

contract.counterparty.verified_by

Login of the Strong Hodler who verified this user

contract.counterparty.strong_hodler

Strong Hodler? (true or false)

Strong Hodler is a member of Hodl Hodl volunteer team that we’re working directly with.

contract.counterparty.country

Country name (or 'Global')

contract.counterparty.country_code

Country code (or 'Global')

contract.counterparty.average_payment_time_minutes

Average payment time (in minutes)

contract.counterparty.average_release_time_minutes

Average release time (in minutes)

contract.counterparty.days_since_last_trade

Number of days since last trade

contract.counterparty.blocked_by

How many traders blocked this user

Payment method instruction fields

contract.payment_method_instruction.payment_method_name

Name of payment method

contract.payment_method_instruction.payment_method_id

ID of payment method

contract.payment_method_instruction.details

Text of the instruction

Volume breakdown

contract.volume_breakdown.goes_to_buyer

Buyer receives this amount minus transaction fee

contract.volume_breakdown.exchange_fee

Amount of crypto currency that trading platform receives

contract.volume_breakdown.exchange_fee_in_fiat

Fiat equivalent of exchange fee (in currency_code currency)

contract.volume_breakdown.transaction_fee

Estimated blockchain transaction fee

Escrow information

contract.escrow.address

Escrow BTC address (for verification)

This field might be null if the offer’s creator uses the website and hasn’t yet confirmed one’s payment password. In such case, repeat this request once every 1-3 minutes until escrow address appears.

contract.escrow.witness_script

Escrow redeem witness script (for verification)

contract.escrow.index

Escrow xpub/xpriv index (for verification)

contract.escrow.you_confirmed

Have you verified and confirmed the escrow? (true or false)

contract.escrow.counterparty_confirmed

Have the other party verified and confirmed the escrow? (true or false)

contract.escrow.confirmations

Blockchain confirmations received so far

contract.escrow.amount_deposited

Amount deposited (in BTC; null when no deposit has been made yet)

contract.escrow.amount_released

Amount released (in BTC; null when no release has been made yet)

contract.escrow.deposit_transaction_id

Blockchain ID of deposit transaction (null when no deposit has been made yet)

contract.escrow.release_transaction_id

Blockchain ID of release transaction (null when no release has been made yet)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "6MJXl5AwCEF9X8hl",
    "your_role": "seller",
    "can_be_canceled": true,
    "offer_id": "JB8szvvviJ6eQKsd",
    "price": "700.00",
    "value": "7903.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "confirmations": 2,
    "payment_window_seconds_left": null,
    "payment_window_time_left_seconds": null,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "pending",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277327",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "77.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 81",
    "country_code": "Country Code 81",
    "created_at": "2024-01-12T12:11:27Z",
    "counterparty": {
      "login": "us4r51",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://localhost:3000/users/us4r51",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 80",
      "country_code": "Country Code 80",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "escrow": {
      "address": null,
      "witness_script": null,
      "index": null,
      "you_confirmed": false,
      "counterparty_confirmed": false,
      "confirmations": 0,
      "amount_deposited": null,
      "amount_released": null,
      "deposit_transaction_id": null,
      "release_transaction_id": null
    }
  }
}

Listing my contracts

This method will return all your existing contracts, recently created first.

Response could be filtered by side and/or by status.

Endpoint

GET /api/v1/contracts/my

Parameters

Name Description
pagination.limit

Number of records to return (default 50, maximum 100)

pagination.offset

Number of records to skip (e.g. 50 for second page of results with the default limit)

filters.side

'buy' or 'sell'

filters.status

Status, see contract.status response field in Getting contract

filters.offer_id

Contracts for offer with id

Request

Route

GET /api/v1/contracts/my?filters[status]=pending

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Query Parameters as JSON

{
  "filters": {
    "status": "pending"
  }
}

cURL

curl -g "hodlhodl.com/api/v1/contracts/my?filters[status]=pending" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contracts

Array of Contracts (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "filters": {
    "status": "pending"
  },
  "pagination": {
    "limit": 50,
    "offset": 0
  },
  "contracts": [
    {
      "id": "tvEhGj7cPr4KIXHl",
      "your_role": "buyer",
      "can_be_canceled": true,
      "offer_id": "Afj5OvRnr51y8aCG",
      "price": "725.53",
      "value": "7900.98",
      "currency_code": "USD",
      "volume": "11.00000000",
      "asset_code": "BTC",
      "comment": "Sell me bitcoins, I agree to the terms!",
      "release_address": "n45ssNV2o1ursURPhLvF1AXVtzrcvKrpPZ",
      "confirmations": 1,
      "payment_window_seconds_left": null,
      "payment_window_time_left_seconds": null,
      "payment_window_minutes": 60,
      "depositing_window_minutes": 30,
      "depositing_window_time_left_seconds": null,
      "status": "pending",
      "dispute_status": null,
      "payment_method_instruction": {
        "payment_method_id": "277330",
        "payment_method_name": "Yandex Money 54",
        "details": "Send money over to account 123"
      },
      "volume_breakdown": {
        "goes_to_buyer": "10.78000000",
        "exchange_fee": "0.22000000",
        "exchange_fee_in_fiat": "79.81",
        "transaction_fee": "0.00000371"
      },
      "country": "Country 83",
      "country_code": "Country Code 83",
      "created_at": "2024-01-11T12:11:28Z",
      "counterparty": {
        "login": "us4r52",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": null,
        "my_review": null,
        "trades_count": 0,
        "url": "http://localhost:3000/users/us4r52",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 82",
        "country_code": "Country Code 82",
        "average_payment_time_minutes": null,
        "average_release_time_minutes": null,
        "days_since_last_trade": null,
        "blocked_by": 0
      },
      "escrow": {
        "address": "2N39fd1Bf22pbXkWsKhazHyrMCjsBoAz7vm",
        "witness_script": "522102334e69adc60aa46254efc9ea0ef49ac568adb99f2d3ffb1d293472e9eb443ff121028706bad0ecd9a4bebf850e4b03f571790ace929db6a11a2f3941e02f0216a8c621028706bad0ecd9a4bebf850e4b03f571790ace929db6a11a2f3941e02f0216a8c653ae",
        "index": 21190,
        "you_confirmed": false,
        "counterparty_confirmed": false,
        "confirmations": 0,
        "amount_deposited": "0.00000000",
        "amount_released": null,
        "deposit_transaction_id": null,
        "release_transaction_id": null
      }
    },
    {
      "id": "2BYnedRdfscsk9YL",
      "your_role": "seller",
      "can_be_canceled": true,
      "offer_id": "UOD2emI2vY5uWPfG",
      "price": "725.53",
      "value": "7900.98",
      "currency_code": "USD",
      "volume": "11.00000000",
      "asset_code": "BTC",
      "comment": "Sell me bitcoins, I agree to the terms!",
      "confirmations": 1,
      "payment_window_seconds_left": null,
      "payment_window_time_left_seconds": null,
      "payment_window_minutes": 60,
      "depositing_window_minutes": 30,
      "depositing_window_time_left_seconds": null,
      "status": "pending",
      "dispute_status": null,
      "payment_method_instruction": {
        "payment_method_id": "277332",
        "payment_method_name": "Yandex Money 56",
        "details": "Send money over to account 123"
      },
      "volume_breakdown": {
        "goes_to_buyer": "10.78000000",
        "exchange_fee": "0.22000000",
        "exchange_fee_in_fiat": "79.81",
        "transaction_fee": "0.00000371"
      },
      "country": "Country 84",
      "country_code": "Country Code 84",
      "created_at": "2024-01-10T12:11:28Z",
      "counterparty": {
        "login": "us4r55",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": null,
        "my_review": null,
        "trades_count": 0,
        "url": "http://localhost:3000/users/us4r55",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 82",
        "country_code": "Country Code 82",
        "average_payment_time_minutes": null,
        "average_release_time_minutes": null,
        "days_since_last_trade": null,
        "blocked_by": 0
      },
      "escrow": {
        "address": "2NCdoSe7p8j4RyHhsZwuTfU3srTuz3oYq75",
        "witness_script": "522103948f8a3bd2590a0439c88d76bd259add0463f45195a90f33723e99bd2e97ad2c2102c261119b32c24bb0100caea3100b7cd0409074e5bc480ee6b90ec57a72fdaac02102c261119b32c24bb0100caea3100b7cd0409074e5bc480ee6b90ec57a72fdaac053ae",
        "index": 21191,
        "you_confirmed": false,
        "counterparty_confirmed": false,
        "confirmations": 0,
        "amount_deposited": "0.00000000",
        "amount_released": null,
        "deposit_transaction_id": null,
        "release_transaction_id": null
      }
    },
    {
      "id": "XvYzRfSiGhQkhNbo",
      "your_role": "buyer",
      "can_be_canceled": true,
      "offer_id": "Afj5OvRnr51y8aCG",
      "price": "725.53",
      "value": "7900.98",
      "currency_code": "USD",
      "volume": "11.00000000",
      "asset_code": "BTC",
      "comment": "Sell me bitcoins, I agree to the terms!",
      "release_address": "n45ssNV2o1ursURPhLvF1AXVtzrcvKrpPZ",
      "confirmations": 1,
      "payment_window_seconds_left": null,
      "payment_window_time_left_seconds": null,
      "payment_window_minutes": 60,
      "depositing_window_minutes": 30,
      "depositing_window_time_left_seconds": null,
      "status": "pending",
      "dispute_status": null,
      "payment_method_instruction": {
        "payment_method_id": "277329",
        "payment_method_name": "Yandex Money 53",
        "details": "Send money over to account 123"
      },
      "volume_breakdown": {
        "goes_to_buyer": "10.78000000",
        "exchange_fee": "0.22000000",
        "exchange_fee_in_fiat": "79.81",
        "transaction_fee": "0.00000371"
      },
      "country": "Country 83",
      "country_code": "Country Code 83",
      "created_at": "2024-01-07T12:11:27Z",
      "counterparty": {
        "login": "us4r52",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": null,
        "my_review": null,
        "trades_count": 0,
        "url": "http://localhost:3000/users/us4r52",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 82",
        "country_code": "Country Code 82",
        "average_payment_time_minutes": null,
        "average_release_time_minutes": null,
        "days_since_last_trade": null,
        "blocked_by": 0
      },
      "escrow": {
        "address": "2NFVai4UNnfMBfUD6mkq4FFfCoNVL8RpM4n",
        "witness_script": "5221026e067f6f5903d3f7623be98ffa2fe52f1bb2d2ddda9c2d67f7a835f8371e99492102181e30d49a397aba66e0717499684fb171dc5432ed8dd106ee5bd50f92a07f262102181e30d49a397aba66e0717499684fb171dc5432ed8dd106ee5bd50f92a07f2653ae",
        "index": 21189,
        "you_confirmed": false,
        "counterparty_confirmed": false,
        "confirmations": 0,
        "amount_deposited": "0.00000000",
        "amount_released": null,
        "deposit_transaction_id": null,
        "release_transaction_id": null
      }
    }
  ]
}

Creating contract

Note 1. offer_version and payment_method_instruction_version could be obtained by querying Getting offer. Clients should not interpret this value. This value will change every time the corresponding offer or payment method instruction is changed. Requiring to provide these values on contract creation ensures that the end-user agrees to the exact terms of offer which they have seen.

Note 2. To create contract for ‘buy’ offer, payment_method_instruction_id should be ID of one of your payment method instructions (see Payment method instructions resource). payment_method_id of the given payment method instruction should be one of the payment_method_ids of the offer.

To create contract for ‘sell’ offer, payment_method_instruction_id should be ID of one of the offer’s payment_method_instructions.id (see Getting offer).

Note 3. Either value or volume must be present in the request (but not both). Non-present value will be calculated automatically (using offer’s price of the created contract).

Note 4. When volume is provided by buyer, actual contract volume is increased to account for trading platform’s fee.

Note 5. See Signed request.

Endpoint

POST /api/v1/contracts

Parameters

Name Description
contract.offer_id

Offer ID (required)

contract.offer_version

Offer version 1 (required)

contract.payment_method_instruction_id

Payment method instruction ID (required) 2

contract.payment_method_instruction_version

Payment method instruction version 1 (required)

contract.comment

Comment of the Contract’s initiator

Value/volume fields 3 (exactly 1 of the following is required):

contract.value

Value (i.e. fiat price of contract; will be rounded to 2 decimal digits)

contract.volume

Volume (i.e. BTC price of contract) 4

Release address (signed request; provide all or none of the following):

contract.release_address

Release address (if omitted then default one from the user’s settings will be used)

nonce

Nonce (string) 5

hmac

Result of HMAC-SHA256 calculation 5

Request

Route

POST /api/v1/contracts

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "contract": {
    "offer_id": "ezDIit3tGGGFR00j",
    "offer_version": "9w0568",
    "payment_method_instruction_id": 262486,
    "payment_method_instruction_version": "a3bzmo",
    "comment": "I accept your offer",
    "value": 350
  }
}

cURL

curl "hodlhodl.com/api/v1/contracts" -d '{"contract":{"offer_id":"ezDIit3tGGGFR00j","offer_version":"9w0568","payment_method_instruction_id":262486,"payment_method_instruction_version":"a3bzmo","comment":"I accept your offer","value":350}}' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "SnLX4h4R2pMXU1cf",
    "your_role": "buyer",
    "can_be_canceled": true,
    "offer_id": "ezDIit3tGGGFR00j",
    "price": "700.00",
    "value": "350.00",
    "currency_code": "EUR",
    "volume": "0.50500000",
    "asset_code": "BTC",
    "comment": "I accept your offer",
    "release_address": "n45ssNV2o1ursURPhLvF1AXVtzrcvKrpPZ",
    "confirmations": 2,
    "payment_window_seconds_left": null,
    "payment_window_time_left_seconds": null,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "pending",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277333",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "0.49490000",
      "exchange_fee": "0.01010000",
      "exchange_fee_in_fiat": "3.54",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 86",
    "country_code": "Country Code 86",
    "created_at": "2024-01-12T12:11:28Z",
    "counterparty": {
      "login": "us4r57",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://localhost:3000/users/us4r57",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 85",
      "country_code": "Country Code 85",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "escrow": {
      "address": "2Mtz5HJSeJWfWuYrZqTbdg9qnsjiEnAu3VT",
      "witness_script": "522102ae345268cfea1b42d7cebc3e6f69c9dd359d746f7f222596cda83a750689d3b42103ada4d9f7507fd1c4141e86c6fe77d34d9262441f4d8a8416a9a57682c0d17c322103ada4d9f7507fd1c4141e86c6fe77d34d9262441f4d8a8416a9a57682c0d17c3253ae",
      "index": 21192,
      "you_confirmed": false,
      "counterparty_confirmed": false,
      "confirmations": 0,
      "amount_deposited": "0.00000000",
      "amount_released": null,
      "deposit_transaction_id": null,
      "release_transaction_id": null
    }
  }
}

Verifying signature key

This method should be used to verify signature key (together with API key)

Endpoint

POST /api/v1/contracts/verify_signature_key

Parameters

Name Description
nonce

Nonce (string) (see Signed request)

hmac

Result of HMAC-SHA256 calculation (see Signed request)

Request

Route

POST /api/v1/contracts/verify_signature_key

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "nonce": "1657892498",
  "hmac": "d9629c165455dcde0518132280daa9416b2d998bf468ebf1ea637f0bc03ebe77"
}

cURL

curl "hodlhodl.com/api/v1/contracts/verify_signature_key" -d '{"nonce":"1657892498","hmac":"d9629c165455dcde0518132280daa9416b2d998bf468ebf1ea637f0bc03ebe77"}' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success"
}

Confirming contract's escrow validity

This method is used to confirm that client-side validation of escrow data was successful.

This method should be called immediately after escrow address appeared in Getting contract response and this escrow address has been verified locally by the client.

Client should verify contract’s escrow data (witness script, address and index) and then send this request. See JS client documentation/examples for more details.

This method gives information to the server that the calling party agrees to go forward with the contract. Clients should ensure by themselves independently that they move funds to the correct address/escrow.

Endpoint

POST /api/v1/contracts/:id/confirm

Parameters

Name Description
id

Contract ID

Request

Route

POST /api/v1/contracts/bp36lnYAIHcQ16B2/confirm

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/contracts/bp36lnYAIHcQ16B2/confirm" -d '' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "bp36lnYAIHcQ16B2",
    "your_role": "buyer",
    "can_be_canceled": true,
    "offer_id": "O1BIs9lUftK7AP9J",
    "price": "7000.00",
    "value": "7210.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "release_address": "n45ssNV2o1ursURPhLvF1AXVtzrcvKrpPZ",
    "confirmations": 2,
    "payment_window_seconds_left": null,
    "payment_window_time_left_seconds": null,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "pending",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277334",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "770.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 89",
    "country_code": "Country Code 89",
    "created_at": "2024-01-12T12:11:29Z",
    "counterparty": {
      "login": "us4r58",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://localhost:3000/users/us4r58",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 88",
      "country_code": "Country Code 88",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "escrow": {
      "address": "2MybQEDeibrkNJxSdzYMFLhKwdescBWnE7Q",
      "witness_script": "5221030595d886d3e965b8ef45e929556f210fd8617ea4d7703b02c10ac8d09a54b897210322627c695e997393ebdfc835a7c2a4f74c4bf5119cc795d74e7fa1bc99845297210322627c695e997393ebdfc835a7c2a4f74c4bf5119cc795d74e7fa1bc9984529753ae",
      "index": 21193,
      "you_confirmed": true,
      "counterparty_confirmed": false,
      "confirmations": 0,
      "amount_deposited": "0.00000000",
      "amount_released": null,
      "deposit_transaction_id": null,
      "release_transaction_id": null
    }
  }
}

Marking contract as paid

Buyer (and only buyer) should call this method when fiat payment was made.

This method could be called only if contract’s status is 'in_progress'.

Endpoint

POST /api/v1/contracts/:id/mark_as_paid

Parameters

Name Description
id

Contract ID

Request

Route

POST /api/v1/contracts/M5hpDTBIUBzDTuHA/mark_as_paid

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/contracts/M5hpDTBIUBzDTuHA/mark_as_paid" -d '' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "M5hpDTBIUBzDTuHA",
    "your_role": "buyer",
    "can_be_canceled": false,
    "offer_id": "08AH2gs12472M6GP",
    "price": "700.00",
    "value": "7903.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "release_address": "n45ssNV2o1ursURPhLvF1AXVtzrcvKrpPZ",
    "confirmations": 2,
    "payment_window_seconds_left": 3599714000,
    "payment_window_time_left_seconds": 3599714000,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "paid",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277335",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "77.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 91",
    "country_code": "Country Code 91",
    "created_at": "2024-01-12T12:11:29Z",
    "counterparty": {
      "login": "us4r59",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://localhost:3000/users/us4r59",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 90",
      "country_code": "Country Code 90",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "escrow": {
      "address": "2N5EmoCnRArU947nLYTyDyoyCV5VA354yHH",
      "witness_script": "522102999cc361999ee87d6084cb141cb8441d873842c9a0dcdff1dc183290c2f3d49121033931623f625f2d14c582c50bfcdf70c32ef2ff7a397e4675affe08be2c37270321033931623f625f2d14c582c50bfcdf70c32ef2ff7a397e4675affe08be2c37270353ae",
      "index": 21194,
      "you_confirmed": true,
      "counterparty_confirmed": true,
      "confirmations": 0,
      "amount_deposited": "11.00000000",
      "amount_released": null,
      "deposit_transaction_id": null,
      "release_transaction_id": null
    }
  }
}

Canceling contract

Contract could be canceled when any of the following conditions are met:

  • Contract status is 'pending' and there are no bitcoins at the escrow address according to our most recent data
  • Contract status is 'depositing' and you are the seller
  • Contract status is 'depositing', you are the buyer, and depositing time has expired
  • Contract status is 'in_progress' and you are the buyer
  • Contract status is 'in_progress', you are the seller, and payment window has expired

If none of the conditions above are met then a validation error will be returned:

{
  'status': 'error',
  'error_code': 'validation',
  'validation_errors': {
    'id': ['Contract in its current state can't be cancelled by you']
  }
}

Endpoint

POST /api/v1/contracts/:id/cancel

Parameters

Name Description
id

Contract ID

Request

Route

POST /api/v1/contracts/cZjpLFFeWUK0UTs8/cancel

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/contracts/cZjpLFFeWUK0UTs8/cancel" -d '' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "cZjpLFFeWUK0UTs8",
    "your_role": "buyer",
    "can_be_canceled": false,
    "offer_id": "SX7qLPu7sVaBJN6n",
    "price": "700.00",
    "value": "7903.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "release_address": "n45ssNV2o1ursURPhLvF1AXVtzrcvKrpPZ",
    "confirmations": 2,
    "payment_window_seconds_left": null,
    "payment_window_time_left_seconds": null,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "canceled",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277336",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "77.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 93",
    "country_code": "Country Code 93",
    "created_at": "2024-01-12T12:11:30Z",
    "counterparty": {
      "login": "us4r60",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://localhost:3000/users/us4r60",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 92",
      "country_code": "Country Code 92",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "escrow": {
      "address": null,
      "witness_script": null,
      "index": null,
      "you_confirmed": false,
      "counterparty_confirmed": false,
      "confirmations": 0,
      "amount_deposited": null,
      "amount_released": null,
      "deposit_transaction_id": null,
      "release_transaction_id": null
    }
  }
}

Showing release transaction of contract

This method should be called by seller when contract status is 'paid'; or by buyer when contract status is 'resolved' and 'dispute_status' is 'resolved_in_favor_of_buyer'.

Endpoint

GET /api/v1/contracts/:id/release_transaction

Parameters

Name Description
id

Contract ID

Request

Route

GET /api/v1/contracts/ISwG56v8UA0SRfRT/release_transaction

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/contracts/ISwG56v8UA0SRfRT/release_transaction" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
transaction.contract_id

Contract ID

transaction.hex

Hex string which represents transaction to be signed

transaction.in_amounts

tx_in amounts of the transaction (Array of Integers)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "transaction": {
    "contract_id": "ISwG56v8UA0SRfRT",
    "hex": "01000000000101931f8e609e3e5a15d6c4965f5cbbb29c32a6f2e9e49e5f0194fc41cf8fdd441c0000000023220020e5179fae90d2ef16b6a3f96e36bf7fcc966791c02aa13dd35c067ead1881c22bffffffff0291f84040000000001976a914f78cccb98956d9412ec023e18329d98e134c3fa888ac80b14f01000000001600149a4930b4ce7289c899053fa4a6d11a37ef4c919a0400473044022024d49682829879391cdd1cb701d646267a33ac253c7c04d25051a0f30e0d1bf3022064762f9381acc944de9be8501035db865afd82157501494fe563b9d8426c74fa0146000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006952210241fac32e57747dcc52a162e186f90b4400bc2d07ce30b7336a087264230291fd2102090b998275408b4cfd3c5f135ec7a83f25962bb57617b20001ceee246095e9832102090b998275408b4cfd3c5f135ec7a83f25962bb57617b20001ceee246095e98353ae00000000",
    "in_amounts": [
      1100000000.0
    ]
  }
}

Showing refund transaction of contract

This method should be called by seller when contract status is 'canceled'; or status is 'resolved' and 'dispute_status' is 'resolved_in_favor_of_seller'.

Endpoint

GET /api/v1/contracts/:id/refund_transaction

Parameters

Name Description
id

Contract ID

release_address

Release address for the refund (required)

Request

Route

GET /api/v1/contracts/rCIg43tFW1QH7aHQ/refund_transaction?release_address=n4VQ5YdHf7hLQ2gWQYYrcxoE5B7nWuDFNF

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Query Parameters as JSON

{
  "release_address": "n4VQ5YdHf7hLQ2gWQYYrcxoE5B7nWuDFNF"
}

cURL

curl -g "hodlhodl.com/api/v1/contracts/rCIg43tFW1QH7aHQ/refund_transaction?release_address=n4VQ5YdHf7hLQ2gWQYYrcxoE5B7nWuDFNF" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
transaction.contract_id

Contract ID

transaction.hex

Hex string which represents transaction to be signed

transaction.in_amounts

tx_in amounts of the transaction (Array of Integers)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "transaction": {
    "contract_id": "rCIg43tFW1QH7aHQ",
    "hex": "01000000000101931f8e609e3e5a15d6c4965f5cbbb29c32a6f2e9e49e5f0194fc41cf8fdd441c00000000232200203d21eb87604c409d616da8b00e4551ea9d80327cb39487d9e97e6a17396f4d23ffffffff0133aa9041000000001976a914fbff95b4e35aca918d26e157392ea1643a2dc28388ac0400483045022100a818395121f4bef9d73beea58de334b83bbb9bcde72e84c7bb4742dc810a3c5d02203b34b0af1739a67495789829eff8fa086cdc66d01a7d2c58ee6194c383c9310a01460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000069522103c9cbe03cdd22d236764469d857e20f5c386fa64d8eeb690942a3bfd661bc310121027fe7fae65fe5733058f7e1a92f98378d22925bffd9d3901a5e678cf2573f192921027fe7fae65fe5733058f7e1a92f98378d22925bffd9d3901a5e678cf2573f192953ae00000000",
    "in_amounts": [
      1100000000.0
    ]
  }
}

Signing release transaction of contract

This method seller should call after viewing & verifying release transaction. Provide signed transaction as hex string in the 'hex' parameter.

Endpoint

POST /api/v1/contracts/:id/release_transaction

Parameters

Name Description
id

Contract ID

hex

Hex string which represents signed transaction

Request

Route

POST /api/v1/contracts/Cqsj9Ak7QnMQIlfK/release_transaction

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "hex": "01000000000101678a8e2c7f513b26dff0d8ce8cfc4502f881c227ee04a3303269ac3cf470698c0000000023220020c5dd11c968cf13500f9cf8fcb2e851dd0bb7ea80a1382d639e9eedffa93806f8ffffffff02cca30200000000001976a914ac288fdff4b0bce5a92c3a36b521f05ec8b04fe788ac16040000000000001600149c8653aa0f661dec64a4cd2dc7f7a817a69cfa270400483045022100e73f9e47c251d199eec3623572403794f10648784251aaf4363825cf9d19511c02202c77e36a22b1c6bdaf1f5addb85397af22b60d5382769d7402e07d638832040101483045022100dfd0582dd26edc54348063e597730eadaa96862489d2e2321881bc638aaaab5102201d4e4488a1ca7456aca02838ed29c33f9db67dfac3b3e5c3e685d72556ac83c5016952210259acf58df1360fa96556d1aa00e8bb928d790557e666cd90b3ef8a0dae1b5c702102dc8a3d88e82e9f6d22d6f76d47c6f5c41aed53cfb926bfdbafae25852d3b540621032756f513a93f1443105eef0c11b2164b8c7995d07152331191e536df9232ed1653ae00000000"
}

cURL

curl "hodlhodl.com/api/v1/contracts/Cqsj9Ak7QnMQIlfK/release_transaction" -d '{"hex":"01000000000101678a8e2c7f513b26dff0d8ce8cfc4502f881c227ee04a3303269ac3cf470698c0000000023220020c5dd11c968cf13500f9cf8fcb2e851dd0bb7ea80a1382d639e9eedffa93806f8ffffffff02cca30200000000001976a914ac288fdff4b0bce5a92c3a36b521f05ec8b04fe788ac16040000000000001600149c8653aa0f661dec64a4cd2dc7f7a817a69cfa270400483045022100e73f9e47c251d199eec3623572403794f10648784251aaf4363825cf9d19511c02202c77e36a22b1c6bdaf1f5addb85397af22b60d5382769d7402e07d638832040101483045022100dfd0582dd26edc54348063e597730eadaa96862489d2e2321881bc638aaaab5102201d4e4488a1ca7456aca02838ed29c33f9db67dfac3b3e5c3e685d72556ac83c5016952210259acf58df1360fa96556d1aa00e8bb928d790557e666cd90b3ef8a0dae1b5c702102dc8a3d88e82e9f6d22d6f76d47c6f5c41aed53cfb926bfdbafae25852d3b540621032756f513a93f1443105eef0c11b2164b8c7995d07152331191e536df9232ed1653ae00000000"}' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "Cqsj9Ak7QnMQIlfK",
    "your_role": "seller",
    "can_be_canceled": false,
    "offer_id": "XedwIAkD2TcJMlHc",
    "price": "7000.00",
    "value": "7210.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "confirmations": 2,
    "payment_window_seconds_left": 3599480000,
    "payment_window_time_left_seconds": 3599480000,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "completed",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277341",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "770.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 99",
    "country_code": "Country Code 99",
    "created_at": "2024-01-12T12:11:31Z",
    "counterparty": {
      "login": "us4r65",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 1,
      "url": "http://localhost:3000/users/us4r65",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 98",
      "country_code": "Country Code 98",
      "average_payment_time_minutes": 0,
      "average_release_time_minutes": null,
      "days_since_last_trade": 0,
      "blocked_by": 0
    },
    "escrow": {
      "address": "2MwdKrpoPX9sFvoa4ryJEB6h81sjr5HAK3r",
      "witness_script": "522103f6fd32c1a45b4da69eca402e6d4e1cf9410782acbbe642ed2143d850fbfe6960210316e3db086a8e6758f50265452482da4c1d052cfe90e4a73a675ad63dd7b0d164210316e3db086a8e6758f50265452482da4c1d052cfe90e4a73a675ad63dd7b0d16453ae",
      "index": 21197,
      "you_confirmed": true,
      "counterparty_confirmed": true,
      "confirmations": 0,
      "amount_deposited": "11.00000000",
      "amount_released": "11.00000000",
      "deposit_transaction_id": null,
      "release_transaction_id": "456..."
    }
  }
}

Signing refund transaction of contract

This method seller should call after viewing & verifying refund transaction. Provide signed transaction as hex string in the 'hex' parameter.

Endpoint

POST /api/v1/contracts/:id/refund_transaction

Parameters

Name Description
id

Contract ID

hex

Hex string which represents signed transaction

Request

Route

POST /api/v1/contracts/6ZtRREvXn1OIbTbp/refund_transaction

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "hex": "01000000000101678a8e2c7f513b26dff0d8ce8cfc4502f881c227ee04a3303269ac3cf470698c0000000023220020c5dd11c968cf13500f9cf8fcb2e851dd0bb7ea80a1382d639e9eedffa93806f8ffffffff02cca30200000000001976a914ac288fdff4b0bce5a92c3a36b521f05ec8b04fe788ac16040000000000001600149c8653aa0f661dec64a4cd2dc7f7a817a69cfa270400483045022100e73f9e47c251d199eec3623572403794f10648784251aaf4363825cf9d19511c02202c77e36a22b1c6bdaf1f5addb85397af22b60d5382769d7402e07d638832040101483045022100dfd0582dd26edc54348063e597730eadaa96862489d2e2321881bc638aaaab5102201d4e4488a1ca7456aca02838ed29c33f9db67dfac3b3e5c3e685d72556ac83c5016952210259acf58df1360fa96556d1aa00e8bb928d790557e666cd90b3ef8a0dae1b5c702102dc8a3d88e82e9f6d22d6f76d47c6f5c41aed53cfb926bfdbafae25852d3b540621032756f513a93f1443105eef0c11b2164b8c7995d07152331191e536df9232ed1653ae00000000"
}

cURL

curl "hodlhodl.com/api/v1/contracts/6ZtRREvXn1OIbTbp/refund_transaction" -d '{"hex":"01000000000101678a8e2c7f513b26dff0d8ce8cfc4502f881c227ee04a3303269ac3cf470698c0000000023220020c5dd11c968cf13500f9cf8fcb2e851dd0bb7ea80a1382d639e9eedffa93806f8ffffffff02cca30200000000001976a914ac288fdff4b0bce5a92c3a36b521f05ec8b04fe788ac16040000000000001600149c8653aa0f661dec64a4cd2dc7f7a817a69cfa270400483045022100e73f9e47c251d199eec3623572403794f10648784251aaf4363825cf9d19511c02202c77e36a22b1c6bdaf1f5addb85397af22b60d5382769d7402e07d638832040101483045022100dfd0582dd26edc54348063e597730eadaa96862489d2e2321881bc638aaaab5102201d4e4488a1ca7456aca02838ed29c33f9db67dfac3b3e5c3e685d72556ac83c5016952210259acf58df1360fa96556d1aa00e8bb928d790557e666cd90b3ef8a0dae1b5c702102dc8a3d88e82e9f6d22d6f76d47c6f5c41aed53cfb926bfdbafae25852d3b540621032756f513a93f1443105eef0c11b2164b8c7995d07152331191e536df9232ed1653ae00000000"}' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "6ZtRREvXn1OIbTbp",
    "your_role": "seller",
    "can_be_canceled": false,
    "offer_id": "i1Q7GEr773F8EGmM",
    "price": "7000.00",
    "value": "7210.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "confirmations": 2,
    "payment_window_seconds_left": 3599468000,
    "payment_window_time_left_seconds": 3599468000,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "completed",
    "dispute_status": null,
    "payment_method_instruction": {
      "payment_method_id": "277343",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "770.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 101",
    "country_code": "Country Code 101",
    "created_at": "2024-01-12T12:11:32Z",
    "counterparty": {
      "login": "us4r67",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 1,
      "url": "http://localhost:3000/users/us4r67",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 100",
      "country_code": "Country Code 100",
      "average_payment_time_minutes": 0,
      "average_release_time_minutes": null,
      "days_since_last_trade": 0,
      "blocked_by": 0
    },
    "escrow": {
      "address": "2MvxunHuLrhLsocQjDuZvqmYKqQ85WfGYiq",
      "witness_script": "5221031a359430610201f6ccff33197f4ef274e80ab85c45038fc1472cd47a7139c0d121024807383b52f25acf7e8ec09c40d319c271074587a9246de1560e74c440f0837721024807383b52f25acf7e8ec09c40d319c271074587a9246de1560e74c440f0837753ae",
      "index": 21198,
      "you_confirmed": true,
      "counterparty_confirmed": true,
      "confirmations": 0,
      "amount_deposited": "11.00000000",
      "amount_released": "11.00000000",
      "deposit_transaction_id": null,
      "release_transaction_id": "456..."
    }
  }
}

Starting dispute on the contract

Starts the dispute.

Dispute could be started:

  • by the seller — when the contract status is 'paid'
  • by the buyer — when the contract status is 'paid' and payment window has expired

Endpoint

POST /api/v1/contracts/:id/dispute

Parameters

Name Description
id

Contract ID

Request

Route

POST /api/v1/contracts/vfFr428TU378plHD/dispute

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/contracts/vfFr428TU378plHD/dispute" -d '' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
contract

Contract (see Getting contract for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "contract": {
    "id": "vfFr428TU378plHD",
    "your_role": "seller",
    "can_be_canceled": false,
    "offer_id": "kmJfXRWvFlgIGs02",
    "price": "700.00",
    "value": "7903.79",
    "currency_code": "EUR",
    "volume": "11.00000000",
    "asset_code": "BTC",
    "comment": "Sell me bitcoins, I agree to the terms!",
    "confirmations": 2,
    "payment_window_seconds_left": 3599693000,
    "payment_window_time_left_seconds": 3599693000,
    "payment_window_minutes": 60,
    "depositing_window_minutes": 30,
    "depositing_window_time_left_seconds": null,
    "status": "disputed",
    "dispute_status": "unresolved",
    "payment_method_instruction": {
      "payment_method_id": "277345",
      "payment_method_name": "Some Bank",
      "details": "Wire transfer to account #123123"
    },
    "volume_breakdown": {
      "goes_to_buyer": "10.78000000",
      "exchange_fee": "0.22000000",
      "exchange_fee_in_fiat": "77.00",
      "transaction_fee": "0.00000371"
    },
    "country": "Country 103",
    "country_code": "Country Code 103",
    "created_at": "2024-01-12T12:11:33Z",
    "counterparty": {
      "login": "us4r69",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://localhost:3000/users/us4r69",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 102",
      "country_code": "Country Code 102",
      "average_payment_time_minutes": 0,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "escrow": {
      "address": "2N1XW2j8UszEKodGQjppPdMdyHy9g44Nb8i",
      "witness_script": "522102108df32d9b16f517353b3416ba7902a5ed7d597d1def2c50faaca0f1b62a398d2102e63277915e49984aecd46f4a48616d7add727b4360b5d81f3270559f280d6f072102e63277915e49984aecd46f4a48616d7add727b4360b5d81f3270559f280d6f0753ae",
      "index": 21199,
      "you_confirmed": true,
      "counterparty_confirmed": true,
      "confirmations": 0,
      "amount_deposited": "11.00000000",
      "amount_released": null,
      "deposit_transaction_id": null,
      "release_transaction_id": null
    }
  }
}

Countries

Countries resource

Listing countries

Note. Example here doesn’t list actual countries. Do an actual query to the API server to get the list.

Endpoint

GET /api/v1/countries

Request

Route

GET /api/v1/countries

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/countries" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
countries

Countries array

countries[#].code

Code

countries[#].name

Name

countries[#].native_name

Name as written in the country’s language

countries[#].currency_code

State currency code

countries[#].currency_name

State currency name

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "countries": [
    {
      "code": "AU",
      "name": "Australia",
      "native_name": "Australia",
      "currency_code": "AUD",
      "currency_name": "Australian dollar"
    },
    {
      "code": "RU",
      "name": "Russia",
      "native_name": "Россия",
      "currency_code": "RUB",
      "currency_name": "Russian ruble"
    }
  ]
}

Currencies

Currencies resource

Listing currencies

Note. Example here doesn’t list actual currencies. Do an actual query to the API server to get the list.

Endpoint

GET /api/v1/currencies

Request

Route

GET /api/v1/currencies

cURL

curl -g "hodlhodl.com/api/v1/currencies" -X GET \
	-H "Version: HTTP/1.0"

Response

Simulated Response

Response Fields

Name Description
currencies

Currencies array

currency[#].code

Code

currency[#].name

Name

currency[#].type

“fiat” or “crypto”

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "currencies": [
    {
      "code": "AUD",
      "name": "Australian dollar",
      "type": "fiat"
    },
    {
      "code": "RUB",
      "name": "Russian ruble",
      "type": "fiat"
    }
  ]
}

Exchange rate providers

Exchange rate providers resource

Listing exchange rate providers

Note. Example here doesn’t list actual exchange rate providers. Do an actual query to the API server to get the list.

Endpoint

GET /api/v1/exchange_rate_providers

Request

Route

GET /api/v1/exchange_rate_providers

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/exchange_rate_providers" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
exchange_rate_providers

Exchange rate providers array

exchange_rate_providers[#].name

Name

exchange_rate_providers[#].currency_codes

Array of currency codes

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "exchange_rate_providers": [
    {
      "name": "Bitpay",
      "currency_codes": [
        "AUD",
        "BCH",
        "USD"
      ]
    },
    {
      "name": "Bitstamp",
      "currency_codes": [
        "AUD",
        "BCH",
        "ETH",
        "USD",
        "XRP"
      ]
    }
  ]
}

Notifications

Notifications resource

Reading notifications

This method fetches all unread notification and marks them as read.

A client must show all notifications which it fetched.

A client must show all textual fields of the notification: title, body, link. Link should be clickable. Clients should show notifications in a way suitable for a particular UI environment which client targets, ensuring best user experience.

Note: body of a notification could be multiline (standard line feeds \n will be used). Title, body and link are all plain-text (no HTML markup).

Endpoint

POST /api/v1/notifications/read

Request

Route

POST /api/v1/notifications/read

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/notifications/read" -d '' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
notifications

Notifications array

notifications[#].id

ID of notification

notifications[#].title

Title

notifications[#].body

Body (could contain \n; could be null) 1

notifications[#].link

Hyperlink (could be null)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "notifications": [
    {
      "id": "155676",
      "title": "Hello, this is a notification!",
      "body": "Dear user. The seller in one of your contracts deposited bitcoins.",
      "link": "https://hodlhodl.com/contracts/123"
    },
    {
      "id": "155677",
      "title": "Hello, this is a notification!",
      "body": "Dear user. The seller in one of your contracts deposited bitcoins.",
      "link": "https://hodlhodl.com/contracts/123"
    },
    {
      "id": "155678",
      "title": "Hello, this is a notification!",
      "body": "Dear user. The seller in one of your contracts deposited bitcoins.",
      "link": "https://hodlhodl.com/contracts/123"
    }
  ]
}

Offers

Offers resource

Getting offer

Note 1: total fee consists of “trading fee” and “transaction fee”. Trading fee is calculated as minimum among buyer and seller fee. User fee is calculated as base fee rate minus discount for online presence. Transaction fee is estimated accroding to current blockchain situation.

Note 2: list of all payment methods, used across the exchange, could be obtained by querying “Payment methods” resource.

Note 3: country and country_code will be "Global" for worldwide offers/traders.

Endpoint

GET /api/v1/offers/:id

Parameters

Name Description
id

Offer ID

Request

Route

GET /api/v1/offers/gpcW5MjTVXvbPjti

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/offers/gpcW5MjTVXvbPjti" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
offer

Offer resource

offer.id

ID

offer.version

Version

offer.asset_code

Asset code. Currently only ‘BTC’ is supported

offer.searchable

Will appear in the search? (true or false)

Note that even non-private offer can be unlisted if it’s not enabled or blocked. This field will show whether the offer will actually be shown in the search.

offer.country

Country name (or "Global")

offer.country_code

Country code (or "Global")

offer.working_now

Does current time suit working_hours_(start|end) and workdays_only (true or false)

offer.side

"buy" or "sell"

offer.title

Title

offer.description

Description

offer.currency_code

Currency code

offer.price

Price (in currency_code fiat currency)

offer.amount_source

Amount source ("sats" or "fiat")

offer.min_amount

Minimal trade amount (in currency_code fiat currency)

offer.max_amount

Maximal trade amount (in currency_code fiat currency)

offer.first_trade_limit

First trade limit (in currency_code fiat currency)

offer.balance

Balance (i.e. maximum sum of all contracts yet to be created) (in currency_code fiat currency)

offer.initial_balance

Initial balance (i.e. balance set by the user) (in currency_code fiat currency)

offer.min_amount_sats

Minimal trade amount (in satoshi)

offer.max_amount_sats

Maximal trade amount (in satoshi)

offer.first_trade_limit_sats

First trade limit (in satoshi)

offer.balance_sats

Balance (i.e. maximum sum of all contracts yet to be created) (in satoshi)

offer.initial_balance_sats

Initial balance (i.e. balance set by the user) (in satoshi)

offer.for_experienced_users

Allow create a contract with experienced users only? (true or false)

An “Experienced user” is a user who has successfully completed at least one contract and is therefore familiar with the process of trading on Hodl Hodl.

This condition is applicable only for public offers and doesn’t apply to private offers.

offer.fee

Fee details 1

offer.fee.intermediary_fee_rate

Intermediary fee rate (decimal fraction)

offer.fee.author_fee_rate

Offer’s creator fee rate (decimal fraction)

offer.fee.your_fee_rate

Your fee rate (decimal fraction) (only available in Getting offer method)

offer.fee.transaction_fee

Transaction fee estimation (BTC) (only available in Getting offer method)

offer.fee.exchange_fee

Trading fee (decimal fraction) (only available in Getting offer method)

offer.payment_window_minutes

Payment window

offer.confirmations

Blockchain confirmations required for deposit transaction in order for Contract to be considered "Deposited"

offer.payment_methods

Array of payment methods

Note: only present for “buy” offers.

offer.payment_methods[#].id

ID of the payment method

offer.payment_methods[#].type

Type of the payment method

offer.payment_methods[#].name

Name of the payment method

offer.payment_method_instructions

Array of accepted payment methods with instructions 2

Note: only present for “sell” offers.

offer.payment_method_instructions[#].id

ID of the instruction

offer.payment_method_instructions[#].version

Version

offer.payment_method_instructions[#].payment_method_id

ID of the instruction’s payment method

offer.payment_method_instructions[#].payment_method_type

Type of the instruction’s payment method

offer.payment_method_instructions[#].payment_method_name

Name of the instruction’s payment method

offer.payment_method_instructions[#].details

Text of the instruction (only shows in Getting offer method for the offer creator)

offer.trader

Offer creator information

offer.trader.login

Login

offer.trader.online_status

"online", "recently_online" or "offline"

offer.trader.rating

Rating (as fraction of 1)

offer.trader.trades_count

Number of conducted trades

offer.trader.url

Hodlhodl website URL

offer.trader.verified

Verified? (true or false)

offer.trader.verified_by

Login of the Strong Hodler who verified this user

offer.trader.strong_hodler

Strong Hodler? (true or false)

Strong Hodler is a member of Hodl Hodl volunteer team that we’re working directly with.

offer.trader.country

Country name (or "Global")

offer.trader.country_code

Country code (or "Global")

offer.trader.average_payment_time_minutes

Average payment time (in minutes)

offer.trader.average_release_time_minutes

Average release time (in minutes)

offer.trader.days_since_last_trade

Number of days since last trade

offer.trader.blocked_by

How many traders blocked this user

The following is shown only for the Offer’s creator:

offer.created_at

Creation datetime in UTC, ISO8601 (YYYY-MM-DDThh:mm:ssZ)

offer.price_source

"fixed_value", "exchange_rate"

offer.working_hours_start_utc

Working hours start in UTC (HH:MM)

offer.working_hours_end_utc

Working hours end in UTC (HH:MM)

offer.working_hours_start_in_timezone

Working hours start in (offer.timezone || offer.timezone) (HH:MM)

offer.working_hours_end_in_timezone

Working hours end in (offer.timezone || offer.timezone) (HH:MM)

offer.workdays_only

Does offer work only on workdays (true or false) default: false

offer.timezone

Offer’s timezone (null means offer uses creator’s timezone)

offer.stop_loss_value

Stop loss value (in currency_code fiat currency) or null

offer.enabled

Enabled? (true or false)

Only the offer’s creator will be able to access an offer if it is not enabled. Trades won’t be conducted. (This is the same as ‘Enabled’ checkbox in the web interface.)

offer.private

Hide the offer from search results? (true or false)

Only non-private offers will appear in the search/list website pages and API responses. (This option is the same as ‘Private’ checkbox in the website form.)

offer.configured_max_amount

Configured by the Offer’s creator maximum amount (in currency_code fiat currency)

offer.configured_max_amount_sats

Configured by the Offer’s creator maximum amount (in satoshi)

The following is shown only for the Offer’s creator in the Getting offer method and if price_source is "exchange_rate" (otherwise they will be null)

offer.exchange_rate_provider

Exchange rate provider name (null if the Offer is fixed price)

offer.exchange_price_deviation

Difference between the offer’s price and price on the exchange (null if the Offer is fixed price)

offer.exchange_price_sign

"+" or "-" (null if the Offer is fixed price)

offer.exchange_price_unit

"%" or "currency" (null if the Offer is fixed price)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "offer": {
    "id": "gpcW5MjTVXvbPjti",
    "version": "7qv4y8",
    "asset_code": "BTC",
    "searchable": true,
    "country": "Country 108",
    "country_code": "Country Code 108",
    "working_now": true,
    "side": "sell",
    "title": "Offer's title",
    "description": "You give me money, I'll give you bitcoins",
    "currency_code": "USD",
    "price": "725.53",
    "amount_source": "fiat",
    "min_amount": "0.20",
    "max_amount": "700.00",
    "first_trade_limit": null,
    "balance": null,
    "initial_balance": null,
    "min_amount_sats": "27566",
    "max_amount_sats": "96481725",
    "first_trade_limit_sats": null,
    "balance_sats": null,
    "initial_balance_sats": null,
    "fee": {
      "author_fee_rate": "0.02000000",
      "intermediary_fee_rate": "0.00000000",
      "your_fee_rate": "0.02000000",
      "transaction_fee": "0.00000371",
      "exchange_fee": "0.02000000"
    },
    "payment_window_minutes": 60,
    "confirmations": 1,
    "payment_method_instructions": [
      {
        "id": "262495",
        "version": "7zcjjs",
        "payment_method_id": "277347",
        "payment_method_type": "Online payment system",
        "payment_method_name": "Yandex Money 62"
      }
    ],
    "trader": {
      "login": "us4r72",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://hodlhodl.com/accounts/us4r72",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 107",
      "country_code": "Country Code 107",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    }
  }
}

Searching/listing offers

Note 1. All filters could be ommitted.

Endpoint

GET /api/v1/offers

Parameters

Name Description
pagination.limit

Number of records to return (default 50, maximum 100)

pagination.offset

Number of records to skip (e.g. 50 for second page of results with the default limit)

filters.asset_code

Asset code. Currently only ‘BTC’ is supported

filters.side

"buy" or "sell"

filters.include_global

Include global offers? (true or false, default false)

Note: if this parameter is true, then global offers will be included in addition to ones select by country filter.

filters.only_working_now

Does current time suit working_hours_(start|end) and workdays_only (true or false)

filters.country

Country (code or name)

filters.currency_code

Currency code

filters.payment_method_id

ID of payment method (see Payment methods/Listing payment methods)

Note: if this parameter is set, then payment_method_type and payment_method_name will be ignored.

filters.payment_method_type

Type of payment method

filters.payment_method_name

Name of payment method

filters.amount

Amount (min offer amount <= amount >= max offer amount)

filters.payment_window_minutes_max

Maximum payment window (in minutes)

filters.user_average_payment_time_minutes_max

Offer’s creator maximum payment time (in minutes)

filters.user_average_release_time_minutes_max

Offer’s creator maximum average release time (in minutes)

sort.direction

"asc" for ascending order (default) or "desc" for descdending

sort.by

Field to sort by, possible values:

  • "price" — offer’s price (default)
  • "payment_window_minutes" — offer’s payment window (in minutes)
  • "user_average_payment_time_minutes" — an offer creator’s average payment time
  • "user_average_release_time_minutes" — an offer creator’s average release time
  • "rating" — an offer creator’s rating

Request

Route

GET /api/v1/offers?filters[user_average_release_time_minutes_max]=25

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Query Parameters as JSON

{
  "filters": {
    "user_average_release_time_minutes_max": "25"
  }
}

cURL

curl -g "hodlhodl.com/api/v1/offers?filters[user_average_release_time_minutes_max]=25" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
offers

Array of Offers (see Getting offer for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "filters": {
    "user_average_release_time_minutes_max": 25,
    "only_working_now": false,
    "include_global": true
  },
  "sort": {
    "direction": "asc",
    "by": "price"
  },
  "pagination": {
    "limit": 50,
    "offset": 0
  },
  "offers": [
    {
      "id": "LsshIeQVg4iv5Igx",
      "version": "bw33ds",
      "asset_code": "BTC",
      "searchable": true,
      "country": "Country 110",
      "country_code": "Country Code 110",
      "working_now": true,
      "side": "sell",
      "title": null,
      "description": "You give me money, I'll give you bitcoins",
      "currency_code": "USD",
      "price": "725.53",
      "amount_source": "fiat",
      "min_amount": "0.20",
      "max_amount": "700.00",
      "first_trade_limit": null,
      "balance": null,
      "initial_balance": null,
      "min_amount_sats": "27566",
      "max_amount_sats": "96481725",
      "first_trade_limit_sats": null,
      "balance_sats": null,
      "initial_balance_sats": null,
      "fee": {
        "author_fee_rate": "0.02000000",
        "intermediary_fee_rate": "0.00000000",
        "your_fee_rate": "0.02000000",
        "transaction_fee": "0.00000371",
        "exchange_fee": "0.02000000"
      },
      "payment_window_minutes": 40,
      "confirmations": 1,
      "payment_method_instructions": [
        {
          "id": "262496",
          "version": "c1v9zc",
          "payment_method_id": "277348",
          "payment_method_type": "Online payment system",
          "payment_method_name": "Yandex Money 63"
        }
      ],
      "trader": {
        "login": "us4r73",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": "0.90",
        "my_review": null,
        "trades_count": 0,
        "url": "http://hodlhodl.com/accounts/us4r73",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 109",
        "country_code": "Country Code 109",
        "average_payment_time_minutes": 20,
        "average_release_time_minutes": 20,
        "days_since_last_trade": null,
        "blocked_by": 0
      }
    },
    {
      "id": "azA2zdvEXVvWpjtU",
      "version": "d6bei8",
      "asset_code": "BTC",
      "searchable": true,
      "country": "Country 111",
      "country_code": "Country Code 111",
      "working_now": true,
      "side": "sell",
      "title": null,
      "description": "You give me money, I'll give you bitcoins",
      "currency_code": "USD",
      "price": "725.53",
      "amount_source": "fiat",
      "min_amount": "0.20",
      "max_amount": "700.00",
      "first_trade_limit": null,
      "balance": null,
      "initial_balance": null,
      "min_amount_sats": "27566",
      "max_amount_sats": "96481725",
      "first_trade_limit_sats": null,
      "balance_sats": null,
      "initial_balance_sats": null,
      "fee": {
        "author_fee_rate": "0.02000000",
        "intermediary_fee_rate": "0.00000000",
        "your_fee_rate": "0.02000000",
        "transaction_fee": "0.00000371",
        "exchange_fee": "0.02000000"
      },
      "payment_window_minutes": 35,
      "confirmations": 1,
      "payment_method_instructions": [
        {
          "id": "262497",
          "version": "dbur7c",
          "payment_method_id": "277349",
          "payment_method_type": "Online payment system",
          "payment_method_name": "Yandex Money 64"
        }
      ],
      "trader": {
        "login": "us4r73",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": "0.90",
        "my_review": null,
        "trades_count": 0,
        "url": "http://hodlhodl.com/accounts/us4r73",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 109",
        "country_code": "Country Code 109",
        "average_payment_time_minutes": 20,
        "average_release_time_minutes": 20,
        "days_since_last_trade": null,
        "blocked_by": 0
      }
    }
  ]
}

Listing my offers

This method will return all your existing offers, recently created first.

Endpoint

GET /api/v1/offers/my

Request

Route

GET /api/v1/offers/my

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/offers/my" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
offers

Array of Offers (see Getting offer for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "offers": [
    {
      "id": "5bTowzRmjzzrjAfY",
      "version": "373sp4",
      "asset_code": "BTC",
      "searchable": true,
      "country": "Country 115",
      "country_code": "Country Code 115",
      "working_now": true,
      "side": "sell",
      "title": null,
      "description": "You give me money, I'll give you bitcoins",
      "currency_code": "USD",
      "price": "725.53",
      "amount_source": "fiat",
      "min_amount": "0.20",
      "max_amount": "700.00",
      "first_trade_limit": null,
      "balance": null,
      "initial_balance": null,
      "min_amount_sats": "27566",
      "max_amount_sats": "96481725",
      "first_trade_limit_sats": null,
      "balance_sats": null,
      "initial_balance_sats": null,
      "fee": {
        "author_fee_rate": "0.02000000",
        "intermediary_fee_rate": "0.00000000",
        "your_fee_rate": "0.02000000",
        "transaction_fee": "0.00000371",
        "exchange_fee": "0.02000000"
      },
      "payment_window_minutes": 35,
      "confirmations": 1,
      "payment_method_instructions": [
        {
          "id": "262500",
          "version": "3ed4vk",
          "payment_method_id": "277352",
          "payment_method_type": "Online payment system",
          "payment_method_name": "Yandex Money 67",
          "details": "Send money over to account 123"
        }
      ],
      "trader": {
        "login": "test_user",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": null,
        "my_review": null,
        "trades_count": 0,
        "url": "http://hodlhodl.com/accounts/test_user",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 113",
        "country_code": "Country Code 113",
        "average_payment_time_minutes": null,
        "average_release_time_minutes": null,
        "days_since_last_trade": null,
        "blocked_by": 0
      },
      "created_at": "2024-01-12T12:11:35Z",
      "working_hours_start_utc": "11:11",
      "working_hours_end_utc": "13:11",
      "working_hours_start_in_timezone": "11:11",
      "working_hours_end_in_timezone": "13:11",
      "timezone": "UTC",
      "workdays_only": false,
      "stop_loss_value": null,
      "enabled": true,
      "private": false,
      "for_experienced_users": false,
      "price_source": "exchange_rate",
      "exchange_rate_provider": "Bitstamp",
      "exchange_price_deviation": "2.00000000",
      "exchange_price_sign": "+",
      "exchange_price_unit": "%",
      "configured_max_amount": "700.00",
      "configured_max_amount_sats": "96481725"
    },
    {
      "id": "asMeXBzXcj2Jigum",
      "version": "1yskgg",
      "asset_code": "BTC",
      "searchable": true,
      "country": "Country 114",
      "country_code": "Country Code 114",
      "working_now": true,
      "side": "sell",
      "title": null,
      "description": "You give me money, I'll give you bitcoins",
      "currency_code": "USD",
      "price": "725.53",
      "amount_source": "fiat",
      "min_amount": "0.20",
      "max_amount": "700.00",
      "first_trade_limit": null,
      "balance": null,
      "initial_balance": null,
      "min_amount_sats": "27566",
      "max_amount_sats": "96481725",
      "first_trade_limit_sats": null,
      "balance_sats": null,
      "initial_balance_sats": null,
      "fee": {
        "author_fee_rate": "0.02000000",
        "intermediary_fee_rate": "0.00000000",
        "your_fee_rate": "0.02000000",
        "transaction_fee": "0.00000371",
        "exchange_fee": "0.02000000"
      },
      "payment_window_minutes": 40,
      "confirmations": 1,
      "payment_method_instructions": [
        {
          "id": "262499",
          "version": "24yd0w",
          "payment_method_id": "277351",
          "payment_method_type": "Online payment system",
          "payment_method_name": "Yandex Money 66",
          "details": "Send money over to account 123"
        }
      ],
      "trader": {
        "login": "test_user",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": null,
        "my_review": null,
        "trades_count": 0,
        "url": "http://hodlhodl.com/accounts/test_user",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 113",
        "country_code": "Country Code 113",
        "average_payment_time_minutes": null,
        "average_release_time_minutes": null,
        "days_since_last_trade": null,
        "blocked_by": 0
      },
      "created_at": "2024-01-12T12:11:35Z",
      "working_hours_start_utc": "11:11",
      "working_hours_end_utc": "13:11",
      "working_hours_start_in_timezone": "11:11",
      "working_hours_end_in_timezone": "13:11",
      "timezone": "UTC",
      "workdays_only": false,
      "stop_loss_value": null,
      "enabled": true,
      "private": false,
      "for_experienced_users": false,
      "price_source": "exchange_rate",
      "exchange_rate_provider": "Bitstamp",
      "exchange_price_deviation": "2.00000000",
      "exchange_price_sign": "+",
      "exchange_price_unit": "%",
      "configured_max_amount": "700.00",
      "configured_max_amount_sats": "96481725"
    }
  ]
}

Fetching newly created offers

This method allows you to fetch newly created offer.

Store pagination.last_id from the first response of this method call on the client. Provide pagination.last_id as pagination.newer_than_id parameter to the next method call to fetch offers which were created strictly after the one with last_id. Repeat until all offers are fetched (offers is []).

Pseudocode to fetch all offers would look like this:

last_id = retrieve_last_id_from_local_db || null
result = fetch_new("pagination": {"newer_than_id": last_id})

while result["offers"] != []
  save_offers_to_local_db(result["offers"])

  last_id = result["pagination"]["last_id"]
  result = fetch_new("pagination": {"newer_than_id": last_id})
end

save_last_id_to_local_db(last_id)

Offers in the response will always be sorted from the oldest to the newest.

Endpoint

GET /api/v1/offers/fetch_new

Parameters

Name Description
pagination.newer_than_id

Set to pagination.last_id value from the previous request (omit it or set to known offer’s ID as initial value)

filters.asset_code

Asset code. Currently only ‘BTC’ is supported

filters.side

"buy" or "sell"

filters.include_global

Include global offers? (true or false, default false)

Note: if this parameter is true, then global offers will be included in addition to ones selected by country filter.

filters.only_working_now

Does current time suit working_hours_(start|end) and workdays_only (true or false, default false)

filters.country

Country (code or name)

filters.currency_code

Currency code

filters.payment_method_id

ID of payment method (see Payment methods/Listing payment methods)

Note: if this parameter is set, then payment_method_type and payment_method_name will be ignored.

filters.payment_method_type

Type of payment method (see Payment methods/Listing payment methods)

filters.payment_method_name

Name of payment method

filters.amount

Amount (min offer amount <= amount >= max offer amount)

filters.payment_window_minutes_max

Maximum payment window (in minutes)

filters.user_average_payment_time_minutes_max

Offer’s creator maximum payment time (in minutes)

filters.user_average_release_time_minutes_max

Offer’s creator maximum average release time (in minutes)

Request

Route

GET /api/v1/offers/fetch_new?filters[user_average_release_time_minutes_max]=25&pagination[newer_than_id]=RGsLjZ2M7elLokAm

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Query Parameters as JSON

{
  "filters": {
    "user_average_release_time_minutes_max": "25"
  },
  "pagination": {
    "newer_than_id": "RGsLjZ2M7elLokAm"
  }
}

cURL

curl -g "hodlhodl.com/api/v1/offers/fetch_new?filters[user_average_release_time_minutes_max]=25&pagination[newer_than_id]=RGsLjZ2M7elLokAm" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
offers

Array of Offers (see Offers/Getting offer for fields description)

filters

Filters values (fetched from the parameters and/or default ones)

pagination.last_id

Newest offer ID to store on the client

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "filters": {
    "user_average_release_time_minutes_max": 25,
    "only_working_now": false,
    "include_global": true
  },
  "pagination": {
    "newer_than_id": "RGsLjZ2M7elLokAm",
    "last_id": "OWY6oTOBTYaWgYDe"
  },
  "offers": [
    {
      "id": "zKJt9iHh2FH65JRq",
      "version": "97weqw",
      "asset_code": "BTC",
      "searchable": true,
      "country": "Country 119",
      "country_code": "Country Code 119",
      "working_now": true,
      "side": "sell",
      "title": null,
      "description": "You give me money, I'll give you bitcoins",
      "currency_code": "USD",
      "price": "725.53",
      "amount_source": "fiat",
      "min_amount": "0.20",
      "max_amount": "700.00",
      "first_trade_limit": null,
      "balance": null,
      "initial_balance": null,
      "min_amount_sats": "27566",
      "max_amount_sats": "96481725",
      "first_trade_limit_sats": null,
      "balance_sats": null,
      "initial_balance_sats": null,
      "fee": {
        "author_fee_rate": "0.02000000",
        "intermediary_fee_rate": "0.00000000",
        "your_fee_rate": "0.02000000",
        "transaction_fee": "0.00000371",
        "exchange_fee": "0.02000000"
      },
      "payment_window_minutes": 35,
      "confirmations": 1,
      "payment_method_instructions": [
        {
          "id": "262503",
          "version": "9dcl8w",
          "payment_method_id": "277355",
          "payment_method_type": "Online payment system",
          "payment_method_name": "Yandex Money 70"
        }
      ],
      "trader": {
        "login": "us4r76",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": "0.90",
        "my_review": null,
        "trades_count": 0,
        "url": "http://hodlhodl.com/accounts/us4r76",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 117",
        "country_code": "Country Code 117",
        "average_payment_time_minutes": 20,
        "average_release_time_minutes": 20,
        "days_since_last_trade": null,
        "blocked_by": 0
      }
    },
    {
      "id": "OWY6oTOBTYaWgYDe",
      "version": "ahiksw",
      "asset_code": "BTC",
      "searchable": true,
      "country": "Country 120",
      "country_code": "Country Code 120",
      "working_now": true,
      "side": "sell",
      "title": null,
      "description": "You give me money, I'll give you bitcoins",
      "currency_code": "USD",
      "price": "725.53",
      "amount_source": "fiat",
      "min_amount": "0.20",
      "max_amount": "700.00",
      "first_trade_limit": null,
      "balance": null,
      "initial_balance": null,
      "min_amount_sats": "27566",
      "max_amount_sats": "96481725",
      "first_trade_limit_sats": null,
      "balance_sats": null,
      "initial_balance_sats": null,
      "fee": {
        "author_fee_rate": "0.02000000",
        "intermediary_fee_rate": "0.00000000",
        "your_fee_rate": "0.02000000",
        "transaction_fee": "0.00000371",
        "exchange_fee": "0.02000000"
      },
      "payment_window_minutes": 34,
      "confirmations": 1,
      "payment_method_instructions": [
        {
          "id": "262504",
          "version": "amsewo",
          "payment_method_id": "277356",
          "payment_method_type": "Online payment system",
          "payment_method_name": "Yandex Money 71"
        }
      ],
      "trader": {
        "login": "us4r76",
        "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
        "online_status": "offline",
        "rating": "0.90",
        "my_review": null,
        "trades_count": 0,
        "url": "http://hodlhodl.com/accounts/us4r76",
        "verified": false,
        "verified_by": null,
        "strong_hodler": false,
        "country": "Country 117",
        "country_code": "Country Code 117",
        "average_payment_time_minutes": 20,
        "average_release_time_minutes": 20,
        "days_since_last_trade": null,
        "blocked_by": 0
      }
    }
  ]
}

Creating offer

Endpoint

POST /api/v1/offers

Parameters

Name Description
offer.asset_code

Asset code. Currently only ‘BTC’ is supported

offer.side

"buy" or "sell" (required)

offer.country_code

Country code (assumed Global if ommited)

offer.currency_code

Currency code (required)

Use Currencies/Listring currencies to get currency code.

offer.stop_loss_value

Stop loss value (in currency_code fiat currency)

offer.for_experienced_users

Allow create a contract with experienced users only? (true or false)

An “Experienced user” is a user who has successfully completed at least one contract and is therefore familiar with the process of trading on Hodl Hodl.

This condition is applicable only for public offers and doesn’t apply to private offers.

offer.confirmations

Blockchain confirmations required for deposit transaction in order for Contract to be considered "Deposited" (default 1)

offer.payment_window_minutes

Payment window (default 90)

offer.workdays_only

true or false (default false)

offer.title

Title

offer.description

Description

offer.enabled

Enabled? (true or false, default false)

Only the offer’s creator will be able to access an offer if it is not enabled. Trades won’t be conducted. (This is the same as ‘Enabled’ checkbox in the web interface.)

offer.private

Hide the offer from search results? (true or false)

Only non-private offers will appear in the search/list website pages and API responses. (This option is the same as ‘Private’ checkbox in the website form.)

offer.payment_method_ids

Array of payment method IDs (see Payment methods/Listing payment methods)

Note: required only for “buy” offers.

offer.payment_method_instruction_ids

Array of payment method instruction IDs (see Payment method instructions)

Note: required only for “sell” offers.

this fields sets amount source to fiat

offer.balance

Balance (i.e. maximum sum of all contracts yet to be created) (in currency_code fiat currency)

offer.min_amount

Minimal trade amount (in currency_code fiat currency) (required)

offer.max_amount

Maximal trade amount (in currency_code fiat currency) (required, 0 for auto-adjust)

offer.first_trade_limit

First trade limit (in currency_code fiat currency)

this fields sets amount source to satoshi

offer.balance_sats

Balance (i.e. maximum sum of all contracts yet to be created) (in satoshi)

offer.min_amount_sats

Minimal trade amount (in satoshi) (required)

offer.max_amount_sats

Maximal trade amount (in satoshi) (required, 0 for auto-adjust)

offer.first_trade_limit_sats

First trade limit (in satoshi)

Managing working hours

offer.working_hours_start_in_timezone

Working hours start in (offer.timezone || user.timezone) (HH:MM)

(default "00:00", half hours increments)

offer.working_hours_end_in_timezone

Working hours end in (offer.timezone || user.timezone) (HH:MM)

(default "00:00", half hours increments)

offer.timezone

Offer’s timezone (Sets timezone different from user.timezone)

(available only with working_hours_start_in_timezone and working_hours_end_in_timezone)

or

offer.working_hours_start_utc

Working hours start in UTC (HH:MM) (half hours increments)

implicitly sets offer.timezone to UTC

offer.working_hours_end_utc

Working hours end in UTC (HH:MM) (half hours increments)

implicitly sets offer.timezone to UTC

If you want to create a fixed-price offer:

offer.price_source

"fixed_value" (required)

offer.price

Price (in currency_code fiat currency) (required)

If you want to create an offer which price follows external exchange rate:

offer.price_source

"exchange_rate" (required)

offer.exchange_rate_provider

Exchange rate provider name (required)

offer.exchange_price_deviation

Difference between the offer’s price and price on the exchange (required)

offer.exchange_price_sign

"+" or "-" (default "+")

offer.exchange_price_unit

"%" or "currency" (default "%")

Request

Route

POST /api/v1/offers

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "offer": {
    "asset_code": "BTC",
    "currency_code": "USD",
    "price_source": "fixed_value",
    "price": 700.0,
    "balance": 20000,
    "side": "buy",
    "country_code": "AU",
    "min_amount": 1.0,
    "max_amount": 6000.0,
    "first_trade_limit": 100,
    "for_experienced_users": false,
    "confirmations": 2,
    "payment_window_minutes": 30,
    "working_hours_start_utc": "02:00",
    "working_hours_end_utc": "06:00",
    "description": "The Description",
    "title": "The Title",
    "enabled": true,
    "private": false,
    "payment_method_ids": [
      277358
    ]
  }
}

cURL

curl "hodlhodl.com/api/v1/offers" -d '{"offer":{"asset_code":"BTC","currency_code":"USD","price_source":"fixed_value","price":700.0,"balance":20000,"side":"buy","country_code":"AU","min_amount":1.0,"max_amount":6000.0,"first_trade_limit":100,"for_experienced_users":false,"confirmations":2,"payment_window_minutes":30,"working_hours_start_utc":"02:00","working_hours_end_utc":"06:00","description":"The Description","title":"The Title","enabled":true,"private":false,"payment_method_ids":[277358]}}' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
offer

Offer (newly created; see Getting offer for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "offer": {
    "id": "rgqqGeSz9SwJzwaK",
    "version": "g6h4bc",
    "asset_code": "BTC",
    "searchable": true,
    "country": "Australia",
    "country_code": "AU",
    "working_now": false,
    "side": "buy",
    "title": "The Title",
    "description": "The Description",
    "currency_code": "USD",
    "price": "700.00",
    "amount_source": "fiat",
    "min_amount": "1.00",
    "max_amount": "6000.00",
    "first_trade_limit": "100.00",
    "balance": "20000.00",
    "initial_balance": "20000.00",
    "min_amount_sats": "142857",
    "max_amount_sats": "857142857",
    "first_trade_limit_sats": "14285714",
    "balance_sats": "2857142857",
    "initial_balance_sats": "2857142857",
    "fee": {
      "author_fee_rate": "0.02000000",
      "intermediary_fee_rate": "0.00000000",
      "your_fee_rate": "0.02000000",
      "transaction_fee": "0.00000371",
      "exchange_fee": "0.02000000"
    },
    "payment_window_minutes": 30,
    "confirmations": 2,
    "payment_methods": [
      {
        "id": "277358",
        "type": "Bank wire",
        "name": "Yandex Money 73"
      }
    ],
    "trader": {
      "login": "test_user",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://hodlhodl.com/accounts/test_user",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 122",
      "country_code": "Country Code 122",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "created_at": "2024-01-12T12:11:35Z",
    "working_hours_start_utc": "02:00",
    "working_hours_end_utc": "06:00",
    "working_hours_start_in_timezone": "02:00",
    "working_hours_end_in_timezone": "06:00",
    "timezone": "UTC",
    "workdays_only": false,
    "stop_loss_value": null,
    "enabled": true,
    "private": false,
    "for_experienced_users": false,
    "price_source": "fixed_value",
    "exchange_rate_provider": null,
    "exchange_price_deviation": null,
    "exchange_price_sign": null,
    "exchange_price_unit": null,
    "configured_max_amount": "6000.00",
    "configured_max_amount_sats": "857142857"
  }
}

Updating offer

All parameters (except ID) are optional.

An attribute does’t change if the corresponding parameter isn’t set.

Parameters are the same as in Creating offer method

Endpoint

PUT /api/v1/offers/:id

Parameters

Name Description
id

Offer ID (required)

offer.side

Offer's side "buy" or "sell"

offer.country_code

Country code (assumed Global if ommited)

offer.stop_loss_value

Stop loss value (in currency_code fiat currency)

offer.for_experienced_users

Allow create a contract with experienced users only? (true or false)

An “Experienced user” is a user who has successfully completed at least one contract and is therefore familiar with the process of trading on Hodl Hodl.

This condition is applicable only for public offers and doesn’t apply to private offers.

offer.confirmations

Blockchain confirmations required for deposit transaction in order for Contract to be considered "Deposited"

offer.payment_window_minutes

Payment window, in minutes

offer.workdays_only

true or false (default false)

offer.title

Title

offer.description

Description

offer.enabled

Enabled? (true or false)

Only the offer’s creator will be able to access an offer if it is not enabled. Trades won’t be conducted. (This is the same as ‘Enabled’ checkbox in the web interface.)

offer.private

Hide the offer from search results? (true or false)

Only non-private offers will appear in the search/list website pages and API responses. (This option is the same as ‘Private’ checkbox in the website form.)

offer.payment_method_ids

Array of payment method IDs (see Payment methods/Listing payment methods)

Note: only use it for “buy” offers.

offer.payment_method_instruction_ids

Array of payment method instruction IDs (see Payment method instructions)

Note: only use it for “sell” offers.

this fields sets amount source to fiat

offer.balance

Balance (i.e. maximum sum of all contracts yet to be created) (in currency_code fiat currency)

offer.min_amount

Minimal trade amount (in currency_code fiat currency) (required)

offer.max_amount

Maximal trade amount (in currency_code fiat currency) (required, 0 for auto-adjust)

offer.first_trade_limit

First trade limit (in currency_code fiat currency)

this fields sets amount source to satoshi

offer.balance_sats

Balance (i.e. maximum sum of all contracts yet to be created) (in satoshi)

offer.min_amount_sats

Minimal trade amount (in satoshi) (required)

offer.max_amount_sats

Maximal trade amount (in satoshi) (required, 0 for auto-adjust)

offer.first_trade_limit_sats

First trade limit (in satoshi)

Managing working hours

offer.working_hours_start_in_timezone

Working hours start in (offer.timezone || user.timezone) (HH:MM)

(default "00:00", half hours increments)

offer.working_hours_end_in_timezone

Working hours end in (offer.timezone || user.timezone) (HH:MM)

(default "00:00", half hours increments)

offer.timezone

Offer’s timezone (Sets timezone different from user.timezone)

(available only with working_hours_start_in_timezone and working_hours_end_in_timezone)

or

offer.working_hours_start_utc

Working hours start in UTC (HH:MM) (half hours increments)

implicitly sets offer.timezone to UTC

offer.working_hours_end_utc

Working hours end in UTC (HH:MM) (half hours increments)

implicitly sets offer.timezone to UTC

If you want to update a fixed-price offer (provide none or all of the following):

offer.price_source

"fixed_value"

offer.price

Price (in currency_code fiat currency)

offer.currency_code

Currency code

Use Currencies/Listring currencies to get currency code.

If you want to update an offer which price follows external exchange rate (provide none or all of the following):

offer.price_source

"exchange_rate"

offer.exchange_rate_provider

Exchange rate provider name

offer.exchange_price_deviation

Difference between the offer’s price and price on the exchange

offer.exchange_price_sign

"+" or "-"

offer.exchange_price_unit

"%" or "currency"

offer.currency_code

Currency code

Use Currencies/Listring currencies to get currency code.

Request

Route

PUT /api/v1/offers/IsOppWT7mv0mvOR1

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "offer": {
    "title": "New title",
    "description": "New description"
  }
}

cURL

curl "hodlhodl.com/api/v1/offers/IsOppWT7mv0mvOR1" -d '{"offer":{"title":"New title","description":"New description"}}' -X PUT \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
offer

Offer (which was updated; see Getting offer for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "offer": {
    "id": "IsOppWT7mv0mvOR1",
    "version": "4cwsxt",
    "asset_code": "BTC",
    "searchable": true,
    "country": "Country 124",
    "country_code": "Country Code 124",
    "working_now": true,
    "side": "sell",
    "title": "New title",
    "description": "New description",
    "currency_code": "USD",
    "price": "725.53",
    "amount_source": "fiat",
    "min_amount": "0.20",
    "max_amount": "700.00",
    "first_trade_limit": null,
    "balance": null,
    "initial_balance": null,
    "min_amount_sats": "27566",
    "max_amount_sats": "96481725",
    "first_trade_limit_sats": null,
    "balance_sats": null,
    "initial_balance_sats": null,
    "fee": {
      "author_fee_rate": "0.02000000",
      "intermediary_fee_rate": "0.00000000",
      "your_fee_rate": "0.02000000",
      "transaction_fee": "0.00000371",
      "exchange_fee": "0.02000000"
    },
    "payment_window_minutes": 60,
    "confirmations": 1,
    "payment_method_instructions": [
      {
        "id": "262506",
        "version": "31hc48",
        "payment_method_id": "277359",
        "payment_method_type": "Online payment system",
        "payment_method_name": "Yandex Money 74",
        "details": "Send money over to account 123"
      }
    ],
    "trader": {
      "login": "test_user",
      "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
      "online_status": "offline",
      "rating": null,
      "my_review": null,
      "trades_count": 0,
      "url": "http://hodlhodl.com/accounts/test_user",
      "verified": false,
      "verified_by": null,
      "strong_hodler": false,
      "country": "Country 123",
      "country_code": "Country Code 123",
      "average_payment_time_minutes": null,
      "average_release_time_minutes": null,
      "days_since_last_trade": null,
      "blocked_by": 0
    },
    "created_at": "2024-01-12T12:11:36Z",
    "working_hours_start_utc": "11:11",
    "working_hours_end_utc": "13:11",
    "working_hours_start_in_timezone": "11:11",
    "working_hours_end_in_timezone": "13:11",
    "timezone": "UTC",
    "workdays_only": false,
    "stop_loss_value": null,
    "enabled": true,
    "private": false,
    "for_experienced_users": false,
    "price_source": "exchange_rate",
    "exchange_rate_provider": "Bitstamp",
    "exchange_price_deviation": "2.00000000",
    "exchange_price_sign": "+",
    "exchange_price_unit": "%",
    "configured_max_amount": "700.00",
    "configured_max_amount_sats": "96481725"
  }
}

Deleting offer

Endpoint

DELETE /api/v1/offers/:id

Parameters

Name Description
id

Offer ID

Request

Route

DELETE /api/v1/offers/g81w2k7lo0CD0PiY

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/offers/g81w2k7lo0CD0PiY" -d '' -X DELETE \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Status

204

Fetching tied to exchange price value

Price is calculated from base value - market rate taken from one of supported exchanges and deviation from that rate. Deviation can be defied in percent (+10%) or as absolute value (-200 USD).

In example below we assume that current BTC/USD rate on Bitstamp is equal to 5000.

Endpoint

GET /api/v1/offers/exchange_rate_price

Parameters

Name Description
asset_code

Cryptocurrency asset code. Currently only ‘BTC’ is supported

currency_code

Fiat currency code

provider

Exchange rate provider name (see exchange rates list)

deviation

Deviation from exchange value

sign

+ or - for adding or substraction from provider rate

unit

Deviation unit. Can be % for relative values or currency for absolute values

Request

Route

GET /api/v1/offers/exchange_rate_price?asset_code=BTC&currency_code=USD&provider=Bitstamp&deviation=40&sign=%2B&unit=currency

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Query Parameters as JSON

{
  "asset_code": "BTC",
  "currency_code": "USD",
  "provider": "Bitstamp",
  "deviation": "40",
  "sign": "+",
  "unit": "currency"
}

cURL

curl -g "hodlhodl.com/api/v1/offers/exchange_rate_price?asset_code=BTC&currency_code=USD&provider=Bitstamp&deviation=40&sign=%2B&unit=currency" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
price

Price

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "price": "5040.00"
}

Payment method instructions

Payment method instructions resource

Note. You can view (list, delete) only payment method instructions which you have created. Payment method instruction is relevant to your ‘sell’ orders — they connect general payment method (e.g. “Online payment system -> Moneygram”) with your specific details (e.g. “Pay to account No. 12345”).

Listing payment method instructions

Endpoint

GET /api/v1/payment_method_instructions

Request

Route

GET /api/v1/payment_method_instructions

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/payment_method_instructions" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
payment_method_instructions

Array of Payment method instructions (see Getting payment method instruction for fields description)”

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "payment_method_instructions": [
    {
      "id": "262508",
      "version": "c2auxs",
      "payment_method_id": "277361",
      "name": "Bank account #1",
      "details": "Pay to account No. 12345",
      "created_at": "2024-01-12T12:11:36Z",
      "updated_at": "2024-01-12T12:11:36Z"
    },
    {
      "id": "262509",
      "version": "cbfji0",
      "payment_method_id": "277361",
      "name": "Bank account #2",
      "details": "Pay to account No. 67890",
      "created_at": "2024-01-12T12:11:36Z",
      "updated_at": "2024-01-12T12:11:36Z"
    }
  ]
}

Getting payment method instruction

Endpoint

GET /api/v1/payment_method_instructions/:id

Parameters

Name Description
id

Payment method instruction ID

Request

Route

GET /api/v1/payment_method_instructions/262511

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/payment_method_instructions/262511" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
payment_method_instruction

Payment method instruction

payment_method_instruction.id

ID

payment_method_instruction.version

Version

payment_method_instruction.payment_method_id

Payment method ID

payment_method_instruction.name

Name (visible only to you)

payment_method_instruction.details

Text of the instruction

payment_method_instruction.created_at

Date-time of creation (ISO 8601)

payment_method_instruction.updated_at

Date-time of last update (ISO 8601)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "payment_method_instruction": {
    "id": "262511",
    "version": "fi3ew8",
    "payment_method_id": "277362",
    "name": "Bank account #1",
    "details": "Pay to account No. 12345",
    "created_at": "2024-01-12T12:11:36Z",
    "updated_at": "2024-01-12T12:11:36Z"
  }
}

Deleting payment method instruction

Endpoint

DELETE /api/v1/payment_method_instructions/:id

Parameters

Name Description
id

Payment method instruction ID

Request

Route

DELETE /api/v1/payment_method_instructions/262512

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl "hodlhodl.com/api/v1/payment_method_instructions/262512" -d '' -X DELETE \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success"
}

Creating payment method instruction

Endpoint

POST /api/v1/payment_method_instructions

Parameters

Name Description
payment_method_instruction.payment_method_id

Payment method ID

payment_method_instruction.name

Name (visible only to you)

payment_method_instruction.details

Text of the instruction

Request

Route

POST /api/v1/payment_method_instructions

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "payment_method_instruction": {
    "name": "Bank account #1",
    "details": "Pay to account No. 12345",
    "payment_method_id": 277366
  }
}

cURL

curl "hodlhodl.com/api/v1/payment_method_instructions" -d '{"payment_method_instruction":{"name":"Bank account #1","details":"Pay to account No. 12345","payment_method_id":277366}}' -X POST \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
payment_method_instruction

Payment method instruction (see Getting payment method instruction for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "payment_method_instruction": {
    "id": "262515",
    "version": "7sw451",
    "payment_method_id": "277366",
    "name": "Bank account #1",
    "details": "Pay to account No. 12345",
    "created_at": "2024-01-12T12:11:37Z",
    "updated_at": "2024-01-12T12:11:37Z"
  }
}

Updating payment method instruction

Endpoint

PUT /api/v1/payment_method_instructions/:id

Parameters

Name Description
id

Payment method instruction ID

payment_method_instruction.payment_method_id

Payment method ID

payment_method_instruction.name

Name (visible only to you)

payment_method_instruction.details

Text of the instruction

Request

Route

PUT /api/v1/payment_method_instructions/262516

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Body

{
  "payment_method_instruction": {
    "name": "Bank account #2",
    "details": "Pay to account No. 54321",
    "payment_method_id": 277369
  }
}

cURL

curl "hodlhodl.com/api/v1/payment_method_instructions/262516" -d '{"payment_method_instruction":{"name":"Bank account #2","details":"Pay to account No. 54321","payment_method_id":277369}}' -X PUT \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
payment_method_instruction

Payment method instruction (see Getting payment method instruction for fields description)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "payment_method_instruction": {
    "id": "262516",
    "version": "dfev9a",
    "payment_method_id": "277369",
    "name": "Bank account #2",
    "details": "Pay to account No. 54321",
    "created_at": "2024-01-12T12:11:37Z",
    "updated_at": "2024-01-12T12:11:37Z"
  }
}

Payment methods

Payment methods resource

Listing payment methods

Note. Payment method type is one of the following:

  • "Bank wire"
  • "Cash"
  • "Cryptocurrency"
  • "Online payment system"

Endpoint

GET /api/v1/payment_methods

Parameters

Name Description
filters.country

Country name or code ("Global" to list global payment methods, omit to return all payment methods)

Request

Route

GET /api/v1/payment_methods?filters[country]=China

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

Query Parameters as JSON

{
  "filters": {
    "country": "China"
  }
}

cURL

curl -g "hodlhodl.com/api/v1/payment_methods?filters[country]=China" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
payment_methods

Payment methods array

payment_methods[#].id

ID

payment_methods[#].type

Type

payment_methods[#].name

Name

payment_methods[#].country_codes

Array of country codes

payment_methods[#].description

Description

payment_methods[#].discounted

Discounted? (true or false)

payment_methods[#].global

Global? (true or false)

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "filters": {
    "country": "China"
  },
  "payment_methods": [
    {
      "id": "277371",
      "type": "Bank wire",
      "name": "Example payment system (two countries)",
      "country_codes": [
        "CHN"
      ],
      "description": {
      },
      "discounted": false,
      "global": false
    },
    {
      "id": "277370",
      "type": "Online payment system",
      "name": "Example payment system (single country)",
      "country_codes": [
        "CHN"
      ],
      "description": {
      },
      "discounted": false,
      "global": false
    }
  ]
}

Timezones

Timezones resource

Listing timezones

Endpoint

GET /api/v1/timezones

Request

Route

GET /api/v1/timezones

cURL

curl -g "hodlhodl.com/api/v1/timezones" -X GET \
	-H "Version: HTTP/1.0"

Response

Simulated Response

Response Fields

Name Description
name

Timezone name

gmt_offset

Timezone GMT offset

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "timezones": [
    {
      "name": "Abu Dhabi",
      "gmt_offset": "+04:00"
    },
    {
      "name": "Adelaide",
      "gmt_offset": "+09:30"
    },
    {
      "name": "Alaska",
      "gmt_offset": "-09:00"
    },
    {
      "name": "Almaty",
      "gmt_offset": "+06:00"
    },
    {
      "name": "American Samoa",
      "gmt_offset": "-11:00"
    },
    {
      "name": "Amsterdam",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Arizona",
      "gmt_offset": "-07:00"
    },
    {
      "name": "Astana",
      "gmt_offset": "+06:00"
    },
    {
      "name": "Athens",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Atlantic Time (Canada)",
      "gmt_offset": "-04:00"
    },
    {
      "name": "Auckland",
      "gmt_offset": "+12:00"
    },
    {
      "name": "Azores",
      "gmt_offset": "-01:00"
    },
    {
      "name": "Baghdad",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Baku",
      "gmt_offset": "+04:00"
    },
    {
      "name": "Bangkok",
      "gmt_offset": "+07:00"
    },
    {
      "name": "Beijing",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Belgrade",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Berlin",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Bern",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Bogota",
      "gmt_offset": "-05:00"
    },
    {
      "name": "Brasilia",
      "gmt_offset": "-03:00"
    },
    {
      "name": "Bratislava",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Brisbane",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Brussels",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Bucharest",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Budapest",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Buenos Aires",
      "gmt_offset": "-03:00"
    },
    {
      "name": "Cairo",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Canberra",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Cape Verde Is.",
      "gmt_offset": "-01:00"
    },
    {
      "name": "Caracas",
      "gmt_offset": "-04:00"
    },
    {
      "name": "Casablanca",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Central America",
      "gmt_offset": "-06:00"
    },
    {
      "name": "Central Time (US & Canada)",
      "gmt_offset": "-06:00"
    },
    {
      "name": "Chatham Is.",
      "gmt_offset": "+12:45"
    },
    {
      "name": "Chennai",
      "gmt_offset": "+05:30"
    },
    {
      "name": "Chihuahua",
      "gmt_offset": "-07:00"
    },
    {
      "name": "Chongqing",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Copenhagen",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Darwin",
      "gmt_offset": "+09:30"
    },
    {
      "name": "Dhaka",
      "gmt_offset": "+06:00"
    },
    {
      "name": "Dublin",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Eastern Time (US & Canada)",
      "gmt_offset": "-05:00"
    },
    {
      "name": "Edinburgh",
      "gmt_offset": "+00:00"
    },
    {
      "name": "Ekaterinburg",
      "gmt_offset": "+05:00"
    },
    {
      "name": "Fiji",
      "gmt_offset": "+12:00"
    },
    {
      "name": "Georgetown",
      "gmt_offset": "-04:00"
    },
    {
      "name": "Greenland",
      "gmt_offset": "-03:00"
    },
    {
      "name": "Guadalajara",
      "gmt_offset": "-06:00"
    },
    {
      "name": "Guam",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Hanoi",
      "gmt_offset": "+07:00"
    },
    {
      "name": "Harare",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Hawaii",
      "gmt_offset": "-10:00"
    },
    {
      "name": "Helsinki",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Hobart",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Hong Kong",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Indiana (East)",
      "gmt_offset": "-05:00"
    },
    {
      "name": "International Date Line West",
      "gmt_offset": "-12:00"
    },
    {
      "name": "Irkutsk",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Islamabad",
      "gmt_offset": "+05:00"
    },
    {
      "name": "Istanbul",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Jakarta",
      "gmt_offset": "+07:00"
    },
    {
      "name": "Jerusalem",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Kabul",
      "gmt_offset": "+04:30"
    },
    {
      "name": "Kaliningrad",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Kamchatka",
      "gmt_offset": "+12:00"
    },
    {
      "name": "Karachi",
      "gmt_offset": "+05:00"
    },
    {
      "name": "Kathmandu",
      "gmt_offset": "+05:45"
    },
    {
      "name": "Kolkata",
      "gmt_offset": "+05:30"
    },
    {
      "name": "Krasnoyarsk",
      "gmt_offset": "+07:00"
    },
    {
      "name": "Kuala Lumpur",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Kuwait",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Kyiv",
      "gmt_offset": "+02:00"
    },
    {
      "name": "La Paz",
      "gmt_offset": "-04:00"
    },
    {
      "name": "Lima",
      "gmt_offset": "-05:00"
    },
    {
      "name": "Lisbon",
      "gmt_offset": "+00:00"
    },
    {
      "name": "Ljubljana",
      "gmt_offset": "+01:00"
    },
    {
      "name": "London",
      "gmt_offset": "+00:00"
    },
    {
      "name": "Madrid",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Magadan",
      "gmt_offset": "+11:00"
    },
    {
      "name": "Marshall Is.",
      "gmt_offset": "+12:00"
    },
    {
      "name": "Mazatlan",
      "gmt_offset": "-07:00"
    },
    {
      "name": "Melbourne",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Mexico City",
      "gmt_offset": "-06:00"
    },
    {
      "name": "Mid-Atlantic",
      "gmt_offset": "-02:00"
    },
    {
      "name": "Midway Island",
      "gmt_offset": "-11:00"
    },
    {
      "name": "Minsk",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Monrovia",
      "gmt_offset": "+00:00"
    },
    {
      "name": "Monterrey",
      "gmt_offset": "-06:00"
    },
    {
      "name": "Montevideo",
      "gmt_offset": "-03:00"
    },
    {
      "name": "Moscow",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Mountain Time (US & Canada)",
      "gmt_offset": "-07:00"
    },
    {
      "name": "Mumbai",
      "gmt_offset": "+05:30"
    },
    {
      "name": "Muscat",
      "gmt_offset": "+04:00"
    },
    {
      "name": "Nairobi",
      "gmt_offset": "+03:00"
    },
    {
      "name": "New Caledonia",
      "gmt_offset": "+11:00"
    },
    {
      "name": "New Delhi",
      "gmt_offset": "+05:30"
    },
    {
      "name": "Newfoundland",
      "gmt_offset": "-03:30"
    },
    {
      "name": "Novosibirsk",
      "gmt_offset": "+07:00"
    },
    {
      "name": "Nuku'alofa",
      "gmt_offset": "+13:00"
    },
    {
      "name": "Osaka",
      "gmt_offset": "+09:00"
    },
    {
      "name": "Pacific Time (US & Canada)",
      "gmt_offset": "-08:00"
    },
    {
      "name": "Paris",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Perth",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Port Moresby",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Prague",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Pretoria",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Puerto Rico",
      "gmt_offset": "-04:00"
    },
    {
      "name": "Quito",
      "gmt_offset": "-05:00"
    },
    {
      "name": "Rangoon",
      "gmt_offset": "+06:30"
    },
    {
      "name": "Riga",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Riyadh",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Rome",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Samara",
      "gmt_offset": "+04:00"
    },
    {
      "name": "Samoa",
      "gmt_offset": "+13:00"
    },
    {
      "name": "Santiago",
      "gmt_offset": "-04:00"
    },
    {
      "name": "Sapporo",
      "gmt_offset": "+09:00"
    },
    {
      "name": "Sarajevo",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Saskatchewan",
      "gmt_offset": "-06:00"
    },
    {
      "name": "Seoul",
      "gmt_offset": "+09:00"
    },
    {
      "name": "Singapore",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Skopje",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Sofia",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Solomon Is.",
      "gmt_offset": "+11:00"
    },
    {
      "name": "Srednekolymsk",
      "gmt_offset": "+11:00"
    },
    {
      "name": "Sri Jayawardenepura",
      "gmt_offset": "+05:30"
    },
    {
      "name": "St. Petersburg",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Stockholm",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Sydney",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Taipei",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Tallinn",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Tashkent",
      "gmt_offset": "+05:00"
    },
    {
      "name": "Tbilisi",
      "gmt_offset": "+04:00"
    },
    {
      "name": "Tehran",
      "gmt_offset": "+03:30"
    },
    {
      "name": "Tijuana",
      "gmt_offset": "-08:00"
    },
    {
      "name": "Tokelau Is.",
      "gmt_offset": "+13:00"
    },
    {
      "name": "Tokyo",
      "gmt_offset": "+09:00"
    },
    {
      "name": "UTC",
      "gmt_offset": "+00:00"
    },
    {
      "name": "Ulaanbaatar",
      "gmt_offset": "+08:00"
    },
    {
      "name": "Urumqi",
      "gmt_offset": "+06:00"
    },
    {
      "name": "Vienna",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Vilnius",
      "gmt_offset": "+02:00"
    },
    {
      "name": "Vladivostok",
      "gmt_offset": "+10:00"
    },
    {
      "name": "Volgograd",
      "gmt_offset": "+03:00"
    },
    {
      "name": "Warsaw",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Wellington",
      "gmt_offset": "+12:00"
    },
    {
      "name": "West Central Africa",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Yakutsk",
      "gmt_offset": "+09:00"
    },
    {
      "name": "Yerevan",
      "gmt_offset": "+04:00"
    },
    {
      "name": "Zagreb",
      "gmt_offset": "+01:00"
    },
    {
      "name": "Zurich",
      "gmt_offset": "+01:00"
    }
  ]
}

Users

Users resource

Getting myself

This method will return information on current user.

Endpoint

GET /api/v1/users/me

Request

Route

GET /api/v1/users/me

Headers

Authorization: Bearer aAb2qlDKQZsS4V1gPHT9.......
Content-Type: application/json

cURL

curl -g "hodlhodl.com/api/v1/users/me" -X GET \
	-H "Version: HTTP/1.0" \
	-H "Authorization: Bearer aAb2qlDKQZsS4V1gPHT9......." \
	-H "Content-Type: application/json"

Response

Simulated Response

Response Fields

Name Description
user.login

Login

user.avatar_url

Avatar URL

user.online_status

"online", "recently_online" or "offline"

user.rating

Rating (as fraction of 1)

user.trades_count

Number of conducted trades

user.url

Hodlhodl website URL

user.verified

Verified? (true or false)

user.verified_by

Login of the Strong Hodler who verified this user

user.strong_hodler

Strong Hodler? (true or false)

Strong Hodler is a member of Hodl Hodl volunteer team that we’re working directly with.

user.country

Country name (or "Global")

user.country_code

Country code (or "Global")

user.average_payment_time_minutes

Average payment time (in minutes)

user.average_release_time_minutes

Average release time (in minutes)

user.days_since_last_trade

Number of days since last trade

user.blocked_by

How many traders blocked this user

user.encrypted_seed

Encrypted seed

user.hide_sensitive_info_from_notifications

If enabled, e-mail and Telegram notifications will not contain sensitive information

Status

200

Headers

Content-Type: application/json; charset=utf-8

Body

{
  "status": "success",
  "user": {
    "login": "test_user",
    "avatar_url": "http://example.org/assets/default_avatar-f5b0258802df64cd87d94b95a1faed32b1b464bfb9b1cef2a10f6c30ddc91158.svg",
    "online_status": "offline",
    "rating": null,
    "my_review": null,
    "trades_count": 0,
    "url": "http://hodlhodl.com/accounts/test_user",
    "verified": false,
    "verified_by": null,
    "strong_hodler": false,
    "country": "Country 141",
    "country_code": "Country Code 141",
    "average_payment_time_minutes": null,
    "average_release_time_minutes": null,
    "days_since_last_trade": null,
    "blocked_by": 0,
    "encrypted_seed": "12345",
    "hide_sensitive_info_from_notifications": null
  }
}