Magic Smoke Protocol Documentation

logo
The Magic Smoke Protocol is used between the Magic Smoke Server and Client. It is based on HTTP and XML. Only POST requests are allowed. All body data is presumed to be in UTF-8 encoding, headers are restricted to ASCII-127.

Each request must have a "x-magicsmoke-request=..." header. The actual request data is sent as POST-data. Except for the serverinfo and startsession requests all requests must also carry a "x-magicsmoke-session" header.

HTTP Headers

Part of the data is transmitted in headers. This section lists all possible headers used by Magic Smoke.

Client Request Headers

x-magicsmoke-requestThe request that is to be executed by the server. This header is mandatory for all requests.
x-magicsmoke-sessionThe session ID of this connection. This header is mandatory for all requests except serverinfo and startsession.

Server Response Headers

x-magicsmoke-statusThe status of the request execution. See table below for details

Possible status codes are:
(missing)If the whole header is missing or contains an unknown value, this should be treated as if it contained "Error" (see below).
OkThe request went ok and the actual data comes as response body.
ErrorSome unspecified error occured. The response body might contain some detailed human readable information.
NonPostThe HTTP method was not POST. The body is a simple HTML page explaining to the user that browsers are not meant to use this page.
UnauthenticatedThe session ID does not exist, authentication failed or the session expired.
NotAllowedThe user does not have the right to execute this transaction.
InvalidRequestThe request was not understood. There was probably a mismatch in client and server version.
SyntaxErrorThere was a syntactical error in the request data. Some details might follow in the response body.

Server Info

A serverinfo-request can be sent by any client in order to get basic information about the server.

The server replies with an XML document that contains the most important information:

<Info>
 <ServerVersion proto="protocol-version">server-version-number</ServerVersion>
 <AuthAlgorithm>hash-algo</AuthAlgorithm>
</Info>
The proto argument of the ServerVersion tag returns the protocol version, which is used by the client to check whether it is compatible with the server. It consists of two blocks of four hex-digits each, separated by a space. The first block is the lowest protocol version understood by the server, while the second block contains the current protocol version implemented by the server.

The server version number in the ServerVersion tags text is a the software version itself. The hash-algorithm values are described below in the authentication protocol section.

The protocol version described in this document is 0000.

Authentication protocol

First the client requests the hash-algorithm from the server. Possible algorithms are:
md5, sha1, sha256use the hash algorithm directly, the returned value is calculated by first concatenating challenge and password/hostkey and then hashing it
hmac-*use the same algorithm in HMAC mode with the challenge as data and the password/hostkey as key

Step 1: Start a Session

The authentication handshake is started with the client asking for a new session using a startsession-request. The post data of this request should consist of at least 128 random bits (base64 or another ASCII encoding) which are used by the server to calculate a session ID. The server responds with a session object:
<SessionStart>
 <ID>session-id-string</ID>
 <HostChallenge>host-challenge-string</HostChallenge>
 <UserChallenge>user-challenge-string</UserChallenge>
 <Timeout>seconds-till-session-timeout</Timeout>
</SessionStart>
The challenge strings are derived from some internal function and the clock. By no means they are meant to be secure against all kinds of attack. The challenge-response-protocol is only supposed to avoid sending the passwords in plain text over the wire.

The timeout of the temporary session is usually 5 minutes (300s).

Step 2: Authenticating the Session

This is done using a sessionauth request. The session ID header must be set.

The client sends its authentication data as XML:

<SessionAuth>
 <HostName>host-name</HostName>
 <HostAuth>host-authentication-data</HostAuth>
 <UserName>user-name</UserName>
 <UserAuth>user-authentication-data</UserAuth>
</SessionAuth>
The authentication data is calculated using the hash-function mandated by the server. The HostAuth item is calculated using the HostChallenge and the hosts key. The UserAuth item is calculated using the UserChallenge and the users password. Both *Auth values are hexadecimal-encoded.

The status is "Ok" or "Unauthenticated" - in the latter case the session ID is deleted and the client needs to start with a startsession request again if it wants to retry. If the request succeeds, the result body contains two numeric items (separated by a newline) that state the new session timeout and the current time as a Unix timestamp (seconds sice epoch - 1Jan1970, 00:00 UTC).

