AyrAs Bitmessage Services

This website gives a brief introduction to services provided by AyrA.


A Bitmessage based market system.
What you see is the readme.txt file below.
The application itself can be found on GitHub.
You can use this readme to build a client for the market system as it describes every command.

BitMarket Readme

This is the server readme for bitmarket It allows developers to set up their own servers and design BitMarket compatible market systems and plugins.

The Default BitMarket release and source contains:


BitMarket is a simple application, allowing you to sell or buy items over the internet securely and anonymously.

How does this system differs from other markets?

Confication proof design

Since users can only contact the sellers via their bitmessage address no actual communication gets stored on the server. In case the database gets Confiscated or even hacked, no useful data is stored on it, assuming buyers and sellers use addresses for "market only" purposes.

BitMarket can be run in a passive mode on a secondary server. It will receive and process all messages but will not generate any messages. In case the primary server is inaccessible, BitMarket can be switched over to active mode and continues to operate normally.

You can have infinite passive mode Markets running on different machines. They all must share the same Bitmessage address and the Database should be set up identically to avoid issues with text lengths.

Note: The Passive mode is not included in the official release/source. You need to code it yourself.

Getting started

BitMarket uses bitmessage as the underlying network infrastructute. Bitmessage is an open-source encrypted communication tool. You can download it from bitmessage.org. Compiled and signed Windows binaries can be obtained from here, if you prefer.

After the client has been started at least once, configure the API settings according to the Bitmessage wiki.

Open BitMarket.exe and configure the API settings you just set in Bitmessage.


BitMarket uses MySQL as default storage engine. To set it up, open the BitMarket.sql file and follow the directions in it.


BitMarket knows two types of plugins which are described below


The GenericServer is an interface which generates and receives messages. They also contain some public methods for removing and broadcasting messages.


A GenericProcessor processes messages generated by the GenericServer. They are loaded in alphabetical order. When a message gets created by a GenericServer, it is given to the first GenericProcessor. After processing, the GenericProcessor can either return a message object back or nothing. if a message object is returned, it is given to the next processor and so on. At the end of the chain, it is deleted.
A GenericProcessor should only return 'nothing' after processing, if the message must not be processed any further. This might become useful for anti-spam processors.

Using the Market

You can browse categories and get an overview of the offers in it. If you want to see an offer, you can download it from the market system. After downloading you can read its description, download attached files and contact the seller. Communication with the seller is made directly through Bitmessage itself and fully works, even without the market being online. We recommend using one individual address for each seller, this way he can recognize you as returning customer, but cannot track your interests.

Market Broadcasts

The Market broadcasts updates to its subscribers. These include: This keeps a client updated, if he comes online on a regular basis without the need to ask the server for updates.

*) Offers marked as "uncategorized" or "private" are not broadcasted.

Market Interface

The market interface allows you to write your own websites and applications to work with the market. You can fully automate your processes with it.

General message format:

The message subject contains the command you wish to execute. It is rather short and should be uppercase. Character casing is ignored server side, but uppercase is recommended so users can manually distinguish better between messages in Bitmessage itself. The message body contains payload data (if any) for the command. Payload data is in a 'Name=Value' format for commands that operate on a single item. A Name-Value pair cannot span multiple lines. The "Name" part is case insensitive. Commands for multiple items (especially lists) use a simpler format described for each individual command below. Some commands may also return unspecified "free-form" data. If only one value is returned, it is usually returned as is without a Name-Value format.
If multiple values are specified on a single line, a tab char is usually used to separate them.
Date and Time values are expressed using the Base.DT_FORMAT constant, which is yyyy-MM-dd hh:mm:ss


Below is a list of commands.
Commands are used as the message subject.


Returns a message with some basic Infromations about the Market. The Text format is free to choose for the Market owner


Returns a message with settings for text fields in the Market. This message might return fields, that cannot be edited by the user. The values do not only tell you how you have to send values, it also tells how values are sent back. Missing values should be assumed to be in RAW format. The settings tell you how a Name-Value pair must be formatted (Maximum Length and format). -1 indicates 'no maximum length'. The Length has to be calculated from the raw data and is in bytes, not in chars.
RAW indicates to send the text as-is
A85 indicates Ascii85 encoding
B64 indicates Base64 encoding

