Userstream previewers: Coming soon there will be a number of changes that may impact applications.
The first is support for OAuth 1.0a. When rolled out, you will be able to sign requests to all streaming API endpoints on betastream.twitter.com. This means that you can use OAuth with both user streams and other streaming calls (filter, sample, etc.) To obtain access tokens use the regular twitter.com OAuth flow, then sign requests to betastream.twitter.com. If you already have an access token you should be able to use it with the streaming API. The second is inclusion of fully hydrated objects for the social events. Instead of just getting a source id, target id, and target object id you will get the full user object in source and target fields, and the full status in the target object field (if applicable). You will also get a "created_at" field that indicates the time the social event was created. This should dramatically reduce the number of REST API calls needed to build a client. Note that most parsers shouldn't need to change -- the ID field will still be set, you will just have more fields available. The format is the same as statuses retrieved via the rest API, with following exceptions: 1) The user's latest status may not be included 2) The user's status count may not be included 3) The user's favorites count may not be included An example of a hydrated social event is {"created_at"=>"Mon May 03 17:42:55 +0000 2010", "target_object"=> {"coordinates"=>nil, "truncated"=>false, "created_at"=>"Sun Jun 28 23:10:35 +0000 2009", "favorited"=>false, "contributors"=>nil, "text"=>"looking at cricket eyes!", "id"=>4, "geo"=>nil, "in_reply_to_user_id"=>nil, "source"=>"web", "place"=>nil, "user"=> {"profile_background_tile"=>false, "name"=>"Ray", "profile_sidebar_border_color"=>"87bc44", "profile_sidebar_fill_color"=>"e0ff92", "location"=>nil, "created_at"=>"Mon Apr 12 00:00:00 +0000 2010", "profile_image_url"=>"/images/default_profile_4_normal.png", "profile_link_color"=>"0000ff", "contributors_enabled"=>false, "url"=>nil, "favourites_count"=>1, "id"=>4, "utc_offset"=>-21600, "profile_text_color"=>"000000", "protected"=>true, "lang"=>"en", "followers_count"=>3, "notifications"=>nil, "verified"=>false, "description"=>nil, "profile_background_color"=>"9ae4e8", "geo_enabled"=>false, "time_zone"=>"Saskatchewan", "profile_background_image_url"=>"/images/themes/theme1/bg.png", "statuses_count"=>1, "friends_count"=>3, "screen_name"=>"ray", "following"=>nil}, "in_reply_to_screen_name"=>nil, "in_reply_to_status_id"=>nil}, "event"=>"favorite", "target"=> {"profile_background_tile"=>false, "name"=>"Ray", "profile_sidebar_border_color"=>"87bc44", "profile_sidebar_fill_color"=>"e0ff92", "location"=>nil, "created_at"=>"Mon Apr 12 00:00:00 +0000 2010", "profile_image_url"=>"/images/default_profile_4_normal.png", "profile_link_color"=>"0000ff", "contributors_enabled"=>false, "url"=>nil, "favourites_count"=>1, "id"=>4, "utc_offset"=>-21600, "profile_text_color"=>"000000", "protected"=>true, "lang"=>"en", "followers_count"=>3, "notifications"=>nil, "verified"=>false, "description"=>nil, "profile_background_color"=>"9ae4e8", "geo_enabled"=>false, "time_zone"=>"Saskatchewan", "profile_background_image_url"=>"/images/themes/theme1/bg.png", "statuses_count"=>1, "friends_count"=>3, "screen_name"=>"ray", "following"=>nil}, "source"=> {"profile_background_tile"=>false, "name"=>"Jack", "profile_sidebar_border_color"=>"87bc44", "profile_sidebar_fill_color"=>"e0ff92", "location"=>"San Francisco", "created_at"=>"Wed Apr 28 00:00:00 +0000 2010", "profile_image_url"=> "http://s3.amazonaws.com/twitter_development/profile_images/2/jack_normal.jpg", "profile_link_color"=>"0000ff", "contributors_enabled"=>false, "url"=>nil, "favourites_count"=>0, "id"=>3, "utc_offset"=>-28800, "profile_text_color"=>"000000", "protected"=>true, "lang"=>"en", "followers_count"=>2, "notifications"=>nil, "verified"=>false, "description"=>"love, love", "profile_background_color"=>"9ae4e8", "geo_enabled"=>false, "time_zone"=>"Pacific Time (US & Canada)", "profile_background_image_url"=>"/images/themes/theme1/bg.png", "statuses_count"=>1, "friends_count"=>2, "screen_name"=>"jack", "following"=>nil}} The third is an improvement to the direct message payload. Currently it's a bit of a pain to disambiguate statuses and DMs. We'll be wrapping direct messages in a higher level "direct_message" object, e.g. {"direct_message"=> {"created_at"=>"Wed Apr 28 14:56:31 +0000 2010", "sender_screen_name"=>"user1", "sender"=> {"profile_background_tile"=>false, "name"=>"User1", "profile_sidebar_border_color"=>"87bc44", "profile_sidebar_fill_color"=>"e0ff92", "location"=>"San Francisco", "created_at"=>"Wed Apr 28 00:00:00 +0000 2010", "profile_image_url"=> "http://s3.amazonaws.com/twitter_development/profile_images/2/user1_normal.jpg", "profile_link_color"=>"0000ff", "contributors_enabled"=>false, "url"=>nil, "favourites_count"=>0, "id"=>3, "utc_offset"=>-28800, "profile_text_color"=>"000000", "protected"=>true, "lang"=>"en", "followers_count"=>2, "notifications"=>nil, "verified"=>false, "description"=>"love, love", "profile_background_color"=>"9ae4e8", "geo_enabled"=>false, "time_zone"=>"Pacific Time (US & Canada)", "profile_background_image_url"=>"/images/themes/theme1/bg.png", "statuses_count"=>1, "friends_count"=>2, "screen_name"=>"user1", "following"=>nil}, "text"=>"holy calamity scream insanity", "recipient_screen_name"=>"user2", "id"=>1, "recipient"=> {"profile_background_tile"=>false, "name"=>"User2", "profile_sidebar_border_color"=>"87bc44", "profile_sidebar_fill_color"=>"e0ff92", "location"=>nil, "created_at"=>"Mon Feb 01 00:00:00 +0000 2010", "profile_image_url"=>"/images/default_profile_5_normal.png", "profile_link_color"=>"0000ff", "contributors_enabled"=>true, "url"=>"http://twitter.com/user2", "favourites_count"=>0, "id"=>5, "utc_offset"=>19800, "profile_text_color"=>"000000", "protected"=>true, "lang"=>"en", "followers_count"=>4, "notifications"=>nil, "verified"=>false, "description"=>nil, "profile_background_color"=>"9ae4e8", "geo_enabled"=>false, "time_zone"=>"Mumbai", "profile_background_image_url"=>"/images/themes/theme1/bg.png", "statuses_count"=>7, "friends_count"=>4, "screen_name"=>"user2", "following"=>nil}, "recipient_id"=>5, "sender_id"=>3}} Given this structure, all messages are easily disambiguated by looking at the first level of keys in the JSON message 1) If the key "text" exists, this is a status 2) If the key "delete" exists, this is a status deletion 3) If the key "scrub_geo" exists, this is a geo-tagging deletion message 4) If the key "direct_message" exists, this is a direct message 5) If the key "event" exists, this is a social event We realize that email isn't the best way to keep this documented in the long term, and we're working on getting this information onto dev.twitter.com. We'll send out additional notices as these become available, but we wanted to let you know these changes were coming. ---Mark http://twitter.com/mccv