A result of "Unauthenticated" can have multiple reasons: the timeout of the temporary session expired before the request was received, the authentication of the user failed, the user is not allowed to connect from this or an anonymous host, or the authentication of the host failed and the user is not allowed to connect from an anonymous host.

Step n: Closing the Session

This is done with a sessionclose request. Neither request nor response contain a body.

This request always yields an "Ok" status response regardless of whether the session ID was still valid or not.

Note on Usernames and Roles

Both, user names and roles, are restricted to letters, digits and "_". Leading and trailing whitespace is ignored (trimmed).

Each role corresponds to a function that can be called and executed remotely through the machine interface. Roles beginning with "_" are reserved keywords that can alter the behaviour of other roles and must not be used to name functions.

Basic Requests

Getting ACL info

The getmyroles transaction requests all roles from the server. A role is a transaction that needs permission to be executed (ie. all transactions except serverinfo, startsession, sessionauth, closesession, and getmyroles) or a special right. The response is a list of roles with one role per line.

Special rights are:
_adminThe user is an administrator and can automatically execute everything.

Event Related Requests

Getting a List of Events

The geteventlist transaction requests all events from the server. The response is a simple XML structure that contains only very basic data for each event:

<EventList>
  <Event id="0" start="1190543432" sold="11" capacity="20" reserved="2">blechsalat</Event>
  <Event id="1" start="1191419769" sold="11" capacity="20" reserved="2">stringsalat</Event>
</EventList>
Each event is encapsulated in an Event tag. The events have no specific order. The id attribute contains the internal ID of the event that can be used to reference it in other requests. The start attribute contains the start time of the event as Unix timestamp. The text of the Event tag contains the title of the event.

There are 3 optional attributes: capacity contains the maximum number of seats for this event, sold the number of tickets that have been sold and reserved the number of tickets that have been reserved.

Getting Detailed Event Data

The geteventdata transaction returns detailed data about the event. The request body contains a space separated list of event IDs. The response looks like:

<EventData>
  <Event id="0" start="1190543432" end="1190543532" capacity="25" defaultprice="1177" cancelled="false">
    <Title>blechsalat</Title>
    <Artist>Broken Blech</Artist>
    <Description>a lot of text containing encoded &lt;b&gt;HTML&lt;/b&gt; tags</Description>
    <Room>Invisible Library</Room>
    <CancelReason>a damned good one</CancelReason>
  </Event>
  <Event id="1" start="1191419769" ...>
  ...
  </Event>
</EventData>
Attributes and tags:
idthe ID of the event
startthe start time as Unix timestamp
endthe end time as Unix timestamp
capacityhow many tickets may be sold for this event
defaultpricethe default price for tickets as integer in cent (or penny or ...)
cancelledoptional: "true" or "false" -- shows whether the event is cancelled, default is "false"
Titlethe title of the event
Artistthe artist appearing
Descriptiona description for the web page, may contain HTML
Roomthe room it is happening in (the room must exist in the list of available rooms)
CancelReasonoptional: if the event is cancelled, the reason for it (human readable)
If one of the requested events does not exist, it simply does not generate an Event block. It is permissible for the server to send an empty EventData tag if no data is available for the request.

Changing/Creating an Event

The seteventdata transaction creates/changes an event. The request data looks like:

<Event id="0" ....>
  <Title>....
</Event>
Attributes and tags are the same as for the geteventdata response. Except that the id attribute may contain the value "new" to create a new event, a negative integer is not allowed.

The response contains the ID of the new/changed event if the status is "Ok". In the case of failure the status will be "Error" and an optional reason for the failure may be in the body.

The request must not change the cancellation status of an event - the attribute "cancelled" is ignored and the element "CancelReason" may be ignored if it violates the current status.

Getting a Ticket Summary of an Event

The eventsummary transaction returns summary data for an event. The request contains the ID of the event. The response contains:

<EventSummary event="eventID" reserved="numbeOfCurrentlyReservedTickets"
    cancelled="numberOfCurrentlyCancelledTickets"
    totaltickets="numberOfUsableTickets" totalmoney="totalIncomeOfEventInCent" >
  <Tickets price="priceCategoryInCent" bought="numberOfUsableTicketsInThisCategory"
      used="numberOfUsedTickets" unused="numberOfUnusedTickets" />
  <Comment customerid="customerID" customer="customers Name" orderid="orderID">comment</Comment>
  <Orders>space separated IDs of all orders for this event</Orders>