General format of a line:


Returns two name-value pairs with each containing a list of transaction IDs you have generated or received.

Sold=23	56	2	16	7	12	19
Bought=1	2	3	4


Returns a list of categories, one category per line. A line contains the category ID, its parent ID (or -1, if no parent), and its name

1	-1	Technology
2	1	Computers
4	-1	Books
3	1	Mobile phones
12	1	Consoles
8	4	Comics
18	4	Novels
33	8	Physical
34	8	Digital
35	18	Physical
36	18	Digital
The tree would look as folows:


Returns a list of all offers. The list incudes (in this exact order): Offer ID, offer category, stock, price map, offer title

1	12	1	$|1-:50	Used N64 for sale
5	8	3	$|3:1100	Action Comics #1


Returns Details for the given offer ID as Name-Value pairs. Values in the body are as folowing:

The Title of the offer.

A more or less detailed description of the offer

Bitmessage address of the owner. Used to contact him.
Only this Address can modify the offer.

ID of the category the offer is in

Special Values:
-1 Uncategorized
This offer is only listed if you call the MAIN OFFERLIST command.

-2 Uncategorized and unlisted
This offer is not listed in any way, you have to know its ID

ID of attached files. Seperated with commas.
Sellers are free to attach file IDs which they do not own, this can make sense if they partner with another seller and if they share files to save them POW time.

Returns two values seperated with a tab.

First Number:
Number of items to be sold. This can be -1 to indicate an infinite stock. Infinite stocks may be useful if you really can provide infinite items or if it is for virtual goods or for work.

Second Number
Number of items in stock considering unconfirmed transactions. Until a transaction is confirmed, the stock value stays unchanged. The second number tells you, how many are left, if all unconfirmed transactions would be confirmed. Therefore this number can go below zero.

This is the Price map.
The price map provides advanced configurations for prices, so you can create discounts for large quantities, or you can define a step value of 5, so an item can only be bought 5 at once (5,10,15,20,etc) If you do not set this at all, the offer is "per request only" so users are forced to contact you and negotiate about the price and quantity.

Format is:

Description of the parts:
A list of currencies you accept in the order you like them most. For example: USD:CHF:BTC
This is always the first item in the PriceMap and can only be used once. You can feeely choose if you use the 3 letter code, the full name or the currency symbol and you can mix them together. To show you with the same exaple as used above: $:CHF:Bitcoin
This defines the range of items.
While the shop does not really cares what you enter here as long as it is mathematically valid you should not create a Price Map with overlapping quantities. A common isssue is a map from 1-10 and one from 10-20, so "10" is actually used twice. In this case the client will always show the first match only.
You can define 1,2 or 3 values:
Note to coders: A simple validation rule in C would be:
Step > 0 && Max >= Min && Min > 0 && (Max - Min) % Step == 0
This is simple. It's the price per piece. You must have as many values as you have currencies and you also must have them in the same order.
The price is always for a single item, so if the Pricemap is "USD|5:1:8|10" and the user buys 7 items, he pays 7*10=70 USD. If you have additional costs (shipment and packaging fees for example) put them in the description and not the PriceMap.

The simplest PriceMap. You sell any quantity at the price of 0.5 BTC per piece

This example sells an item in 3 currencies and offers a discount, if 10 or more are bought at once.
1-9 items: you pay 1.20 USD or 1.15 CHF or 0.0012 BTC per piece
10 or more items: you pay 1 USD or 0.95 CHF or 0.001 BTC per piece

The user can buy 10,30 or 50 items for 5 USD per single item

Similar example as above, but it would be rejected by BitMarket, because 60 items cannot be reached with the given Range

This is the Date and Time, when the offer was last modified.
Offers disappear after 30 days so if you want to keep it active longer, occasionally execute the SET command.


Use this command to create new offers and and modify your existing offers. Supply the Name-Value Pairs you want to define below. Read carefully for each pair if it is optional and what happens if ommited. Set the ID in the command to -1 to create a new offer.

Returns a Broadcast message with the offer ID in it as response. Sends a private message with the ID in it if the offer is hidden.

