diff --git a/include/class.api.php b/include/class.api.php
index 76fb481dec6cc5b81a0ffb3a3295c73916179da9..67f2855274dac367ccc9158b2a480d08fa6596b5 100644
--- a/include/class.api.php
+++ b/include/class.api.php
@@ -323,6 +323,17 @@ class ApiXmlDataParser extends XmlDataParser {
                 $value = (bool)$value;
             } else if ($key == "autorespond") {
                 $value = (bool)$value;
+            } else if ($key == "message") {
+                if (!is_array($value)) {
+                    $value = array(
+                        "body" => $value,
+                        "type" => "text/plain",
+                        # TODO: Get encoding from root <xml> node
+                    );
+                } else {
+                    $value["body"] = $value[":text"];
+                    unset($value[":text"]);
+                }
             } else if ($key == "attachments") {
                 if(!isset($value['file'][':text']))
                     $value = $value['file'];
@@ -363,34 +374,24 @@ class ApiJsonDataParser extends JsonDataParser {
                 $value = (bool)$value;
             } else if ($key == "autorespond") {
                 $value = (bool)$value;
+            } elseif ($key == "message") {
+                // Allow message specified in RFC 2397 format
+                $data = Format::parseRfc2397($value, 'utf-8');
+                if (!isset($data['type']) || $data['type'] != 'text/html')
+                    $value = sprintf('<div style="white-space:pre-wrap">%s</div>',
+                        Format::htmlchars($data['data']));
+                else
+                    $value = $data['data'];
             } else if ($key == "attachments") {
                 foreach ($value as &$info) {
                     $data = reset($info);
                     # PHP5: fopen("data://$data[5:]");
-                    if (substr($data, 0, 5) != "data:") {
-                        $info = array(
-                            "data" => $data,
-                            "type" => "text/plain",
-                            "name" => key($info));
-                    } else {
-                        $data = substr($data,5);
-                        list($meta, $contents) = explode(",", $data);
-                        list($type, $extra) = explode(";", $meta);
-                        $info = array(
-                            "data" => $contents,
-                            "type" => ($type) ? $type : "text/plain",
-                            "name" => key($info));
-                        # XXX: Handle decoding here??
-                        if (substr($extra, -6) == "base64")
-                            $info["encoding"] = "base64";
-                        # Handle 'charset' hint in $extra, such as
-                        # data:text/plain;charset=iso-8859-1,Blah
-                        # Convert to utf-8 since it's the encoding scheme
-                        # for the database. Otherwise, assume utf-8
-                        list($param,$charset) = explode('=', $extra);
-                        if ($param == 'charset' && $charset)
-                            $contents = Format::utf8encode($contents, $charset);
-                    }
+                    $contents = Format::parseRfc2397($data, 'utf-8', false);
+                    $info = array(
+                        "data" => $contents['data'],
+                        "type" => $contents['type'],
+                        "name" => key($info),
+                    );
                 }
                 unset($value);
             }
@@ -399,10 +400,6 @@ class ApiJsonDataParser extends JsonDataParser {
             }
         }
 
-        if(isset($current['message']) && $current['message'])
-            $current['message'] = sprintf('<div style="white-space:pre-wrap">%s</div>',
-                    Format::htmlchars($current['message']));
-
         return $current;
     }
 }
diff --git a/include/class.format.php b/include/class.format.php
index 11f0b1040b7e5a8e36f3ba7b65b92cf326dfe21e..843033ae205875af379cff31c7c26026df1a2855 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -369,5 +369,62 @@ class Format {
         return (empty($text)) ? 'n-a' : $text;
     }
 
+    /**
+     * Parse RFC 2397 formatted data strings. Format according to the RFC
+     * should look something like:
+     *
+     * data:[type/subtype][;charset=utf-8][;base64],data
+     *
+     * Parameters:
+     * $data - (string) RFC2397 formatted data string
+     * $output_encoding - (string:optional) Character set the input data
+     *      should be encoded to.
+     * $always_convert - (bool|default:true) If the input data string does
+     *      not specify an input encding, assume iso-8859-1. If this flag is
+     *      set, the output will always be transcoded to the declared
+     *      output_encoding, if set.
+     *
+     * Returs:
+     * array (data=>parsed and transcoded data string, type=>MIME type
+     * declared in the data string or text/plain otherwise)
+     *
+     * References:
+     * http://www.ietf.org/rfc/rfc2397.txt
+     */
+    function parseRfc2397($data, $output_encoding=false, $always_convert=true) {
+        if (substr($data, 0, 5) != "data:")
+            return array('data'=>$data, 'type'=>'text/plain');
+
+        $data = substr($data, 5);
+        list($meta, $contents) = explode(",", $data, 2);
+        if ($meta)
+            list($type, $extra) = explode(";", $meta, 2);
+        else
+            $extra = '';
+        if (!isset($type) || !$type)
+            $type = 'text/plain';
+
+        $parameters = explode(";", $extra);
+
+        # Handle 'charset' hint in $extra, such as
+        # data:text/plain;charset=iso-8859-1,Blah
+        # Convert to utf-8 since it's the encoding scheme for the database.
+        $charset = ($always_convert) ? 'iso-8859-1' : false;
+        foreach ($parameters as $p) {
+            list($param, $value) = explode('=', $extra);
+            if ($param == 'charset')
+                $charset = $value;
+            elseif ($param == 'base64')
+                $contents = base64_decode($contents);
+        }
+        if ($output_encoding && $charset)
+            $contents = Format::encode($contents, $charset, $output_encoding);
+
+        return array(
+            'data' => $contents,
+            'type' => $type
+        );
+    }
+
 }
 ?>