</EventSummary>

Cancelling an Event

The cancelevent transaction can be used to cancel an event. This transaction is not reversible. The request contains the event-ID and the cancel reason separated by a newline, the response is empty.

Room related Transactions

Getting Rooms

The getroomdata transaction returns data about rooms in the database. The request data looks like this:

<GetRooms detail="basic">
  <Room>ID of room</Room>
  ...
</GetRooms>
The detail attribute may be "basic" or "full". If no <Room> tags are present all rooms are returned.

The response data looks like:

<RoomData>
  <Room capacity="24">
    <ID>Room ID</ID>
    <Description>some encoded HTML text that describes the room</Description>
  </Room>
  ...
</RoomData>
The capacity attribute tells how many persons fit into the room. The ID tag contains the ID or Name of the room, the optional Description tag contains a description of the room - it is only present if full detail has been requested.

Setting Rooms

The setroomdata transaction is used to create/change one or more rooms, the request data looks like:

<RoomData>
  <Room capacity="24">
    <ID>Room ID</ID>
    <Description>some encoded HTML text that describes the room</Description>
  </Room>
  ...
</RoomData>
The response simply contains the status "Ok" or "Error".

ACL related Transactions

Getting User Info

The getusers transaction returns the names and descriptions of all users in the system. The request is empty, the response looks like:

<Users>
  <User name="loginname">Description of User</User>
  ...
</Users>

Adding Users and Setting New Descriptions

The setuserdescription call can be used to set new descriptions for existing users. The call may silently fail for any user that does not exist, hence the client should request user data from the server to confirm whether the call succeeded.

The adduser call can be used to create new user accounts. Initially the new user will have no ACL and no host settings.

Both calls use this structure for the request:

<Users>
  <User name="loginname" passwd="initial password">Description of User</User>
  ...
</Users>
The passwd attribute is optional.

The adduser call also uses it for the response, leaving out any user name that already existed or does not conform to the syntax requirements.

Deleting a User

The deleteuser transaction deletes one single user. The request contains the user name to be deleted on the first line and optionally a user to assign database object to that are currently owned by the user to be deleted (eg. orders). If no second user is referenced those objects are un-assigned.

The response is empty or optionally contains an error message.

Changing a Users own Password

The setmypasswd can be used to change the user of the current session. The request looks like:

<SetMyPasswd oldpwd="old password" newpwd="new password"\>
The response is empty. Only the status counts.

Changing another Users Password

The setpasswd can be used to change the user of the current session. The request looks like:

<SetPasswd user="user name" newpwd="new password"\>
The response is empty. Only the status counts.

Getting User ACLs

The getuseracl transaction returns the ACL of a specific user. The request contains only the login name of the user. The response looks like:

<ACL user="username">
  <Role name="rolename" set="1|0"/>
  ...
</ACL>
All setable roles must be listed, so that the client can use these for displaying in a dialog.

Setting User ACLs

The setuseracl transaction can be used to update a users ACL. The request is identical to the response of getuseracl, while the response is an empty document on success - only the status "OK" counts.

Any role listed in the request is changed accordingly, non-existant roles are ignored, roles not listed are left unchanged.

Getting a Users Hosts

The getuserhosts transaction returns the allowed client hosts of a specific user. The request contains only the login name of the user. The response looks like:

<Hosts user="username">
  <Host name="hostname" set="1|0"/>
  ...
</Hosts>
All setable hosts must be listed, so that the client can use these for displaying in a dialog.

Setting User Hosts

The setuserhosts transaction can be used to update a users allowed client hosts. The request is identical to the response of getuserhosts, while the response is an empty document on success - only the status "OK" counts.

Any host listed in the request is changed accordingly, non-existant hosts are ignored, hosts not listed are left unchanged.

Creating and Changing Hosts

The addhost transaction creates new hosts. The sethost transaction changes the key of existing hosts. For both the request looks like:

<Hosts>
  <Host name="hostname">hostkey</Host>
  ...
</Hosts>
FIXME: currently these transactions do not return any feedback about success. The sethost transaction silently ignores hosts that do not exist.

Getting All Hosts

The gethosts transaction returns the name and key of all hosts. There is no request body. The response looks like the request above.

Deleting Hosts

The deletehost transaction deletes one single host. The request contains only the name of the host as ASCII text.

