singly 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +63 -0
  5. data/Rakefile +8 -0
  6. data/lib/singly/account.rb +63 -0
  7. data/lib/singly/api/auth/merge.rb +8 -0
  8. data/lib/singly/api/auth/service/oauth1_apply.rb +13 -0
  9. data/lib/singly/api/auth/service/oauth2_apply.rb +13 -0
  10. data/lib/singly/api/auth/service.rb +23 -0
  11. data/lib/singly/api/auth.rb +163 -0
  12. data/lib/singly/api/friends/group.rb +12 -0
  13. data/lib/singly/api/friends.rb +76 -0
  14. data/lib/singly/api/id.rb +6 -0
  15. data/lib/singly/api/multi.rb +6 -0
  16. data/lib/singly/api/profile.rb +6 -0
  17. data/lib/singly/api/profiles/delete.rb +8 -0
  18. data/lib/singly/api/profiles/delete_profile.rb +8 -0
  19. data/lib/singly/api/profiles/delete_service.rb +8 -0
  20. data/lib/singly/api/profiles/self.rb +8 -0
  21. data/lib/singly/api/profiles/self_update.rb +8 -0
  22. data/lib/singly/api/profiles/service.rb +18 -0
  23. data/lib/singly/api/profiles.rb +178 -0
  24. data/lib/singly/api/proxy/delete.rb +8 -0
  25. data/lib/singly/api/proxy/get.rb +8 -0
  26. data/lib/singly/api/proxy/post.rb +8 -0
  27. data/lib/singly/api/proxy/put.rb +8 -0
  28. data/lib/singly/api/proxy.rb +169 -0
  29. data/lib/singly/api/services/37signals.rb +14 -0
  30. data/lib/singly/api/services/bodymedia.rb +30 -0
  31. data/lib/singly/api/services/dropbox.rb +22 -0
  32. data/lib/singly/api/services/dwolla.rb +14 -0
  33. data/lib/singly/api/services/endpoint.rb +12 -0
  34. data/lib/singly/api/services/facebook.rb +62 -0
  35. data/lib/singly/api/services/fitbit.rb +34 -0
  36. data/lib/singly/api/services/flickr.rb +26 -0
  37. data/lib/singly/api/services/foursquare.rb +34 -0
  38. data/lib/singly/api/services/gcal.rb +18 -0
  39. data/lib/singly/api/services/gcontacts.rb +18 -0
  40. data/lib/singly/api/services/gdocs.rb +18 -0
  41. data/lib/singly/api/services/github.rb +34 -0
  42. data/lib/singly/api/services/gmail.rb +22 -0
  43. data/lib/singly/api/services/google.rb +14 -0
  44. data/lib/singly/api/services/gplus.rb +18 -0
  45. data/lib/singly/api/services/id_endpoint.rb +12 -0
  46. data/lib/singly/api/services/imgur.rb +14 -0
  47. data/lib/singly/api/services/instagram.rb +26 -0
  48. data/lib/singly/api/services/klout.rb +26 -0
  49. data/lib/singly/api/services/linkedin.rb +26 -0
  50. data/lib/singly/api/services/meetup.rb +30 -0
  51. data/lib/singly/api/services/paypal.rb +14 -0
  52. data/lib/singly/api/services/picasa.rb +22 -0
  53. data/lib/singly/api/services/rdio.rb +26 -0
  54. data/lib/singly/api/services/reddit.rb +14 -0
  55. data/lib/singly/api/services/runkeeper.rb +38 -0
  56. data/lib/singly/api/services/service.rb +48 -0
  57. data/lib/singly/api/services/shutterfly.rb +22 -0
  58. data/lib/singly/api/services/soundcloud.rb +14 -0
  59. data/lib/singly/api/services/stocktwits.rb +22 -0
  60. data/lib/singly/api/services/tout.rb +14 -0
  61. data/lib/singly/api/services/tumblr.rb +26 -0
  62. data/lib/singly/api/services/twitter.rb +42 -0
  63. data/lib/singly/api/services/withings.rb +18 -0
  64. data/lib/singly/api/services/wordpress.rb +22 -0
  65. data/lib/singly/api/services/yammer.rb +26 -0
  66. data/lib/singly/api/services/youtube.rb +18 -0
  67. data/lib/singly/api/services/zeo.rb +26 -0
  68. data/lib/singly/api/services.rb +158 -0
  69. data/lib/singly/api/types/type.rb +12 -0
  70. data/lib/singly/api/types.rb +68 -0
  71. data/lib/singly/endpoint.rb +112 -0
  72. data/lib/singly/error.rb +24 -0
  73. data/lib/singly/http.rb +38 -0
  74. data/lib/singly/logger.rb +14 -0
  75. data/lib/singly.rb +37 -0
  76. data/lib/version.rb +3 -0
  77. data/singly.gemspec +25 -0
  78. data/spec/integration/auth_spec.rb +14 -0
  79. data/spec/singly/account_spec.rb +108 -0
  80. data/spec/singly/api/auth_spec.rb +8 -0
  81. data/spec/singly/endpoint_spec.rb +100 -0
  82. data/spec/singly/error_spec.rb +40 -0
  83. data/spec/singly/http_spec.rb +52 -0
  84. data/spec/singly/logger_spec.rb +32 -0
  85. data/spec/singly_spec.rb +53 -0
  86. data/spec/spec_helper.rb +27 -0
  87. data/spec/vcr_cassettes/http_fetch_with_api_error.yml +39 -0
  88. data/spec/vcr_cassettes/http_fetch_with_json_response.yml +102 -0
  89. data/spec/vcr_cassettes/http_fetch_with_non_json_response.yml +39 -0
  90. metadata +216 -0
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Singly::Endpoint do
4
+ class DummyEndpoint
5
+ include Singly::Endpoint
6
+ endpoint :get, "/dummy/:service/:id@:type", required: [:a, :b], optional: [:c, :d]
7
+ end
8
+ context "class methods" do
9
+ describe ".type" do
10
+ subject { DummyEndpoint.type }
11
+ it { should == :get }
12
+ end
13
+ describe ".route" do
14
+ subject { DummyEndpoint.route }
15
+ it { should == "/dummy/:service/:id@:type" }
16
+ end
17
+ describe ".required_route_params" do
18
+ subject { DummyEndpoint.required_route_params }
19
+ it { should == [:service, :id, :type] }
20
+ end
21
+ describe ".required_params" do
22
+ subject { DummyEndpoint.required_params }
23
+ it { should == [:a, :b] }
24
+ end
25
+ describe ".optional_params" do
26
+ subject { DummyEndpoint.optional_params }
27
+ it { should == [:c, :d] }
28
+ end
29
+ end
30
+ context "instance methods" do
31
+ describe "#fetch" do
32
+ let(:endpoint) { DummyEndpoint.new(params) }
33
+ context "with valid params" do
34
+ subject { endpoint.fetch }
35
+ let(:params) { {
36
+ service: :timehop,
37
+ id: 123,
38
+ type: "just_my",
39
+ a: "a",
40
+ b: "b",
41
+ c: "c"
42
+ } }
43
+ let(:result) { double(:json) }
44
+ before { Singly::Http.should_receive(:fetch).with(:get, "/dummy/timehop/123@just_my", {a: "a", b: "b", c: "c"}).and_return(result) }
45
+ it { should == result }
46
+ end
47
+ context "with missing required params" do
48
+ let(:params) { {
49
+ service: :timehop,
50
+ id: 123,
51
+ type: "just_my",
52
+ b: "b",
53
+ c: "c"
54
+ } }
55
+ it { expect{endpoint.fetch}.to raise_error(Singly::Error, "y u no has query params :a???") }
56
+ end
57
+ context "with missing route params" do
58
+ let(:params) { {
59
+ service: :timehop,
60
+ a: "a",
61
+ b: "b"
62
+ } }
63
+ it { expect{endpoint.fetch}.to raise_error(Singly::Error, "y u no has route params :id, :type???") }
64
+ end
65
+ end
66
+ describe "#url" do
67
+ let(:endpoint) { DummyEndpoint.new(params) }
68
+ context "with valid params" do
69
+ subject { endpoint.url }
70
+ let(:params) { {
71
+ service: :timehop,
72
+ id: 123,
73
+ type: "just_my",
74
+ a: "a",
75
+ b: :b,
76
+ c: "c"
77
+ } }
78
+ it { should == "https://api.singly.com/v0/dummy/timehop/123@just_my?a=a&b=b&c=c" }
79
+ end
80
+ context "with missing required params" do
81
+ let(:params) { {
82
+ service: :timehop,
83
+ id: 123,
84
+ type: "just_my",
85
+ b: "b",
86
+ c: "c"
87
+ } }
88
+ it { expect{endpoint.fetch}.to raise_error(Singly::Error, "y u no has query params :a???") }
89
+ end
90
+ context "with missing route params" do
91
+ let(:params) { {
92
+ service: :timehop,
93
+ a: "a",
94
+ b: "b"
95
+ } }
96
+ it { expect{endpoint.fetch}.to raise_error(Singly::Error, "y u no has route params :id, :type???") }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Singly::Error do
4
+ describe ".y_u_no?" do
5
+ let(:did_i_do_that) { true }
6
+ it "should raise error with y u no message" do
7
+ expect{
8
+ Singly::Error.y_u_no?("stop doing that") { did_i_do_that }
9
+ }.to raise_error(Singly::Error, "y u no stop doing that???")
10
+ end
11
+ end
12
+ end
13
+ describe Singly::TimeoutError do
14
+ describe "#initialize" do
15
+ let(:response) { Typhoeus::Response.new({
16
+ return_code: :operation_timedout,
17
+ total_time: 2.01,
18
+ effective_url: "http://www.example.com/timemeout"
19
+ }) }
20
+ it "should raise a timeout erro " do
21
+ expect{
22
+ raise Singly::TimeoutError.new(response)
23
+ }.to raise_error(Singly::TimeoutError, "Response timed out after 2.01 seconds. http://www.example.com/timemeout")
24
+ end
25
+ end
26
+ end
27
+ describe Singly::ApiError do
28
+ describe "#initialize" do
29
+ let(:response) { Typhoeus::Response.new({
30
+ response_code: 400,
31
+ effective_url: "http://www.example.com/badresponse",
32
+ body: {timehop: :is_amazing}.to_json
33
+ }) }
34
+ it "should raise an api error" do
35
+ expect{
36
+ raise Singly::ApiError.new(response)
37
+ }.to raise_error(Singly::ApiError, "400 {\"timehop\":\"is_amazing\"} http://www.example.com/badresponse")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Singly::Http do
4
+ let(:http) { Singly::Http }
5
+ describe ".base_url" do
6
+ context "with version 'vTest0'" do
7
+ subject { http.base_url }
8
+ before { Singly.version = "vTest0" }
9
+ it { should == "https://api.singly.com/vTest0" }
10
+ end
11
+ context "with version 'vTest1'" do
12
+ subject { http.base_url }
13
+ before { Singly.version = "vTest1" }
14
+ it { should == "https://api.singly.com/vTest1" }
15
+ end
16
+ end
17
+ describe ".fetch" do
18
+ context "with timeout" do
19
+ let(:timed_out_response) { Typhoeus::Response.new(return_code: :operation_timedout) } # Yeah, this is kinda
20
+ before { Typhoeus::Request.stub(:send).with(any_args).and_return(timed_out_response)} # fragile, but how do
21
+ it "should raise timeout error" do # I otherwise enforce
22
+ expect{ http.fetch(:get, "/any_damn_thing") }.to raise_error(Singly::TimeoutError) # a real timeout?
23
+ end
24
+ end
25
+ context "with api error" do
26
+ it "should raise api error" do
27
+ expect {
28
+ VCR.use_cassette "http_fetch_with_api_error" do
29
+ http.fetch(:get, "/no_such_endpoint")
30
+ end
31
+ }.to raise_error(Singly::ApiError)
32
+ end
33
+ end
34
+ context "with json response" do
35
+ subject {
36
+ VCR.use_cassette "http_fetch_with_json_response" do
37
+ http.fetch(:get, "/services")
38
+ end
39
+ }
40
+ let(:known_services) { ["fitbit", "gcontacts", "zeo", "foursquare", "meetup", "smugmug", "github", "dwolla", "yahoo", "runkeeper", "twitter", "google", "gdocs", "bodymedia", "dropbox", "37signals", "stocktwits", "yammer", "linkedin", "gplus", "picasa", "soundcloud", "gcal", "paypal", "tumblr", "rdio", "tout", "flickr", "youtube", "wordpress", "withings", "reddit", "imgur", "gmail", "instagram", "klout", "facebook", "shutterfly"] }
41
+ it { (subject.keys - known_services).should be_empty }
42
+ end
43
+ context "with non-json response" do
44
+ subject {
45
+ VCR.use_cassette "http_fetch_with_non_json_response" do
46
+ http.fetch(:get, "/enoch") # /enoch is the endpoint used internally at singly to check
47
+ end # service health. It is not documented and likely to change.
48
+ } # But for the purposes of testing non-json responses without
49
+ it { should == "true" } # having to supply auth params, it's perfect.
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Singly::Logger do
4
+ class DummyLogger
5
+ include Singly::Logger
6
+ end
7
+ describe "#log" do
8
+ before { Singly.verbose = true }
9
+ let(:lumberjack) { DummyLogger.new }
10
+ context "without Rails" do
11
+ before { lumberjack.should_receive(:puts).with("[singly] I'm a lumberjack and I don't care") }
12
+ it "should puts the message" do
13
+ lumberjack.log("I'm a lumberjack and I don't care")
14
+ end
15
+ end
16
+ context "with Rails" do
17
+ let(:logger) { double(:logger) }
18
+ before {
19
+ class Rails
20
+ def self.logger
21
+ logger
22
+ end
23
+ end
24
+ }
25
+ before { Rails.should_receive(:logger).and_return(logger) }
26
+ before { logger.should_receive(:info).with("[singly] I'm a lumberjack and I don't care") }
27
+ it "should log the message in rails" do
28
+ lumberjack.log("I'm a lumberjack and I don't care")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Singly do
4
+ describe ".client_id" do
5
+ context "should return client id" do
6
+ subject { Singly.client_id }
7
+ before { Singly.client_id = "a_client_id" }
8
+ it { should == "a_client_id" }
9
+ end
10
+ end
11
+ describe ".client_secret" do
12
+ context "should return client secret" do
13
+ subject { Singly.client_secret }
14
+ before { Singly.client_secret = "a_client_secret" }
15
+ it { should == "a_client_secret" }
16
+ end
17
+ end
18
+ describe ".verbose" do
19
+ context "should return if logging is enabled or not" do
20
+ subject { Singly.verbose }
21
+ before { Singly.verbose = true }
22
+ it { should == true }
23
+ end
24
+ end
25
+ describe ".timeout" do
26
+ context "should return timeout config" do
27
+ subject { Singly.timeout }
28
+ before { Singly.timeout = 2500 }
29
+ it { should == 2500 }
30
+ end
31
+ end
32
+ describe ".account" do
33
+ context "should provide a new account" do
34
+ subject { Singly.account("an_access_token", "an_account_id") }
35
+ it { subject.class.should == Singly::Account }
36
+ it { subject.access_token.should == "an_access_token" }
37
+ it { subject.account_id.should == "an_account_id" }
38
+ end
39
+ end
40
+ describe ".auth" do
41
+ context "should provide a new auth endpoint" do
42
+ subject { Singly.auth }
43
+ it { subject.class.should == Singly::Auth }
44
+ end
45
+ end
46
+ describe ".multi" do
47
+ context "should provide a new multi endpoint" do
48
+ subject { Singly.multi(["services/facebook", "auth/instagram/apply"]) }
49
+ it { subject.class.should == Singly::Multi }
50
+ it { subject.query_params[:urls].should == "services/facebook,auth/instagram/apply" }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ require 'singly'
2
+ require 'vcr'
3
+
4
+ RSpec.configure do |config|
5
+ config.color_enabled = true
6
+
7
+ defaults = { # Restore defaults before each test to
8
+ version: Singly.version, # avoid transitive failures
9
+ verbose: Singly.verbose,
10
+ timeout: Singly.timeout,
11
+ client_id: Singly.client_id,
12
+ client_secret: Singly.client_secret
13
+ }
14
+ config.before(:each) do
15
+ Singly.version = defaults[:version]
16
+ Singly.verbose = defaults[:verbose]
17
+ Singly.timeout = defaults[:timeout]
18
+ Singly.client_id = defaults[:client_id]
19
+ Singly.client_secret = defaults[:client_secret]
20
+ end
21
+ end
22
+
23
+ VCR.configure do |config|
24
+ config.cassette_library_dir = 'spec/vcr_cassettes'
25
+ config.hook_into :typhoeus
26
+ # config.allow_http_connections_when_no_cassette = true
27
+ end
@@ -0,0 +1,39 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.singly.com/v0/no_such_endpoint
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Typhoeus - https://github.com/typhoeus/typhoeus
12
+ response:
13
+ status:
14
+ code: 401
15
+ message: Unauthorized
16
+ headers:
17
+ Access-Control-Allow-Headers:
18
+ - Accept, Cache-Control, Pragma, User-Agent, Origin, X-Request, Referer, X-Requested-With,
19
+ Content-Type
20
+ Access-Control-Allow-Methods:
21
+ - GET, POST, OPTIONS, PUT, DELETE
22
+ Access-Control-Allow-Origin:
23
+ - ! '*'
24
+ Content-Type:
25
+ - application/json; charset=utf-8
26
+ Date:
27
+ - Sun, 17 Feb 2013 03:22:16 GMT
28
+ X-Powered-By:
29
+ - Express
30
+ Content-Length:
31
+ - '55'
32
+ Connection:
33
+ - keep-alive
34
+ body:
35
+ encoding: US-ASCII
36
+ string: ! '{"error":"This request requires a valid access_token."}'
37
+ http_version: '1.1'
38
+ recorded_at: Sun, 17 Feb 2013 03:22:15 GMT
39
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,102 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.singly.com/v0/services
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Typhoeus - https://github.com/typhoeus/typhoeus
12
+ response:
13
+ status:
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ Access-Control-Allow-Headers:
18
+ - Accept, Cache-Control, Pragma, User-Agent, Origin, X-Request, Referer, X-Requested-With,
19
+ Content-Type
20
+ Access-Control-Allow-Methods:
21
+ - GET, POST, OPTIONS, PUT, DELETE
22
+ Access-Control-Allow-Origin:
23
+ - ! '*'
24
+ Content-Type:
25
+ - application/json; charset=utf-8
26
+ Date:
27
+ - Sun, 17 Feb 2013 03:22:16 GMT
28
+ ETag:
29
+ - ! '"235545938"'
30
+ X-Powered-By:
31
+ - Express
32
+ Content-Length:
33
+ - '45214'
34
+ Connection:
35
+ - keep-alive
36
+ body:
37
+ encoding: US-ASCII
38
+ string: ! '{"fitbit":{"name":"Fitbit","desc":"Syncs devices, activity, sleep
39
+ and weight/bodyfat","key":"Consumer key","secret":"Consumer secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/fitbit.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/fitbit.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/fitbit.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/fitbit.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/fitbit.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/fitbit.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/fitbit.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/fitbit.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/fitbit.png"}],"sandbox":true,"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"activities","frequency":7200,"class":"personal"},{"name":"devices","frequency":86400,"class":"personal"},{"name":"fat","frequency":7200,"class":"personal"},{"name":"sleep","frequency":7200,"class":"personal"},{"name":"weight","frequency":86400,"class":"personal"}],"hasTestKeys":true},"gcontacts":{"name":"Google
40
+ Contacts","desc":"Syncs contacts from any Google account","key":"Client ID","secret":"Client
41
+ secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/gcontacts.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/gcontacts.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/gcontacts.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/gcontacts.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/gcontacts.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/gcontacts.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/gcontacts.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/gcontacts.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/gcontacts.png"}],"synclets":[{"name":"self","frequency":1700,"class":"core","note":"frequency
42
+ has to be < 30min to keep access token alive for media fetches for now, see
43
+ map.js TODO"},{"name":"contacts","frequency":86400,"class":"core"}],"hasTestKeys":true},"zeo":{"name":"zeo","desc":"Syncs
44
+ and archives average zqscore and historic sleep stats","key":"API Key","secret":"Secret
45
+ Key","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/zeo.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/zeo.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/zeo.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/zeo.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/zeo.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/zeo.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/zeo.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/zeo.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/zeo.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"sleep_stats","frequency":7200,"class":"personal"},{"name":"sleep_records","frequency":7200,"class":"personal"},{"name":"zq_scores","frequency":7200,"class":"personal"}],"hasTestKeys":true},"foursquare":{"name":"foursquare","desc":"Syncs
46
+ checkins, photos, and friends checkins","key":"Client ID","secret":"Client
47
+ Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/foursquare.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/foursquare.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/foursquare.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/foursquare.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/foursquare.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/foursquare.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/foursquare.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/foursquare.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/foursquare.png"}],"sandbox":true,"synclets":[{"frequency":86400,"name":"self","class":"core"},{"frequency":86400,"name":"friends","class":"core"},{"frequency":600,"name":"checkins","class":"personal"},{"frequency":300,"name":"recent","max":3600,"class":"social"},{"frequency":43200,"name":"photos","class":"personal"},{"frequency":86400,"name":"badges","class":"personal"}],"hasTestKeys":true},"meetup":{"name":"Meetup","desc":"Get
48
+ Meetup data","key":"Key","secret":"Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/meetup.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/meetup.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/meetup.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/meetup.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/meetup.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/meetup.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/meetup.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/meetup.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/meetup.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"checkins","frequency":3600,"class":"personal"},{"name":"groups","frequency":3600,"class":"personal"},{"name":"photos","frequency":3600,"class":"personal"},{"name":"events","frequency":3600,"class":"personal"}],"hasTestKeys":true},"smugmug":{"name":"SmugMug","desc":"Provides
49
+ authentication, proxy, photos and albums for SmugMug accounts.","key":"Client
50
+ ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/smugmug.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/smugmug.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/smugmug.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/smugmug.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/smugmug.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/smugmug.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/smugmug.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/smugmug.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/smugmug.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"photos","frequency":86400,"class":"personal"}],"hasTestKeys":false},"github":{"name":"GitHub","desc":"Syncs
51
+ friends, followers, issues, repo summary, received and generated events","key":"Client
52
+ ID","secret":"Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/github.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/github.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/github.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/github.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/github.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/github.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/github.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/github.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/github.png"}],"synclets":[{"frequency":86400,"name":"self","class":"core"},{"frequency":86400,"name":"users","class":"core"},{"frequency":3600,"name":"issues","class":"personal"},{"frequency":86400,"name":"repos","class":"personal"},{"frequency":3600,"name":"received","class":"social"},{"frequency":3600,"name":"events","class":"social"}],"hasTestKeys":true},"dwolla":{"name":"Dwolla","desc":"Only
53
+ provides authentication with and the basic profile for any Dwolla account.","key":"Key","secret":"Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/dwolla.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/dwolla.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/dwolla.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/dwolla.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/dwolla.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/dwolla.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/dwolla.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/dwolla.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/dwolla.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":true},"yahoo":{"name":"Yahoo
54
+ Account","desc":"Provides authentication, proxy and the basic profile for
55
+ any Yahoo account.","key":"Client ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/yahoo.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/yahoo.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/yahoo.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/yahoo.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/yahoo.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/yahoo.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/yahoo.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/yahoo.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/yahoo.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":false},"runkeeper":{"name":"RunKeeper
56
+ Health Graph","desc":"Connect to RunKeeper activities and devices","key":"Client
57
+ ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/runkeeper.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/runkeeper.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/runkeeper.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/runkeeper.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/runkeeper.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/runkeeper.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/runkeeper.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/runkeeper.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/runkeeper.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"fitness_activities","frequency":3600,"class":"personal"},{"name":"strength_activities","frequency":3600,"class":"personal"},{"name":"background_activities","frequency":3600,"class":"personal"},{"name":"records","frequency":86400,"class":"personal"},{"name":"street_team","frequency":86400,"class":"core"}],"hasTestKeys":true},"twitter":{"name":"Twitter","desc":"Syncs
58
+ tweets, mentions, timeline, friends, and followers (up to 1k of them).","key":"Consumer
59
+ Key","secret":"Consumer Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/twitter.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/twitter.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/twitter.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/twitter.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/twitter.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/twitter.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/twitter.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/twitter.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/twitter.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"friends","frequency":86400,"class":"core"},{"name":"followers","frequency":21600,"class":"core"},{"name":"favorites","frequency":600,"class":"personal"},{"name":"tweets","frequency":600,"class":"personal"},{"name":"timeline","frequency":120,"class":"social"},{"name":"related","frequency":7000,"class":"social"},{"name":"mentions","frequency":600,"class":"social"},{"name":"received_messages","frequency":600,"class":"personal","aka":"direct_messages"},{"name":"sent_messages","frequency":600,"class":"personal","aka":"direct_messages"}],"hasTestKeys":true},"google":{"name":"Google
60
+ Account","desc":"Only provides authentication with and the basic profile for
61
+ any Google account.","key":"Client ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/google.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/google.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/google.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/google.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/google.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/google.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/google.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/google.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/google.png"}],"synclets":[{"name":"self","frequency":9999999,"class":"core"}],"hasTestKeys":true},"gdocs":{"name":"Google
62
+ Documents","desc":"Access to Google Docs, sync''s the change feed","key":"Client
63
+ ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/google.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/google.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/google.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/google.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/google.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/google.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/google.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/google.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/google.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"changes","frequency":3600,"class":"personal"}],"hasTestKeys":true},"bodymedia":{"name":"BodyMedia","desc":"Indexes
64
+ the steps, calories, and sleep from an armband.","key":"Key","secret":"Shared
65
+ Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/bodymedia.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/bodymedia.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/bodymedia.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/bodymedia.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/bodymedia.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/bodymedia.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/bodymedia.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/bodymedia.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/bodymedia.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"steps_hour","frequency":86400,"class":"personal"},{"name":"burn_year","frequency":86400,"class":"personal"},{"name":"burn_day","frequency":43200,"class":"personal"},{"name":"sleep_year","frequency":86400,"class":"personal"},{"name":"sleep_day","frequency":43200,"class":"personal"}],"hasTestKeys":true},"dropbox":{"name":"Dropbox","desc":"Connect
66
+ to your Dropbox account","key":"Client ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/dropbox.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/dropbox.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/dropbox.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/dropbox.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/dropbox.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/dropbox.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/dropbox.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/dropbox.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/dropbox.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"files","frequency":86400,"class":"personal","aka":"folders"}],"hasTestKeys":true},"37signals":{"name":"37signals","desc":"Authentication
67
+ only","key":"Client ID","secret":"Client Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/37signals.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/37signals.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/37signals.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/37signals.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/37signals.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/37signals.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/37signals.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/37signals.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/37signals.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":true},"stocktwits":{"name":"StockTwits","desc":"Connect
68
+ to and authenticate with any StockTwits profile","key":"Consumer key","secret":"Consumer
69
+ secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/stocktwits.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/stocktwits.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/stocktwits.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/stocktwits.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/stocktwits.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/stocktwits.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/stocktwits.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/stocktwits.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/stocktwits.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"users","frequency":86400,"class":"core","aka":"following
70
+ followers"}],"hasTestKeys":true},"yammer":{"name":"Yammer","desc":"Sync messages,
71
+ users, and groups","key":"Client ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/yammer.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/yammer.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/yammer.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/yammer.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/yammer.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/yammer.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/yammer.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/yammer.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/yammer.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"messages","frequency":600,"class":"social"},{"name":"users","frequency":86400,"class":"core"},{"name":"groups","frequency":86400,"class":"core"}],"hasTestKeys":false},"linkedin":{"name":"LinkedIn","desc":"Syncs
72
+ connections, shares, and the network updates news feed.","key":"API Key","secret":"Secret
73
+ Key","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/linkedin.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/linkedin.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/linkedin.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/linkedin.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/linkedin.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/linkedin.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/linkedin.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/linkedin.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/linkedin.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"updates","frequency":3600,"class":"social"},{"name":"network","frequency":3600,"class":"core"},{"name":"connections","frequency":86400,"class":"core","freshInstead":"network"}],"hasTestKeys":true},"gplus":{"name":"Google
74
+ Plus","desc":"Authentication only","key":"Client ID","secret":"Client Secret","synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"activities","frequency":86400,"class":"personal"}],"icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/google.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/google.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/google.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/google.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/google.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/google.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/google.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/google.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/google.png"}],"hasTestKeys":true},"picasa":{"name":"Google
75
+ Picasa","desc":"Authenticate a Picasa User","key":"Client ID","secret":"Client
76
+ secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/picasa.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/picasa.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/picasa.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/picasa.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/picasa.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/picasa.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/picasa.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/picasa.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/picasa.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"photos","frequency":86400,"class":"personal","aka":"albums"}],"hasTestKeys":true},"soundcloud":{"name":"SoundCloud","desc":"Syncs
77
+ the user''s profile.","key":"Client ID","secret":"Client Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/soundcloud.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/soundcloud.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/soundcloud.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/soundcloud.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/soundcloud.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/soundcloud.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/soundcloud.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/soundcloud.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/soundcloud.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":true},"gcal":{"name":"Google
78
+ Calendar","desc":"Access to Google Calendar, sync''s the calendar list","key":"Client
79
+ ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/gcal.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/gcal.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/gcal.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/gcal.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/gcal.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/gcal.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/gcal.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/gcal.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/gcal.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"calendars","frequency":86400,"class":"personal"}],"hasTestKeys":true},"paypal":{"name":"PayPal","desc":"Authentication
80
+ only","key":"App ID","secret":"App secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/paypal.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/paypal.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/paypal.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/paypal.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/paypal.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/paypal.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/paypal.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/paypal.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/paypal.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":false},"tumblr":{"name":"Tumblr","desc":"Syncs
81
+ blogs followed, dashboard, and all posts.","key":"OAuth Consumer Key","secret":"Secret
82
+ Key","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/tumblr.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/tumblr.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/tumblr.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/tumblr.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/tumblr.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/tumblr.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/tumblr.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/tumblr.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/tumblr.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"following","frequency":86400,"class":"core"},{"name":"dashboard","frequency":600,"class":"social"},{"name":"posts","frequency":1200,"class":"personal"}],"hasTestKeys":true},"rdio":{"name":"Rdio","desc":"Syncs
83
+ following, collection, and activity.","key":"Key","secret":"Shared Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/rdio.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/rdio.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/rdio.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/rdio.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/rdio.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/rdio.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/rdio.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/rdio.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/rdio.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"following","frequency":600,"class":"core"},{"name":"collection","frequency":3600,"class":"personal"},{"name":"activity","frequency":3600,"class":"personal"}],"hasTestKeys":true},"tout":{"name":"Tout","desc":"Syncs
84
+ the user''s profile and videos.","key":"API Key","secret":"Secret Key","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/tout.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/tout.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/tout.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/tout.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/tout.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/tout.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/tout.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/tout.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/tout.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":true},"flickr":{"name":"Flickr","desc":"Syncs
85
+ photos","key":"Key","secret":"Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/flickr.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/flickr.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/flickr.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/flickr.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/flickr.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/flickr.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/flickr.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/flickr.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/flickr.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"photos","frequency":3600,"class":"personal"},{"name":"contacts","frequency":86400,"class":"personal"},{"name":"photos_feed","frequency":3600,"class":"social"}],"hasTestKeys":true},"youtube":{"name":"YouTube","desc":"Basic
86
+ authentication to any YouTube user","key":"Client ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/youtube.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/youtube.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/youtube.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/youtube.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/youtube.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/youtube.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/youtube.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/youtube.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/youtube.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"uploads","frequency":86400,"class":"personal"}],"hasTestKeys":true},"wordpress":{"name":"WordPress.com","desc":"Connect
87
+ to your activity and blogs on WordPress.com","key":"Client ID","secret":"Client
88
+ Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/wordpress.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/wordpress.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/wordpress.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/wordpress.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/wordpress.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/wordpress.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/wordpress.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/wordpress.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/wordpress.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"posts","frequency":3600,"class":"personal"},{"name":"feed","frequency":3600,"class":"social"}],"hasTestKeys":true},"withings":{"name":"Withings","desc":"Withings","key":"Client
89
+ ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/withings.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/withings.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/withings.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/withings.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/withings.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/withings.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/withings.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/withings.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/withings.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"measures","frequency":43200,"class":"personal"}],"hasTestKeys":true},"reddit":{"name":"reddit","desc":"Authentication
90
+ only","key":"App ID","secret":"App secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/reddit.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/reddit.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/reddit.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/reddit.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/reddit.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/reddit.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/reddit.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/reddit.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/reddit.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":false},"imgur":{"name":"imgur","desc":"Authentication
91
+ only","key":"App ID","secret":"App secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/imgur.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/imgur.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/imgur.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/imgur.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/imgur.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/imgur.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/imgur.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/imgur.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/imgur.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"}],"hasTestKeys":false},"gmail":{"name":"Gmail","desc":"Syncs
92
+ photos, contacts, and links.","key":"Client ID","secret":"Client secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/gmail.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/gmail.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/gmail.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/gmail.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/gmail.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/gmail.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/gmail.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/gmail.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/gmail.png"}],"synclets":[{"name":"self","frequency":3600,"class":"core"},{"name":"headers","frequency":3600,"class":"core"}],"hasTestKeys":true},"instagram":{"name":"Instagram","desc":"Syncs
93
+ photos, photo feed, and friends.","key":"CLIENT ID","secret":"CLIENT SECRET","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/instagram.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/instagram.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/instagram.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/instagram.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/instagram.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/instagram.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/instagram.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/instagram.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/instagram.png"}],"sandbox":true,"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"feed","frequency":600,"class":"social"},{"name":"follows","frequency":86400,"class":"core"},{"name":"updated","frequency":4200,"class":"personal"},{"name":"media","frequency":3600,"class":"personal"}],"hasTestKeys":true},"klout":{"name":"Klout","desc":"Connect
94
+ any Klout profile","key":"OAuth API Key","secret":"Shared Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/klout.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/klout.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/klout.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/klout.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/klout.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/klout.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/klout.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/klout.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/klout.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"influence","frequency":86400,"class":"core"},{"name":"topics","frequency":86400,"class":"core"}],"hasTestKeys":true},"facebook":{"name":"Facebook","desc":"Syncs
95
+ data for photos, wall, news feed, and friends.","key":"App ID","secret":"App
96
+ Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/facebook.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/facebook.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/facebook.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/facebook.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/facebook.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/facebook.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/facebook.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/facebook.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/facebook.png"}],"sandbox":true,"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"feed","frequency":3600,"class":"personal","aka":"feed_self
97
+ feed_others"},{"name":"checkins","frequency":1800,"class":"personal"},{"name":"friends","frequency":86400,"class":"core"},{"name":"home","frequency":600,"class":"social","aka":"home_photos"},{"name":"home_update","frequency":7000,"class":"social"},{"name":"photos","frequency":86400,"class":"personal","aka":"albums"},{"name":"likes","frequency":86400,"class":"personal","aka":"url_likes
98
+ stream_likes page_likes"},{"name":"pages","frequency":86400,"class":"personal"}],"hasTestKeys":true},"shutterfly":{"name":"Shutterfly","desc":"Authentication
99
+ only","key":"Application Id","secret":"Shared Secret","icons":[{"height":16,"width":16,"source":"http://assets.singly.com/service-icons/16px/shutterfly.png"},{"height":24,"width":24,"source":"http://assets.singly.com/service-icons/24px/shutterfly.png"},{"height":32,"width":32,"source":"http://assets.singly.com/service-icons/32px/shutterfly.png"},{"height":48,"width":48,"source":"http://assets.singly.com/service-icons/48px/shutterfly.png"},{"height":64,"width":64,"source":"http://assets.singly.com/service-icons/64px/shutterfly.png"},{"height":128,"width":128,"source":"http://assets.singly.com/service-icons/128px/shutterfly.png"},{"height":256,"width":256,"source":"http://assets.singly.com/service-icons/256px/shutterfly.png"},{"height":512,"width":512,"source":"http://assets.singly.com/service-icons/512px/shutterfly.png"},{"height":1024,"width":1024,"source":"http://assets.singly.com/service-icons/1024px/shutterfly.png"}],"synclets":[{"name":"self","frequency":86400,"class":"core"},{"name":"photos","frequency":86400,"class":"personal"},{"name":"albums","frequency":86400,"class":"personal"}],"hasTestKeys":true}}'
100
+ http_version: '1.1'
101
+ recorded_at: Sun, 17 Feb 2013 03:22:15 GMT
102
+ recorded_with: VCR 2.4.0