diff --git a/include/class.forms.php b/include/class.forms.php
index 48e1e9047156e384d3324edc82fcd36add8520a7..b51629bc5c69fcca17a905e5916b58dd349e4f6a 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -553,6 +553,14 @@ class ChoiceField extends FormField {
         );
     }
 
+    function parse($value) {
+        if (is_numeric($value))
+            return $value;
+        foreach ($this->getChoices() as $k=>$v)
+            if (strcasecmp($value, $v) === 0)
+                return $k;
+    }
+
     function toString($value) {
         $choices = $this->getChoices();
         if (isset($choices[$value]))
diff --git a/include/class.ticket.php b/include/class.ticket.php
index d6002ab73f7e0598fb9690a571d8be75716d6857..82cc169a59eb019fe6c2d87a61f1052561f66586 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1897,7 +1897,7 @@ class Ticket {
         foreach ($form->getFields() as $field) {
             $fname = $field->get('name');
             if ($fname && isset($vars[$fname]) && !$field->value)
-                $field->value = $vars[$fname];
+                $field->value = $field->parse($vars[$fname]);
         }
 
         // Don't enforce form validation for email
diff --git a/setup/doc/api/tickets.md b/setup/doc/api/tickets.md
index a8bfd39f1b0791d9bb097484d0d09364e1ef1749..9c6f3dfe4af5c1d22a15ab1c9f54d2a8cd662c9f 100644
--- a/setup/doc/api/tickets.md
+++ b/setup/doc/api/tickets.md
@@ -17,13 +17,18 @@ request content.
 *   __email__:   *required* Email address of the submitter
 *   __name__:    *required* Name of the submitter
 *   __subject__: *required* Subject of the ticket
-*   __message__: *required* Initial message for the ticket thread
+*   __message__: *required* Initial message for the ticket thread. The
+                message content can be specified using RFC 2397 in the JSON
+                format. The content of the message element should be the
+                message body. Encoding is assumed based on the encoding
+                attributed set in the xml processing instruction.
+    *  __type__:    Content-Type of the message body. Valid values are
+        `text/html` and `text/plain`. If not specified, `text/plain` is
+        assumed
 *   __alert__:       If unset, disable alerts to staff. Default is `true`
 *   __autorespond__: If unset, disable autoresponses. Default is `true`
 *   __ip__:          IP address of the submitter
-*   __phone__:       Phone number of the submitter
-*   __phone_ext__:   Phone number extension -- can also be embedded in *phone*
-*   __priorityId__:  Priority *id* for the new ticket to assume
+*   __priority__:    Priority *id* for the new ticket to assume
 *   __source__:      Source of the ticket, default is `API`
 *   __topicId__:     Help topic *id* associated with the ticket
 *   __attachments__: An array of files to attach to the initial message.
@@ -34,6 +39,47 @@ request content.
     *   __type__:     Mime type of the file. Default is `text/plain`
     *   __encoding__: Set to `base64` if content is base64 encoded
 
+### Custom Forms and Fields ###
+
+Fields added to both the common ticket and common client forms can accept
+data via the API as well. The `name` attribute given in form designer is
+used to match up the data in the API request with the field to parse and
+receive the data.
+
+These fields are included with the stock common client form. The `name`
+field can be changed and the field can also be deleted. This section is
+provided as an initial list. The fields supported by your help desk will
+depend on your configuration for the common client and common ticket forms.
+
+*   __phone__:       Phone number of the submitter. If the extension is
+                     included, use a capital 'X' followed by the extension
+*   __notes__:       Internal notes for the client created. These notes are
+                     only visible to authenticated staff members
+
+#### Field Data Processing Rules ####
+
+Some fields have special formatting for inputs. For instance date fields
+must receive the date formatted in Unix epoch time. This processing is
+performed automatically for requests from the web interface. However, in the
+case of the API, the remote requester is required to perform the procecssing
+priori to submitting the request via the API. The sections below outline how
+to format data for custom fields for requests sent via the API.
+
+* __Date Fields__:  Date fields need to be formatted in a format
+        recognizable to PHP's strtotime() function. The best formats are
+        [Unix epoch time](wikipedia.org/wiki/Unix_time), and [ISO 8601]
+        (http://xkcd.com/1179/). If using timezone offset in the date
+        specification, ensure that the _Timezone Aware_ flag is set for the
+        field.
+
+* __Phone number Fields__: If the extension is provided with the phone
+        number, include a capital 'X' between the phone number and phone
+        extension parts of the field.
+
+* __Choice and Selection Fields__: Use either the key specified with the
+        choice field, or the name of the field. For selection fields, do not
+        use anything from the `extra` column of the list designer.
+
 ### XML Payload Example ######
 
 * `POST /api/tickets.xml`
@@ -55,8 +101,8 @@ Notice that the phone extension can be sent as the `@ext` attribute of the
     <name>Angry User</name>
     <email>api@osticket.com</email>
     <subject>Testing API</subject>
-    <phone ext="123">318-555-8634</phone>
-    <message><![CDATA[Message content here]]></message>
+    <phone>318-555-8634X123</phone>
+    <message type="text/plain"><![CDATA[Message content here]]></message>
     <attachments>
         <file name="file.txt" type="text/plain"><![CDATA[
             File content is here and is automatically trimmed
@@ -99,7 +145,7 @@ an object or array definition, and newlines are not allowed inside strings.
     "phone": "3185558634X123",
     "subject": "Testing API",
     "ip": "123.211.233.122",
-    "message": "MESSAGE HERE",
+    "message": "data:text/html,MESSAGE <b>HERE</b>",
     "attachments": [
         {"file.txt": "data:text/plain;charset=utf-8,content"},
         {"image.png": "data:image/png;base64,R0lGODdhMAA..."},