FIXME: special hosts (beginning with "_") return errors. Non-existing hosts are silently ignored.

Customers

Getting List of Customers

The getcustomerlist transaction returns a short list of customers. The request is empty. The response returns this:
<CustomerList>
  <Customer id="integer ID" name="full name"/>
  ...
</CustomerList>

Customer Details

The getcustomer transaction returns detailed information about a customer. The request contains the ID of the customer, the response contains:

<Customer id="integer ID" name="full name" mail="login-mail-for-webinterface">
  <Address> address info</Address>
  <Contact> contact information</Contact>
  <Comment> system internal comment</Comment>
</Customer>
The "mail" attribute is optional - it is only reported for customers that have a web-interface account.

Setting Customer Details

The setcustomer transaction is used to set details of the customer. The request contains a customer XML object as listed above, but without the mail attribute. The response contains the ID of the customer.

Deleting and Merging Customers

The deletecustomer transaction can be used to attempt to delete a customer from the database. It will fail if this customer still has any data (eg. orders) stored in the database. The request contains the ID of the customer to be deleted. The request may optionally contain a second customer ID separated from the first with a single space - if it does, the first customer is merged into the second one. The response is empty.

If customers are merged, the following rules are executed:

Orders and Sales

The order XML representation looks as follows:
<Order id="orderid" customer="customerid" seller="sellerid" ordertime="timestamp" senttime="timestamp"
    totalprice="amountInCent" paid="amountInCent" status="orderstate">
  <Ticket event="eventid" id="ticketid" price="priceInCent" status="ticketstate" />
  <Voucher id="voucherid" price="priceInCent" value="remainingValueInCent" used="0|1" status=""/>
  <Shipping price="priceInCent" type="shippingtypeID">Shipping Comment</Shipping>
  <DeliveryAddress>deliver address</DeliveryAddress>
  <Comment>comment...</Comment>
</Order>
ItemDescriptionOccurrence
OrderContainer for one single order or sale1
  idID of the order, if already known.0-1
  customerID of the customer. Mandatory.1
  sellerLogin of the seller. Automatically filled in.0-1
  ordertimeTime of the order. Automatically filled in.0-1
  senttimeTime at which the order was shipped. Automatically filled in.0-1
  totalpriceTotal accumulated price of the order. Automatically filled in.0-1
  paidAmount that has already been paid. Automatically filled in.0-1
  statusCurrent status of the order. Automatically filled in. See table below.0-1
Ticket(*)data about a single ticket bought in this order0-unlimited
  idID of the ticket1
  eventID of the event this ticket refers to.1
  pricePrice of the ticket1
  statusStatus of the ticket (see below)1
Voucher(*)data about a single voucher bought in this order, vouchers that are used to pay for an order are not stored0-unlimited
  idID of the voucher1
  pricePrice of the voucher (adds to price of the order)1
  valueValue (in cent) of the voucher (does not add to the order, but refers to how much the voucher is worth)1
  statusonly in validation responses: result of the validation0-1
  usedFlag whether the voucher has been used to pay for anything (assumed as 0 if not present)0-1
Shippinginformation about the kind of shipping used and how much it costs; if text is used it is a copy of the text from the shipping table information - it cannot be changed here0-1
  pricePrice of the shipping option1
  typeshipping type ID1
DeliveryAddressthe address to send the stuff to, if not present or empty the address of the customer is used0-1
Commentcomment entered into the order by customer or seller0-1
(*)At least one of Ticket or Voucher must be used.

If items that are not expected are filled in in a message, they will be ignored.

Order status:
StatusDescription
placedThe order has been placed, nothing has been sent or paid yet.
sentThe order has been shipped.
reservedThe order has been reserved. This means the tickets are blocked, but it cannot be paid or shipped.
cancelledThe user cancelled an unshipped and unpaid order.
closedThe order is final and cannot be altered. (State maybe not needed.)

Ticket status:
StatusDescription
bought(1)The ticket is valid; whether it is paid for depends on the order status.
refund(2)The ticket has been or needs to be refunded; eg. after the event or order was cancelled.
used(1)The ticket has been used.
reservedThe ticket is reserved. This state is currently not used.
(1)bought and used tickets add to the total price of an order; only bought tickets can be used
(2)refunded tickets add nothing to the total price of an order, this may make the paid amount higher than the amount due.

