The XML-RPC API is no longer under active development. While it is still supported, no further improvements or changes will be made to it.

We strongly recommend that you use the REST API instead.


You can easily create and manipulate users in ActionKit using the XML-RPC API.



Creates a new user and returns a struct representing the new user. See User Fields below for the full list of valid fields.


A User created using this method will not be subscribed and will not be mailable. You will need to call act() using this User's token or email for them to be mailable.

>>> user = actionkit.User.create({
            'email': 'xmlrpctest@example.com',
            'first_name': 'XML',
            'last_name': 'RPC',
            'zip': '12345',
>>> user
{'address1': '',
 'address2': '',
 'city': '',
 'country': 'United States',
 'email': 'xmlrpctest@example.com',
 'first_name': 'XML',
 'id': 4,
 'last_name': 'RPC',
 'middle_name': '',
 'password': '',
 'plus4': '',
 'postal': '',
 'prefix': '',
 'region': '',
 'source': '',
 'state': 'NY',
 'state_name': 'New York',
 'subscription_status': 'never',
 'suffix': '',
 'token': '.4.Im5_dn',
 'zip': '12345'}


Retrieves a struct of information about a user from ActionKit, which includes user fields and custom user fields. The method takes one argument (id or email), but in a struct.

The get method call will return a Fault with faultCode 'DoesNotExist' if the user is not found.

struct = actionkit.User.get({'id':id})
struct = actionkit.User.get({'email':'email@example.com'})
struct = actionkit.User.get({'pk':'email@example.com'})
struct = actionkit.User.get({'akid':akid})

ActionKit tries hard to figure out which unique key you are using. For example, if you try to find Phones for a user, you can use an email or id. However, you cannot use akid for related objects.

{'created_at': '2011-06-16T14:08:44',
 'id': 29,
 'normalized_phone': '2125551212',
 'phone': '2125551212',
 'source': 'user',
 'type': 'home',
 'updated_at': '2011-06-16T14:08:44',
 'user': 5}

{'created_at': '2011-06-16T14:08:44',
 'id': 29,
 'normalized_phone': '2125551212',
 'phone': '2125551212',
 'source': 'user',
 'type': 'home',
 'updated_at': '2011-06-16T14:08:44',
 'user': 5}


The save method will update an existing ActionKit user's data. The struct must contain an 'id' key, to identify the user we will update. The other keys may be any valid user field or custom user field.

Custom user fields should be prefixed with user_. If you have added a user field named 'favorite_color', you would call save with 'user_favorite_color'.

May return a Fault with faultCode 'InvalidFieldError' or 'DoNotExist'

When you change any part of a user's address through the API, we clear the user's other address fields. So, if you change a user's ZIP, we'll clear their old address1. That keeps our automatic ZIP+4 lookup from overwriting your new ZIP with a ZIP based on the old address.

As a result, your API apps need to update all address fields at once to work right. For example, it wouldn't work to write a script that updates just user ZIPs in one pass and user street addresses in another.

No address info will be cleared as long as all the fields you submit either match what was on file or are blank. Submitting the ZIP that's already on file, or no address info at all, is safe.

struct = actionkit.User.save({'id':id, 'zip':'10014'})


The save_or_create method will create a new User or update an existing User.

May return a Fault with faultCode 'IllegalArgumentError', 'InvalidFieldError'

struct = actionkit.User.save_or_create({
            'email': 'xml+rpc@example.com',
            'first_name': 'XML',
            'last_name': 'RPC',
            'zip': '10014',


The is_subscribed method let's you determine if a user is subscribed to any list or to a particular list.

boolean = actionkit.User.is_subscribed()
boolean = actionkit.User.is_subscribed({'list': list_id})

Note on subscriptions

There is no User method for subscribing users, because User's can only be subscribed when taking an action. Processing actions is described in Processing User Actions.


Returns a list of current subscriptions for a given User. Each struct in the list will have the keys created_at, id (of the list), and name (of the list).

list = actionkit.User.subscriptions({'id':user_id})


Returns a list of a User's subscription history - each change in their subscription status.

>>> list = actionkit.User.subscription_history({'id': user_id})
>>> pprint.pprint(list)
[{'changed_at': '2009-09-29T13:02:00',
  'list_id': 1,
  'list_name': 'Main email list',
  'subscription_change': 'unsubscribe'},
 {'action_id': 3,
  'action_taken_at': '2009-09-26T10:10:09',
  'changed_at': '2009-09-26T10:10:09',
  'list_id': 1,
  'list_name': 'Main email list',
  'page_name': 'everyhome',
  'page_type': 'Signup',
  'subscription_change': 'subscribe'}]


Unsubscribes a User from all lists.

>>> actionkit.User.unsubscribe_all({'id': user_id})

Returns nothing on success and DoesNotExist fault if the user doesn't exist.


Unsubscribes a User from one list

>>> actionkit.User.unsubscribe({'id': user_id, 'list_id': list_id})

Returns nothing on success and DoesNotExist fault if the user or list doesn't exist.


Returns a user's highest previous contribution or '0.00'.

>>> actionkit.User.highest_previous_contribution({'id': user_id})

You can also use DonationHPCRules directly with or without a user.

>>> actionkit.DonationHPCRule.generate_ask(dict(
>>> actionkit.DonationHPCRule.generate_ask(dict(



Here's a simple example of how to use the User methods. In all the examples, you should use the user and password you Setup to have the api privilege. The host is the hostname of your ActionKit admin server.

from xmlrpclib import Server

actionkit = Server('https://%s:%s@%s/api/' % (user,password,host))

user_data = {
        'email': 'xmlrpctest@example.com',
        'first_name': 'XML',
        'last_name': 'RPC',
        'zip': '12345',

user = actionkit.User.save_or_create(user_data)

user["zip"] = '54321'

user = actionkit.User.save(user)

id = user["id"]

user = actionkit.User.get({ 'id': id })

print "Hello, %s!" % user["first_name"]

User Fields

The basic user fields are:

  • email - 255 characters, searchable, unique, required

Name Fields

  • prefix - 255 characters
  • first_name - 255 characters
  • middle_name - 255 characters
  • last_name - 255 characters
  • suffix - 255 characters


  • subscription_status - 255 characters, searchable, defaults to 'never', see subscription status choices below.
  • source - 255 characters, searchable. This field is an arbitrary code for tracking users, simply add 'source' to your action processing code.

Address Fields

  • address1 - 255 characters
  • address2 - 255 characters
  • city - 255 characters
  • state - 255 characters
  • region - 255 characters
  • postal - 255 characters, if country is 'United States' must be a valid zip (ex. "10001" or "10001-1234")
  • zip - 5 characters
  • plus4 - 4 characters
  • country - 255 characters, defaults to 'United States'


  • updated_at - Datetime of last update
  • created_at - Datetime User was created

Subscription Status

User's are subscribed to lists when they take actions. Users are unsubscribed when they manually unsubscribe or bounce. We keep a field in the user's table to make it easy to find a User's current status. See subscription_history for getting more detailed information.

The status field in the struct returned by User methods can be:

  • subscribed - A currently mailable User.
  • unsubscribed - A User who has unsubscribed.
  • bounced - A User whose email had a hard bounce.
  • never - A User who has never been subscribed.

Custom User Fields

In ActionKit, you can create custom user fields to store additional information with each User record. You can update and retrieve these user fields using the API. In order to append a field to a User record you first have to add it as an allowed user field. See Custom User Fields in the ActionKit Admin.

Calls that return Users will return custom fields in a key names 'custom_fields'. Calls that update Users should prefix custom fields with user_.

struct = actionkit.User.save_or_create({
            'email': 'xml+rpc@example.com',
            'first_name': 'XML',
            'last_name': 'RPC',
            'zip': '10014',
            'user_favorite_color': 'orange'

It is also possible to set custom fields using a custom_fields input.

struct = actionkit.User.save_or_create({
            'email': 'xml+rpc@example.com',
            'first_name': 'XML',
            'last_name': 'RPC',
            'zip': '10014',
            'custom_fields': {
                'favorite_color': 'orange'

You can also get only custom fields using the custom_fields method:

struct = actionkit.User.custom_fields({
    'email': 'xmprpc@example.com'

Custom fields are searchable, but only when you search for another field that is indexed, e.g. zip, country or state:

list = actionkit.User.search(dict(
    country='United States'