Using The WordPress XML-RPC API With PHP: The Post Model’s Properties

Part 4 in a series on working with the WordPress XML-RPC API with PHP.

Previously I discussed the reasons for creating a data model (aka a class), that looks like a WordPress post, in order to streamline and simplify working with the WordPress XML-RPC API.

In this post, we’ll create the properties, or data, that goes into that model. This will help us make heads and tails out of what we need to send to the XML-RPC API, and what we’ll get back, when working with posts.

The Post Model: Properties

Here’s what data is contained inside a WordPress post object, according to the documentation:

These are the properties of a WordPress post. Source: WordPress Codex, XML-RPC WordPress API/Posts
These are the properties of a WordPress post. Source: WordPress Codex, XML-RPC WordPress API/Posts

This table contains notes about each of these properties of a post, as described at the WordPress Codex.

In those cases where the name and contents of the field are self-explanatory, there is no note.

In some cases, the Codex describes a field as a given data type (e.g., string) when in fact it’s something else (e.g, an integer). A dagger indicates a field is actually an integer; an asterix, that the field is really an enum.

type property notes
string† post_id This is a numeric ID for the post. If you’re creating a new post, you don’t provide this; it is the return value you’ll get back from the API.
string post_title  
datetime post_date When we create a post via XML-RPC, we send datetimes as an XML-RPC datetime, which is really just a string, formatted YYYYMMDDThh:mm:ss; the “T” in that is a literal “T” and represents a separator between the date and time. When the XML-RPC API returns a post to us, this field is an object. This doesn’t need to be set when creating a post; the current timestamp is the default value. This note is true for all four datetime values in the post model.
datetime post_date_gmt Same as above, only in GMT / UTC.
datetime post_modified  
datetime post_modified_gmt  
string* post_status Must be ‘draft’, ‘publish’, ‘pending’, ‘future’, ‘private’ or a custom registered status. Defaults to ‘draft’ for new posts.
string* post_type Must be ‘post’, ‘page’, ‘link’, ‘nav_menu_item’ or a custom post type. Defaults to ‘post’ for new posts.
string* post_format Must be ‘standard’, ‘aside’, ‘chat’, ‘gallery’, ‘link’, ‘image’, ‘quote’, ‘status’, ‘video’ ‘audio’ or a custom post format. Defaults to ‘standard’ for new posts.
string post_name This is the “slug” of the article, which is often used for making pretty permalinks. It tends to be an all-lower-case, hyphenated version of the post title, although it can technically be set to just about anything. For example, this post has the post_name “using-wordpress-xml-rpc-api-php-post-models-properties.”
string† post_author In the WordPress database itself, this is a foreign key reference to a user ID from the users table. It’s possible to spoof authors; that is, if your XML-RPC user has sufficient permissions to edit another user’s work, you can create or edit an article via XML-RPC for users other than the user connecting via XML-RPC. If you don’t specify an author when making a new post, the user ID of the XML-RPC user is used.
string post_password  
string post_excerpt  
string post_content  
string† post_parent Mostly used for pages or custom post types that support hierarchies, this is actually an integer containing the post ID of the parent post.
string post_mime_type This is primarily used for attachments (e.g., Media), which are actually treated as a custom post type by WordPress. It is a standard MIME type identifier string (e.g., image/jpeg, application/pdf).
string link Again, mostly useful when retrieving an attachment via its post ID; this is the URL to the attachment’s file, or for nav_menu_item, the link where the menu item goes.
string guid This is usually a URL that will properly display the content of the post. It’s what’s returned by the WordPress function wp_get_shortlink.
int menu_order Used for nav menu items, determines the order in which the post is displayed when being treated as a nav item.
string* comment_status Confined to ‘open’ or closed, defaults to WordPress setting for the post type being created.
string* ping_status Whether trackbacks and pingbacks are allowed for this post. As above, confined to ‘closed’ or ‘open’ and defaults to WordPress setting for the post type being created.
bool sticky
int / struct post_thumbnail When creating a new post or updating a post, this is the numeric ID of the attachment that will be the featured image for this post. When retrieving a post, this is returned as a struct; we’ll flesh this out more concretely when we create the Media model, in an upcoming post.
array terms When inserting or updating a post, this is an array of keys, which are the term types, with child arrays of numeric identifiers for terms. When retrieving a post, this is an array containing a number of fields. We’ll flesh this out more when we create the Taxonomy model in an upcoming post.
array custom_fields When inserting or updating a post, this is an array of arrays containing key-value pairs for the custom field. For example, if I wanted to make a new post and add a custom field named ‘foo’ with a value of ‘bar’, I would do this:

array(array('foo', 'bar'));

. If I retrieved that post, I would get back something like this:

array(array('1023', 'foo', 'bar'));
struct enclosure Most commonly used when creating podcast or similar media-rich RSS-like posts, this contains an array of the URL, file size in bytes and MIME type for a file, such as an MP3 or video file.
Disambiguation: A struct, within the context of the WordPress post model, is basically an associative (i.e., key => value pairs) array.

Custom Fields

When we create or retrieve a post that has custom fields, we provide an array of associative arrays.

That is, each metadata item is an associative array, containing the keys id, key and value. All those metadata arrays are, in turn, placed in another, wrapper array, named custom_fields.

In the WordPress XML-RPC Post model, custom_fields is an array; inside that array are additional, associative arrays containing an id, a key, and a value for the meta data field. Source: WordPress Codex, XML-RPC API
In the WordPress XML-RPC Post model, custom_fields is an array; inside that array are additional, associative arrays containing an id, a key, and a value for the meta data field. Source: WordPress Codex, XML-RPC API
type property notes
int id The internal WordPress ID for this metadata field, returned by WordPress when we retrieve a post. Don’t provide this when creating a metadata field for a new post.
string key The name of the metadata field, e.g., “post_background_color
string value The value that I am storing in the metadata field, e.g., “blue”

When we create a post, we don’t need to provide an ID for the metadata item. We only need to provide a key — e.g., “my_metafield” — and a value — e.g., “hello world.”

However, metadata keys are not unique in WordPress, which is why WordPress returns the id value for the metadata field when we retrieve a post via XML-RPC.

That is, if I create a post through XML-RPC with the key “my_metafield” and the value “hello world,” that field will be added to my post with that value. No need to provide an ID; WordPress will generate one when it adds the field to the post.

However, I can’t then edit the same post, pass in a custom_field with the key “my_metafield” and the value “goodbye world,” but no ID for that metadata field.

If I do that, WordPress will add a second metadata field with the key “my_metadata” and the value “goodbye world.” So I’ll have two metadata fields with the key “my_metafield”: one that has the value “hello world,” and another that has the value “goodbye world.”

To edit the value of an existing custom_field, I need to know its ID. Otherwise, I’ll effectively create a duplicate meta key with a different value.

We’ll cover taxonomy and media in upcoming posts.

All links in this post on delicious:


  1. I have integrated xmlrpc in php , now i can able to post in word-press through php xmlrpc API , I have installed the custom post plugin & created the custom posts in wordpress, When i try to post in the custom posts, i am getting the error as invalid post type. The custom post slug name is custompost. is it possible to create the custom post in XmlRPc php?

  2. @Rasim: Yes, you can create a custom post type via XML-RPC and the built-in wp.newPost method. The struct you create for the post must have the field “post_type” which must be the slug of the custom post type in WordPress. So check your register_post_type function and make sure you’re using the right slug.

    Assuming the slug is “custompost,” your struct would look something like this:

    	'post_title' => 'This is the title of my post',
    	'post_content' => 'Lorem ipsum dolor sit amet.',
    	'post_type' => 'custompost'

    You should probably rename your custom post type to something other than “custompost.” Pretty much anything that does not contain “custom” or “post” is a good name, since it would not surprise me to find that “custom,” “post” and “custompost” are all stop words. Rename it to something like “appletoot” because I am sure that’s fine.

    Finally ensure that your custom post type has support for all the fields you are supplying in the post struct. That is, don’t pass in categories for a custom post type; if you’re passing in a custom taxonomy, make sure that it is properly registered, etc.

  3. Hi Doug,

    Thanks for this article ! This helps me a lot !!
    However, I have some problems to schedule a post. I tried to put : ‘post_status’=>’future’ and for example ‘post_date’=>’20160422T15:52:01’ but my post is immediatly published. Do you know why ?

  4. @Fred: The two most likely reasons are that your website server’s clock is wrong (it’s set to a far-future date) or you are running a plugin that is preventing scheduled posts.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!