Checking or Creating Orders/Sales

The createorder transaction creates an open order. The initial state of the order is "placed".
The createreservedorder transaction creates a reservation. The order looks like a normal order, but it is in the "reserved" state in which it cannot be paid or shipped - it has to be converted first
The createsale transaction creates an order that is marked as delivered and paid. The initial state of the created order is "sent" and the amount paid is equal to the total price.
The checkorder transaction performs all checks and lookups of an order, but does not commit it to the database.

The create* transactions fail with an error if a ticket cannot be reserved or if a voucher value is invalid. The checkorder transaction uses special state values to signify failure. It sets the price of a voucher to the nearest legal voucher value if the value is not allowed.

The request is an order object without most fields filled in, the response is a copy of that object with all relevant fields filled in:
ElementAttributes in RequestAttributes in Response
Ordercustomerid(1), customer, seller(3), ordertime(1,4), totalprice(5), paid(1), status(6), senttime(2,4)
Ticketevent, price(7)event, id(1), price, status(6)
Vouchervalue, price(7)value, price, id(1), status(11)
Shippingtype(8), price(9)type(10), price, [text](10)
DeliveryAddress[text][text]
Comment[text][text]
(1)field is optional for checks and has no meaning there, it is recommended the server returns a dummy ID for checks
(2)the field only exists for sales
(3)the seller is automatically taken to be the session user
(4)time stamps are automatically filled in with the current server time
(5)the total price is the accumulated price of all tickets and vouchers in the order
(6)the status fields have special meanings for checks, see below
(7)the price field will only be honoured in the request, if the user also has the privilege to use the changeticketprice transaction
(8)the shipping types that are allowed depend on whether the user has the _anyshipping privilege
(9)price is optional, if set it is ignored if the user does not have the _repriceshipping privilege
(10)the type in the response may be -1 if an error occurred in this case the text contains the error message, otherwise it contains a copy of the shipping option text
(11)in validation responses if the voucher contains a non-empty state it is not deemed valid by the server, the state must be one of the status constants below

Order status for checks:
StateDescription
ok(1)the order can be executed as is
saleonly(2)the order can only be continued as a sale, not as an open order
orderonly(2)the order can only be continued as an open order, not as a sale; this state also shows that there is a problem with the configuration
failthe order contains failed items
(1)Attention: the return code "ok" means the order would have succeeded at the time of the check, it may still fail when it is actually placed
(2)these states are equivalent to ok if the intended transaction matches and to fail if it does not match

Ticket status for checks:
StateDescription
ok(1)the order can be executed as is
saleonly(2)the order can only be continued as a sale, not as an open order
orderonly(2)the order can only be continued as an open order, not as a sale; this state also shows that there is a problem with the configuration
toolatethe order is not possible any more
exhaustedthere are no more tickets for this event
cancelledthe event has been cancelled, no order is possible
invalidthe event does not exist in the database
(1)Attention: the return code "ok" means the order would have succeeded at the time of the check, it may still fail when it is actually placed
(2)if two or more tickets contradict on this state the order is returned as failed

Voucher status for checks:
StateDescription
[empty]the order can be executed as is
invalidvaluethe user is not allowed to use this value for the voucher
invalidpricefor this user the price must equal the value (or be ommitted)

Getting an Overview List of Orders

The getorderlist transaction can be used to get a list of all currently stored orders. The request does not contain any data, the response looks like:

<OrderList>
  <Order id="orderid" customer="customerid" status="orderstatus"
       totalprice="amountDueInCent" paid="amountPaidInCent"/>
  ...
</OrderList>
(this is a small subset of the full order object)

Paying/Refunding Orders

The orderpay transaction is used to add to the amount paid in an order. The orderrefund transaction is used to subtract from the amount paid of an order. In both cases the request consists of two positive numbers separated by a space: the order-ID and the amount in cent. The response contains the new amount paid after the transaction in the case of success and status error plus an explanation in case of any problem.

Set Shipping State of an Order

The ordershipped transaction is used to mark an order as shipped. This transaction is only legal for orders in the "placed" state. The request contains the order ID, the response contains the new shipping time (set automatically during transaction).

Cancelling an Order

The cancelorder transaction is used to mark an order as cancelled. It also marks all tickets inside the order as cancelled and voids any vouchers in it. This transaction is only legal for orders in the "placed" state. It will fail if any tickets or vouchers have already been used.