If you supply invalid arguments you additionally also receive error messages. You should check your invalid values and submit the command again, as your offer is now partially edited.
Ommitting a Name-Value Pair or only sending the "Name=" part is not the same.
Ommitting usually leaves the value unchanged, while supplying the Name-Part clears the value (since you set it to nothing). This is not valid for everything, for example the title or the Category.
Editing an offer resets its expiration time. An offer is removed after being unchanged for 30 days.
When editing an offer all fields are optional.
You can basically submit an empty SET message if you want to keep your offer active for another 30 days without changing anything.

This is required for creating an offer and optional for editing.
When not supplied, the current value is kept. Must not be empty

This is optional. When not supplied, the current value is kept for editing and an empty value is set for creating.

This is optional. When not supplied, the current value is kept for editing and -1 is set for creating. Must not be empty
Special values:
This is optional. When not supplied, the current value is kept for editing and an empty value is set for creating.

This is optional. When not supplied, the current value is kept for editing and 0 (out of stock) is set for creating.
When setting this value, consider the PriceMap, if you have a map that allows users to buy in steps of 5 you should always have multiples of 5 in stock.
Must not be empty
Special values:
PriceMap This is optional. When not supplied, the current value is kept for editing and an empty value is set for creating.


This just removes an offer.
You can only use this command from the address, that created the offer. Returns a Broadcast message with the offer ID in it as response. Sends a private message with the ID in it if the offer is hidden.
Removing an offer does not removes or disables open transactions.


(buyer side)

Buys the item with the specified ID.
When you buy the item with this command you will receive a message with a transaction ID in it and nothing more.
When you buy an item you can send a message to the seller at the same time. If the seller requires you to send some informations in the offers desctiption you can do so here. This will speed up the negotiation process. You can still contact the seller in bitmessage manually if you prefer.
The body of your command message must contain name-value pairs (at least the Amount pair):

Required, the number of items you want to buy. This must match the PriceMap or your offer is rejected on the server.

Optional, Bitmessage requires time to send messages, so two people can buy the last few items at the same time and one of them wins.
This must match the PriceMap or your offer is rejected on the server.
You can specify a number between 1 and the Amount of items you bought.

Assuming only 6 items are left, because somebody bought 4 just before you could buy all 10. What happens now depends on the understock value. If it is 6 or less, you will buy that many, because 6 are left.
If it is 7 or more, you will buy none and receive an error message.
If you do not specify this value it is internally set to the amount you want to buy.

optional, a message you want to send to the seller. This can be anything.
Read the offer description carefully, sometimes the seller requires informations, for example shipping address or color of the item.
The Message will not be stored on the server.


(seller side)

You cannot buy your own items (seller and buyer address must differ), but as the seller you receive part of the result of this command.
When somebody buys an item from you, you automatically receive a message with the command as subject. Since you cannot buy your own items you can determine from the ID, if you are the seller or buyer of an item.
The body contains Name-Value Pairs:

This is the transaction ID, not the offer ID. The offer ID is specified in the command (subject). You need the transaction ID to approve, reject, comment and rate the transaction.

This is the bitmessage address of the user

Two values seperated with a comma. First value is what the user wanted, the second value is what he got (considering your stock count). If he got less than what he wanted you definitely want to check how fast you can restock. Some users are willing to wait a few days.
Since your stock count stays the way it is until you approve the transaction, you should either approve (or reject) them quickly or have a high stock value.
Only the first value is saved in the transaction!

This is the Understock value the user specified. In case your stock count count was too high you can try to convince the user to reduce his amount a little. This value will most likely be the minimum amount he is willing to still buy from you.
This value is not saved with the transaction!

The message, the user entered during the transaction.
This field might be missing or empty if the user did not write anything.
This value is not saved with the transaction!


Returns the specific File as Name Value Pair to the sender

File Name

File contents


Saves or modifies a file.
A file can only be modified by its owner address.

This is required for creating a file and optional for editing.
When not supplied, the current value is kept.
Must not be empty.
Doesn't needs to be a valid file name but at least should end with a proper file extension (.jpg .png, etc) so the client can properly display it.

This is required for creating a file and optional for editing.
When not supplied, the current value is kept.
Must not be empty