Converting Reservations

The reservationtoorder transaction marks a reservation as a normal order. From that time on it can be paid and shipped.
The reservationtosale transaction marks a reservation as a sale. It will be marked as paid and shipped.

The request contains the order ID, the response is empty or contains an error message.

Use the cancelorder transaction (see above) to cancel a reservation.

Searching for an Order

The orderbyticket transaction can be used to find an order by a ticket ID from that order. The request contains the ticket ID, the response contains the order ID or returns as error if not found.

The getordersbyevents transaction can be used to return all orders that contain tickets for a specific event. The request is a space separated list of event IDs, the response has the format of the getorderlist response.

Changing the Comment of an Order

The setordercomment transaction is used to change the orders comment. The request is a simple XML document:

<OrderComment orderid="id">comment text...</OrderComment>
The response body is empty or optionally contains an error message.

Changing the shipping option on an order

The orderchangeshipping transaction can be used to change the shipping information on an order. The request looks like:
<OrderChangeShipping orderid="orderId" type="newShippingType" price="newPriceInCent"/>
If type is not present, the price is taken from the new shipping type. If type is not present, it is not changed. If type is empty it is reset to none (NULL) in the Database. If a price other than 0 is used, the type in the database must be present (!= NULL).

The response contains the updated order object or just an error message.

Creating/Changing/Deleting Shipping Options

The setshipping creates or changes a shipping option. The request looks like:
<ShippingOption type="shippingOptionID" price="priceInCent" web="0|1" anyUser="0|1">
  Text that describes the option
</ShippingOption>
If the type attribute is missing the server creates a new option. Otherwise it changes an existing one. The web attribute tells whether the option is available to customers using the web interface. The anyUser attribute tells whether the option can be used by anyone who can create an order/sale (=1) or only by users with the "_anyshipping" privilege (=0).

The response contains the new shipping option id or contains an error message.

The deleteshipping transaction can be used to delete a shipping option. The request contains just the ID of the option, the response is empty.

Listing Shipping Options

The getshipping transaction can be used to return all shipping options. If the user has the "setshipping" or "_anyshipping" privilege the list will also contain privileged options. The request is empty. The response looks like:
<ShippingList>
  <ShippingOption type="shippingOptionID" price="priceInCent" web="0|1" anyUser="0|1">
    Text that describes the option
  </ShippingOption>
  ...
  ...
</ShippingList>

Adding Tickets or Vouchers to an Order

tbd.

Tickets

Getting Tickets

The getticket transaction can be used to get information about a ticket. The request contains only the ticketID, the response looks like:

<Ticket id="ticketid" status="ticketstate" order="orderid" event="eventid" price="priceincent" orderpaystate="status of the order" />
The attribute orderid may be <0 if the ticket is not attached to an order.

AttributeDescription
statuscan be any of reserved, bought, used, refund, error (see getorder above for details)
orderpaystatethe payment status of the order, it can be "none" if the order is invalid or the ticket is not attached to one, "ok" if the order has been paid correctly, "cancelled" if the order was cancelled, "needpayment" if the order is not fully paid yet, or "needrefund" if too much has been paid

Using Tickets

The useticket transaction marks a ticket as used. The request contains only the ticket ID, the response has status ok and no body if the action succeeded, it has status error and an explanatory text if it failed.

Only tickets that have status "bought" and whose order have payment status "ok" or "needrefund" can be used. The transaction fails for all other tickets.

Changing Ticket Prices

The changeticketprice transaction can be used to change the price of a ticket. The request contains the ticket-ID and the new price in cent separated by a newline. The response is empty.

Returning Tickets

The ticketreturn transaction can be used to return a ticket that has not been used yet. The request contains the ticket-ID, the response is empty.

Vouchers

Rules for vouchers:

Getting Valid Voucher Prices

The getvoucherprices transaction can be used to retrieve allowed voucher prices. The request is empty. The response contains the allowed prices in cents, separated by spaces - it is empty if no voucher prices are configured.

Using a Voucher

The usevoucher transaction can be used to use a voucher for payment. The request contains the voucher-ID on the first line and the order to be paid on the second line.

On success the response contains the amount that remains on the voucher on the first line and the now current amount that has been paid for the order on the second line. On error the response contains an error message.