Deletes a file from the market.
This will not remove file references from offers.
Can only be executed by the address who owns the file.


Can only be executed by buyer (user who created the transaction) and seller (owner of the offer).
Returns Name-Value pairs of the transaction to view its details.

The address which generated the transaction. (Buyer of items)

The address of the Offer owner. (Seller of items).
The reson this is specified is because the offer may be deleted already.

Number of items bought

ID of the offer

The state the transaction is in.
Possible Values:
The comment, the buyer left. This should describe the reason for the given rating

SellerComment The comment, the seller left. This should describe the reason for the given rating

BuyerRating Rating, the buyer left. (0-5). 0 indicates 'unrated'

SellerRating Rating, the seller left. (0-5). 0 indicates 'unrated'

TransactionTime The time the transaction was generated.
Buyer and seller should try to complete a transaction within 60 days.
After 60 days it is expired and cannot be changed anymore.


Can be initiated by buyer and seller and has different meanings, depending on who confirms.
Both parties receive the full transaction spec (as if the sender issued the GET command) if something changes.
You cannot confirm an expired transaction.

The seller should confirm the transaction if he is willing to process it. He should only do so if he guarantees, that he processes the offer, in other words after negotiation with the buyer is complete and everything is set up.
This will adjust the stock count of the item in question.
If the amount has changed during negotiation you need to manually edit your offer and adjust the stock count manually.
The seller can only confirm in state 0.

The buyer should confirm the offer, after he received the item.
He can only confirm in state 1 (cannot confirm before the seller did).
Confirmation just indicates, that the buyer received the item and not that he is happy with it.


Can be initiated by buyer and seller as long, as the transaction State is not 3 or higher.
Rejecting a transaction should be done with caution. Rejecting ultimatively prevents a transaction from being successful and is irreversible.
A transaction should only be rejected after negotiation with each other. You cannot reject an expired transaction.
There are different reasons for rejecting, including the buyer not paying or the seller not being able to deliver the quantity requested.
Rejecting will change the State of the transaction but it will not affect the stock count. If the seller has already confirmed he needs to manually adjust the stock count. Rejecting a transaction also removes comments and ratings from it.
The reason for this is, because you cannot change a comment in a negative transaction state.
This allows both parties to set a comment again just once.
If one party rejects, the other should not automatically reject if he was still willing to complete it (you can still rate and comment it before expiration). If the transaction expires it tells who has rejected when users ask for rating. If only the buyer rejects, users know, that the seller was willing to fulfill the transaction but the buyer did not.
Since the Market is fully anonymous (and also trustless) it makes it easier for users to understand the comments if the proper transaction state is maintained.


Adds or changes a comment and a rating in a transaction.
You cannot comment on expired transactions.
You cannot comment in state 3 or higher.
You cannot comment on transactions in negative state (<0) if a comment or rating is already present.
Before leaving negative feedback, try to resolve the issue with the seller. And always double check in your Bitmessage client, if the message was delivered and is not waiting for ACK.
Supply two Name-Value pairs in the body of the message:

A whole number from 0-5.
1-2 is considered negative feedback, 3 is neutral, 4-5 is positive feedback.
0 means unrated. In some cases you might want to give a text comment but not a Number rating.
This is not very nice and may affect your own rating if a client sees this.

This should be a textual representation of the Rating value.

RATING <Address> GET

Returns a list of ratings the specified address has received. Ratings are important but in a completely anonymous system you might not trust them too much.
The command returns a simple list of comments:
Transaction state,Address,Rating,Comment

Example (last value is cut short to fit into this site):
3	BM-Bc7Rspa4zxAPy9PK26vmcyoovftipStp	4	VmVyeSBmYXN0IGRlbGl[...]

This is a comment from a completed transaction.
The author is BM-Bc7Rspa4zxAPy9PK26vmcyoovftipStp
The Rating the address in question received is 4
The message is "Very fast delivery, did not had everything in stock"

The reason the comment is in Base64 is because the SETTINGS command defined it as such.
You always receive text values the way you have to send them.

Error Messages

Whenever something goes wrong, you receive at least one error message.
Error messages have "ERROR" as the subject and a human readable message as body.