Returning/Cancelling a Voucher

The cancelvoucher transaction can be used to cancel a voucher. The request contains just the voucher-ID. The response is empty or contains an error message.

For this transaction to succeed the voucher must not have been used. The price and the value will be reset to zero. If the voucher is already cancelled the transaction will report success.

Destroying a Voucher

The emptyvoucher transaction can be used to void any remaining value of the voucher. The request contains just the voucher-ID. The response is empty or contains an error message.

This transaction simulates buying nothing for a lot of money: it sets the voucher to used and resets the remaining value to zero. The voucher will still have a price that needs to be paid and it cannot be returned/reimbursed afterwards.

Only privileged users should be able to do this (if anybody at all).

Getting a Voucher

The getvoucher transaction can be used to retrieve information about a specific voucher. The request just contains the voucher ID, the response contains the XML representation of it (see the Voucher tag in the Order XML object for details).

Using a Voucher outside the system

The usevoucheroutside transaction can be used to remove value from a voucher without logging it to a specific order. The request contains the voucherid in the first line and the value to take in the second line. The response contains the actual value taken in the first line and the remaining value of the voucher in the second line.

Templates

Templates are used for printouts and documents. There are several types of templates:

Base names of templates are restricted to the regular expression ^[a-z0-9_]+$ and are case-insensitive. They may have an extension (legal values: "od[ts]t", "xtt") and a variant ID (at the moment numeric, but may match "^[a-z0-9_]+$").

Below "file name" refers to the complete concatenation of base name, extension, and variant: basename.extension[,variant]

List of Templates

The gettemplatelist transaction returns an informational list of templates. The request is empty, the response looks like:

<TList>
  <Template name="filename" hash="md5-hash">Description text</Template>
  ...
</TList>
The Hash is caculated at the server side and can be used to find out whether the template has been changed. It does not necessarily need to be MD5 or any other specific algorithm, it can be any kind of ASCII string that shows changes (hence the client must remember the string if it wants to use it).

Getting a Template

The gettemplate transaction returns a specific template. The request contains only the file name, the response contains the template file as content. In case of an error the content is left empty and the status code is set appropriately.

Setting a Template

The settemplate transaction creates a new template file. The request contains the file name terminated with a newline ("\n") and then the binary content of the template - it is important that there are no additional characters between the newline and the template content. The response contains the new hash of the template or error details. The description is initially set to NULL and can be changed later with settemplatedescription.

The settemplatedescription transaction sets a new description for a template. The first line of the request contains the filename, the remainder the description.

Deleting a Template

The deletetemplate transaction deletes a template from the database. The request contains the file name (full name). The response is empty. The transaction does not return any errors.

Backup

The currently implemented backup function is DB scheme dependent. This may change in the future.

The machine interface only provides for the retrieval of the backup file. Restoration is done via admin.php.

The backup transaction is used to retrieve a backup file. It does not have any parameters. The response is in the special backup format:

startbackup
backupversion 0
dbversion 00.02
table exampletab
value stringcolumn str TWFnaWNTbW9rZVZlcnNpb24=
value intcolumn int 1
value boolcolumn bool 1
value anothercolumn NULL NULL
insert
endofbackup
The format is command oriented: each line is a specific command that can be interpreted by the restore processor:
CommandDescription
startbackupmarks the begin of a backup file
backupversiondefines the format version (integer version number) of this backup file - this only shows which commands are valid, not what content can be transferred
dbversionversion of the database scheme this data is taken from
tablemarks the start of a new table, has the (scheme-)name of the table as parameter, deletes the current dataset buffer
valueadds a value to the current dataset buffer, parameters are the column name, encoding format and value
insertpushes the current dataset buffer into the current table, then empties the dataset buffer
endofbackupmarks the end of the backup file, the processor should stop here

Table cell values are encoded according to the content in the source database. The target database must decode the values according to the format used in the backup file and then escape the value as appropriate for the target database (irrespective of the just decoded source format).

The following encoding formats are currently known:
FormatDescription
NULLa NULL value, the actual value in the backup file does not matter, the target value is NULL
intinteger, the value must be converted into an integer number
boolboolean, the value "1" means true, the value "0" means false, everything else is an error and should be interpreted as NULL
strstring or blob, the content is base64 encoded - if it is a string the result of base64 decoding is in UTF-8 encoding