├── .ackrc ├── content ├── index.md ├── nginx.conf.erb ├── reference │ ├── resources │ │ ├── post │ │ │ ├── report.md │ │ │ ├── replies.md │ │ │ ├── lookup.md │ │ │ ├── stars.md │ │ │ ├── reposts.md │ │ │ ├── lifecycle.md │ │ │ ├── streams.md │ │ │ └── search.md │ │ ├── user │ │ │ ├── search.md │ │ │ ├── post-interactions.md │ │ │ ├── lookup.md │ │ │ ├── muting.md │ │ │ ├── blocking.md │ │ │ └── following.md │ │ ├── file │ │ │ ├── lookup.md │ │ │ ├── content.md │ │ │ └── lifecycle.md │ │ ├── message │ │ │ ├── lookup.md │ │ │ ├── lifecycle.md │ │ │ └── search.md │ │ ├── token │ │ │ └── index.md │ │ ├── index.md │ │ ├── user-stream │ │ │ └── lifecycle.md │ │ ├── channel │ │ │ ├── muting.md │ │ │ ├── search.md │ │ │ ├── lookup.md │ │ │ ├── lifecycle.md │ │ │ └── subscriptions.md │ │ ├── text-processor │ │ │ └── index.md │ │ ├── explore │ │ │ └── index.md │ │ ├── interaction │ │ │ └── index.md │ │ ├── stream-marker │ │ │ └── index.md │ │ ├── filter │ │ │ └── lifecycle.md │ │ ├── app-stream │ │ │ └── lifecycle.md │ │ └── config │ │ │ └── index.md │ ├── make-request │ │ ├── data-formats.md │ │ ├── rate-limits.md │ │ └── migrations.md │ ├── authentication │ │ ├── flows │ │ │ ├── sdk.md │ │ │ ├── app-access-token.md │ │ │ ├── password.md │ │ │ └── web.md │ │ └── authorize-with-appnet.md │ ├── other │ │ ├── oembed.md │ │ ├── web-intents.md │ │ └── feeds.md │ └── index.md ├── docs │ ├── guides │ │ ├── create-a-post.md │ │ ├── messaging.md │ │ ├── create-an-app.md │ │ ├── using-annotations.md │ │ └── send-a-broadcast.md │ └── index.md └── assets │ └── js │ └── app.js ├── static ├── images │ ├── button.png │ ├── docs-broadcast.png │ ├── docs-authentication.png │ ├── docs-broadcast@2x.png │ └── docs-authentication@2x.png └── css │ └── pygments.css ├── lib └── default.rb ├── layouts ├── partials │ ├── endpoints-tab.html │ ├── object-tab.html │ ├── buttons │ │ └── button.css │ ├── parameters.md │ ├── endpoints │ │ ├── text-processor.md │ │ ├── config.md │ │ ├── interaction.md │ │ ├── stream-marker.md │ │ ├── place.md │ │ ├── explore-stream.md │ │ ├── user-stream.md │ │ ├── token.md │ │ ├── filter.md │ │ ├── app-stream.md │ │ ├── message.md │ │ ├── file.md │ │ ├── post.md │ │ └── channel.md │ ├── parameters-typed.md │ ├── endpoint.md │ ├── top_nav.html │ └── reference_nav.html └── default.html ├── .gitignore ├── Guardfile ├── Gemfile ├── README.md ├── Rules └── config.yaml /.ackrc: -------------------------------------------------------------------------------- 1 | --ignore-dir=.git 2 | --ignore-dir=tmp 3 | --ignore-dir=output 4 | -------------------------------------------------------------------------------- /content/index.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Root of docs is [here](/docs/). 4 | -------------------------------------------------------------------------------- /static/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appdotnet/api-spec/HEAD/static/images/button.png -------------------------------------------------------------------------------- /lib/default.rb: -------------------------------------------------------------------------------- 1 | # All files in the 'lib' directory will be loaded 2 | # before nanoc starts compiling. 3 | -------------------------------------------------------------------------------- /static/images/docs-broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appdotnet/api-spec/HEAD/static/images/docs-broadcast.png -------------------------------------------------------------------------------- /static/images/docs-authentication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appdotnet/api-spec/HEAD/static/images/docs-authentication.png -------------------------------------------------------------------------------- /static/images/docs-broadcast@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appdotnet/api-spec/HEAD/static/images/docs-broadcast@2x.png -------------------------------------------------------------------------------- /layouts/partials/endpoints-tab.html: -------------------------------------------------------------------------------- 1 |
<%= render 'partials/endpoints/'+@for %>
-------------------------------------------------------------------------------- /static/images/docs-authentication@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appdotnet/api-spec/HEAD/static/images/docs-authentication@2x.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *~ 4 | .DS_Store 5 | *# 6 | *emacs.desktop* 7 | output 8 | tmp 9 | crash.log 10 | Gemfile.lock 11 | bin 12 | vendor 13 | .bundle 14 | local_config.yml 15 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard 'nanoc' do 5 | watch('config.yaml') # Change this to config.yaml if you use the old config file name 6 | watch('Rules') 7 | watch(%r{^(content|layouts|lib|static)/.*$}) 8 | end 9 | -------------------------------------------------------------------------------- /content/nginx.conf.erb: -------------------------------------------------------------------------------- 1 | <% if @site.config[:redirects] %> 2 | # Set up URL redirects 3 | <% @site.config[:redirects].each do |h| %> 4 | <% unless h[:from].include? '"' or h[:to].include? ';' %> 5 | rewrite "<%= h[:from] %>" "<%= h[:to] %>" redirect; 6 | <% end %> 7 | <% end %> 8 | <% end %> -------------------------------------------------------------------------------- /layouts/partials/object-tab.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | {::options parse_block_html="true" /} 7 |
8 | -------------------------------------------------------------------------------- /layouts/partials/buttons/button.css: -------------------------------------------------------------------------------- 1 | a.adn-button, a.adn-button:visited, a.adn-button:hover { 2 | background-color: #C75244; 3 | color: #FFFFFF; 4 | text-decoration: none; 5 | display: inline-block; 6 | font-size: 18px; 7 | line-height: 18px; 8 | padding: 10px 20px; 9 | border-radius: 18px; 10 | -webkit-border-radius: 18px; 11 | -moz-border-radius: 18px; 12 | } 13 | 14 | a.adn-button:hover { 15 | background-color: #CA5D4E; 16 | } -------------------------------------------------------------------------------- /layouts/partials/parameters.md: -------------------------------------------------------------------------------- 1 | #### <%= header %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | <% params.each do |param| %> 12 | 13 | 14 | 15 | 16 | <% end %> 17 | 18 |
NameDescription
<%= param[0] %><%= param[1] %>
-------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'nanoc', '3.6.4' 4 | gem 'adsf', '1.1.1' 5 | gem 'fssm', '0.2.10' 6 | gem 'kramdown', '1.1.0' 7 | gem 'coderay', '1.0.9' 8 | gem 'pygments.rb', '0.5.2' 9 | gem 'nokogiri', '1.6.1' 10 | gem 'rack', '1.5.2' 11 | gem 'colored', '1.2' 12 | gem 'cri', '2.3.0' 13 | gem 'posix-spawn', '0.3.6' 14 | gem 'yajl-ruby', '1.1.0' 15 | gem 'listen', '1.2.2' 16 | gem 'guard-nanoc', '1.0.1' 17 | gem 'rb-readline' 18 | gem 'w3c_validators' 19 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/text-processor.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
DescriptionMethodPathToken
Process textPOST/stream/0/text/processAny
-------------------------------------------------------------------------------- /layouts/partials/endpoints/config.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
DescriptionMethodPathToken
Retrieve the Configuration objectGET/stream/0/configNone
-------------------------------------------------------------------------------- /layouts/partials/endpoints/interaction.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
DescriptionMethodPathToken
Retrieve Interactions with the current UserGET/stream/0/users/me/interactionsUser
-------------------------------------------------------------------------------- /layouts/partials/endpoints/stream-marker.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
DescriptionMethodPathToken
Update a Stream MarkerPOST/stream/0/posts/markerUser
19 | -------------------------------------------------------------------------------- /layouts/partials/parameters-typed.md: -------------------------------------------------------------------------------- 1 | #### <%= header %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | <% params.each do |param| %> 14 | 15 | 16 | 17 | 18 | 19 | 20 | <% end %> 21 | 22 |
NameRequired?TypeDescription
<%= param[0] %><%= param[1].to_s.capitalize %><%= param[2] %><%= param[3] %>
23 | -------------------------------------------------------------------------------- /content/reference/resources/post/report.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Report" 3 | --- 4 | 5 | # Report 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Report a Post 11 | 12 | Report a post as spam. This will mute the author of the post and send a report to App.net. 13 | 14 | > If you are testing this endpoint, please send an email to [support@app.net](mailto:support@app.net) letting us know the account you are about to report. 15 | 16 | <%= general_params_note_for "post" %> 17 | 18 | <%= endpoint "POST", "posts/[post_id]/report", "User" %> 19 | 20 | <%= url_params [ 21 | ["post_id", "The id of the Post to report."] 22 | ]%> 23 | 24 | #### Example 25 | 26 | <%= curl_example(:post, "posts/#{get_id(:post)}/report", :post) %> 27 | -------------------------------------------------------------------------------- /layouts/partials/endpoint.md: -------------------------------------------------------------------------------- 1 | #### Endpoint 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <% if scope != '' %> 10 | 11 | <% end %> 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | <% if scope != '' %> 20 | 21 | <% end %> 22 | 23 | 24 |
MethodURLTokenScope
<%= method %><%= path %><%= token %><%= scope %>
-------------------------------------------------------------------------------- /content/reference/resources/user/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Search" 3 | --- 4 | 5 | # Search 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Search for Users 11 | 12 | Search the App.net userbase. 13 | 14 | <%= general_params_note_for "user" %> 15 | 16 | <%= endpoint "GET", "users/search", "Any" %> 17 | 18 | <%= query_params [ 19 | ["q","The search query. Supports @username or #tag searches as well as normal search terms. Searches username, display name, bio information. Does not search posts."], 20 | ["count","(Optional) The number of Users to return, up to a maximum of 200. Defaults to 20 if not specified."] 21 | ]%> 22 | 23 | #### Example 24 | 25 | <%= curl_example(:get, "users/search?q=%23api", :user, {:response => :paginated}) do |h| 26 | h["meta"]["count"] = 1 27 | h["data"][0]["pagination_id"] = "10000" 28 | end %> 29 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/place.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
DescriptionMethodPathToken
Retrieve a PlaceGET/stream/0/places/{factual_id}Any
Search for PlacesGET/stream/0/places/searchUser
25 | -------------------------------------------------------------------------------- /content/reference/resources/post/replies.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Post Replies" 3 | --- 4 | 5 | # Replies 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve the replies to a Post 11 | 12 | Retrieve all the [Posts](/reference/resources/post/) that are in the same thread as this post. The specified Post does not have to be the root of the conversation. Additionally, the specified Post will be included in the response at the appropriate place. 13 | 14 | **This endpoint would be more accurately named `stream/0/posts/{post_id}/thread` and may be renamed in a later API version.** 15 | 16 | <%= general_params_note_for "post" %> 17 | 18 | <%= pagination_note %> 19 | 20 | <%= endpoint "GET", "posts/[post_id]/replies", "Any" %> 21 | 22 | <%= url_params [ 23 | ["post_id","The id of a Post in the thread to retrieve."] 24 | ]%> 25 | 26 | #### Example 27 | 28 | <%= curl_example(:get, "posts/#{get_id(:post)}/replies", :post_reply, {:response => :paginated}) %> 29 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/explore-stream.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
DescriptionMethodPathToken
Retrieve all Explore StreamsGET/stream/0/posts/stream/exploreNone
Retrieve an Explore StreamGET/stream/0/posts/stream/explore/{slug}None
25 | -------------------------------------------------------------------------------- /content/reference/make-request/data-formats.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Data Formats" 3 | --- 4 | 5 | # Notes on data formats 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Dates 11 | 12 | Dates will be formatted as a **strict** subset of [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601). Dates are parseable by almost any ISO 8601 date parser or merely by parsing from position. All dates will be formatted as follows: 13 | 14 | `2012-12-31T13:22:55Z` 15 | 16 | where `2012` is the year, `12` represents December, `31` represents the 31st day of the month, `13` represents 1 PM, `22` minutes and `55` seconds past the hour. All times will be expressed in terms of UTC. 17 | 18 | This format was chosen to minimize ambiguity and edge cases in terms of parsing while maximizing readability of dates during 19 | development. 20 | 21 | ## Object IDs 22 | 23 | Object IDs will always be transferred as strings to avoid issues with with limitations of JavaScript integers. You can assume that object IDs are integers. 24 | -------------------------------------------------------------------------------- /layouts/partials/top_nav.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/user-stream.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
DescriptionMethodPathToken
Delete a User StreamDELETE/stream/0/users/me/streams/{connection_id}User
Delete a User Stream subscriptionDELETE/stream/0/users/me/streams/{connection_id}/{subscription_id}User
25 | -------------------------------------------------------------------------------- /content/reference/authentication/flows/sdk.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Authorize via App.net SDK" 3 | --- 4 | 5 | # Authorize via App.net SDK 6 | 7 | On iOS and Android, App.net provides SDKs to streamline the process of a user authenticating your app. This is also the easiest way for a new user to sign up for App.net via their mobile device. Both SDKs work in similar ways: 8 | 9 | 1. The developer integrates the SDK into their native app 10 | 2. The developer shows the user a "Log in" button 11 | 3. When the user taps that button, they are taken to the Official App.net App. 12 | 4. Once the user authorizes the developer's app, the Official App.net App returns the user to the developer's app with an access token. 13 | 14 | ## iOS 15 | 16 | The [iOS Login SDK](https://github.com/appdotnet/ADNLogin-SDK-iOS) is hosted on Github with complete installation instructions. 17 | 18 | ## Android 19 | 20 | The [Android Login SDK](https://github.com/appdotnet/ADNLogin-SDK-Android) is hosted on Github with complete installation instructions. 21 | -------------------------------------------------------------------------------- /content/reference/resources/post/lookup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Post Lookup" 3 | --- 4 | 5 | # Lookup 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve a Post 11 | 12 | Returns a specific [Post](/reference/resources/post/). 13 | 14 | <%= general_params_note_for "post" %> 15 | 16 | <%= endpoint "GET", "posts/[post_id]", "None" %> 17 | 18 | <%= url_params [ 19 | ["post_id","The id of the Post to retrieve."] 20 | ]%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:get, "posts/#{get_id(:post)}", :post) %> 25 | 26 | ## Retrieve multiple Posts 27 | 28 | Returns multiple Posts requested by id. At most 200 posts can be requested. 29 | 30 | <%= general_params_note_for "post" %> 31 | 32 | <%= endpoint "GET", "posts", "Any" %> 33 | 34 | <%= query_params [ 35 | ["ids","A comma separated list of ids of Posts to retrieve."] 36 | ]%> 37 | 38 | #### Example 39 | 40 | <%= curl_example(:get, "posts?ids=#{get_id(:post)},2", :post, {:response => :collection}) do |h| 41 | second = h["data"][0].clone() 42 | second["id"] = "2" 43 | h["data"].unshift(second) 44 | end %> 45 | -------------------------------------------------------------------------------- /content/reference/resources/user/post-interactions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Post Interactions" 3 | --- 4 | 5 | # Post Interactions 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## List Users who have reposted a Post 11 | 12 | List all the Users who have reposted a given Post. 13 | 14 | <%= general_params_note_for "user" %> 15 | 16 | <%= endpoint "GET", "posts/[post_id]/reposters", "Any" %> 17 | 18 | <%= url_params [ 19 | ["post_id","The id of the target Post."] 20 | ]%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:get, "posts/1/reposters", :user, {:response => :paginated}) do |h| 25 | h["data"][0]["pagination_id"] = "345" 26 | h["meta"]["more"] = true 27 | end %> 28 | 29 | ## List Users who have starred a Post 30 | 31 | List all the Users who have starred a given Post. 32 | 33 | <%= general_params_note_for "user" %> 34 | 35 | <%= endpoint "GET", "posts/[post_id]/stars", "Any" %> 36 | 37 | <%= url_params [ 38 | ["post_id","The id of the target post."] 39 | ]%> 40 | 41 | #### Example 42 | 43 | <%= curl_example(:get, "posts/1/stars", :user, {:response => :paginated}) do |h| 44 | h["data"][0]["pagination_id"] = "1356" 45 | h["meta"]["more"] = true 46 | end %> 47 | -------------------------------------------------------------------------------- /content/reference/resources/user/lookup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Lookup" 3 | --- 4 | 5 | # Lookup 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve a User 11 | 12 | Returns a specific User object. 13 | 14 | <%= general_params_note_for "user" %> 15 | 16 | <%= endpoint "GET", "users/[user_id]", "None" %> 17 | 18 | <%= url_params [ 19 | ["user_id","The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 20 | ]%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:get, "users/#{get_id(:user)}", :user) %> 25 | 26 | ## Retrieve multiple Users 27 | Returns multiple Users requested by id. At most 200 users can be requested. 28 | 29 | <%= general_params_note_for "user" %> 30 | 31 | <%= endpoint "GET", "users", "Any" %> 32 | 33 | <%= query_params [ 34 | ["ids","A comma separated list of User ids to retrieve."] 35 | ]%> 36 | 37 | #### Example 38 | 39 | <%= curl_example(:get, "users?ids=1,2", :user, {:response => :collection}) do |h| 40 | second = h["data"][0].clone() 41 | second["id"] = "2" 42 | h["data"].unshift(second) 43 | end %> 44 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/token.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
DescriptionMethodPathToken
Retrieve the current tokenGET/stream/0/tokenAny
Retrieve authorized User IDs for an appGET/stream/0/apps/me/tokens/user_idsApp
Retrieve authorized User tokens for an appGET/stream/0/apps/me/tokensApp
-------------------------------------------------------------------------------- /content/docs/guides/create-a-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create a Post" 3 | --- 4 | 5 | # Creating a Post via the API 6 | 7 | <%= access_token_required_note %> 8 | 9 | A [Post](/reference/resources/post) is the microblogging primitive of the App.net API. When a user creates a post, it appears in all of their follower's streams. Posts can have images, links, and annotations but at their simplest, they just contain a piece of text. 10 | 11 | ## Create a post 12 | 13 | The easiest way to create a post is to use [one of the API libraries](/docs/libraries). 14 | 15 | Using [adnpy](/docs/libraries#python) 16 | 17 | ~~~ python 18 | import adnpy 19 | 20 | # Set the default access token for API calls. 21 | adnpy.api.add_authorization_token('') 22 | 23 | # Create a post 24 | post = adnpy.api.create_post(data={'text':'Hello App.net from Python!'}) 25 | ~~~ 26 | 27 | Or with the [adn](/docs/libraries#ruby) Ruby gem: 28 | 29 | ~~~ ruby 30 | require 'adn' 31 | 32 | ADN.token = '' 33 | post = ADN::Post.send_post(:text => "Hello App.net from Ruby!") 34 | ~~~ 35 | 36 | If you want to send the equivalent broadcast from the API without using a library, use this curl command: 37 | 38 | <%= curl_example(:post, "posts", :none, {:data => {"text" => "Hello App.net from curl!"}}) %> 39 | -------------------------------------------------------------------------------- /content/reference/other/oembed.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "oEmbed" 3 | --- 4 | 5 | # oEmbed 6 | 7 | oEmbed is an open standard for turning a URL into an embeddable piece of content for your site. To find out more about oEmbed [read the spec](http://www.oembed.com/). The App.net oEmbed endpoint will return HTML snippets that you can include on your site. Right now it works for individual posts, and photos. 8 | 9 | 10 | ## oEmbed Endpoint 11 | 12 | Returns an oEmbed response for a given URL. 13 | 14 | <%= endpoint "GET", "oembed", "None", '', '' %> 15 | 16 | <%= url_params [ 17 | ["url", "A URL for a post or photo on App.net."] 18 | ]%> 19 | 20 | #### Example 21 | 22 | <% response = { 23 | "provider_url" => "https://app.net", 24 | "version" => "1.0", 25 | "author_url" => "https://alpha.app.net/mthurman", 26 | "title" => "join.app.net getting ready for the world w/ @dalton @berg @voidfiles @jhubball @aaronblyth @andrew @vinitlee @mark @mintz @barmstrong @laughingman @mikegreenspan @ben #joinus", 27 | "url" => "https://alpha.app.net/mthurman/post/1", 28 | "provider_name" => "App.net", 29 | "type" => "link", 30 | "html" => "...", 31 | "author_name" => "mthurman" 32 | } %> 33 | 34 | <%= curl_example(:get, "oembed?url=https://posts.app.net/1", response, {:path_prefix => "/"}) %> 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # developers.app.net 2 | 3 | This branch (new-docs) of the appdotnet/api-spec repo contains the source for [developers.app.net](http://developers.app.net/) and replaces the docs located on the master branch. 4 | 5 | This documentation can be compiled using [nanoc](http://nanoc.stoneship.org/). 6 | 7 | All submissions are welcome. To submit a change, fork this repo, commit your changes, and send us a [pull request](http://help.github.com/send-pull-requests/). 8 | 9 | ## Building the docs 10 | 11 | Ruby is required to build the site. 12 | 13 | To install nanoc and make sure you have all the necessary ruby gems, open a terminal in the root of the api-spec checkout and run 14 | 15 | $ bundle install 16 | 17 | To compile the docs for the first time, run 18 | 19 | $ bundle exec nanoc 20 | 21 | Nanoc compiles the site into static files living in `./output`. 22 | 23 | In general, the best way to work on the docs is like this: 24 | 25 | $ bundle exec nanoc view & 26 | $ bundle exec guard start 27 | 28 | Guard will run and auto-generate new HTML output when you edit Markdown files, and the nanoc built-in webserver will be available on http://localhost:3000/ 29 | 30 | If you want to learn more about using nanoc, view the [nanoc documentation](http://nanoc.stoneship.org/docs/1-introduction/). 31 | -------------------------------------------------------------------------------- /Rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # A few helpful tips about the Rules file: 4 | # 5 | # * The string given to #compile and #route are matching patterns for 6 | # identifiers--not for paths. Therefore, you can’t match on extension. 7 | # 8 | # * The order of rules is important: for each item, only the first matching 9 | # rule is applied. 10 | # 11 | # * Item identifiers start and end with a slash (e.g. “/about/” for the file 12 | # “content/about.html”). To select all children, grandchildren, … of an 13 | # item, use the pattern “/about/*/”; “/about/*” will also select the parent, 14 | # because “*” matches zero or more characters. 15 | 16 | compile '/assets/js/*' do 17 | filter :erb 18 | end 19 | 20 | compile '/static/*' do 21 | end 22 | 23 | compile '/nginx' do 24 | filter :erb, :trim_mode =>"<>" 25 | end 26 | 27 | compile '*' do 28 | if item.binary? 29 | # don’t filter binary items 30 | else 31 | filter :erb 32 | filter :kramdown, :toc_levels => [2], :enable_coderay => false 33 | filter :colorize_syntax, :default_colorizer => :pygmentsrb, :linenos => 'inline' 34 | layout 'default' 35 | end 36 | end 37 | 38 | route '/nginx' do 39 | '/nginx.conf' 40 | end 41 | 42 | route '/static/*' do 43 | '/assets'+item.identifier[7..-2] 44 | end 45 | 46 | route '/assets/js/*' do 47 | item.identifier.chop + '.' + item[:extension] 48 | end 49 | 50 | route '*' do 51 | if item.binary? 52 | # Write item with identifier /foo/ to /foo.ext 53 | item.identifier.chop + '.' + item[:extension] 54 | else 55 | # Write item with identifier /foo/ to /foo/index.html 56 | item.identifier + 'index.html' 57 | end 58 | end 59 | 60 | layout '*', :erb 61 | -------------------------------------------------------------------------------- /content/reference/resources/file/lookup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "File Lookup" 3 | --- 4 | 5 | # Lookup 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve a File 11 | 12 | Returns a specific [File](/reference/resources/file/). 13 | 14 | <%= general_params_note_for "file" %> 15 | 16 | <%= endpoint "GET", "files/[file_id]", "Varies"%> 17 | 18 | <%= file_token_reminder %> 19 | 20 | <%= url_params [ 21 | ["file_id", "The id of the File to retrieve."] 22 | ]%> 23 | 24 | #### Example 25 | 26 | <%= curl_example(:get, "files/1", :file) %> 27 | 28 | ## Retrieve multiple Files 29 | 30 | Returns multiple Files requested by id. At most 200 files can be requested. Files which do not exist or which the requesting user does not have authorization to view will not be returned. 31 | 32 | <%= general_params_note_for "file" %> 33 | 34 | <%= endpoint "GET", "files", "User", "files"%> 35 | 36 | <%= file_token_reminder %> 37 | 38 | <%= query_params [ 39 | ["ids", "A comma separated list of File ids to retrieve."] 40 | ]%> 41 | 42 | #### Example 43 | 44 | In the following example, file 6502 is omitted because it doesn't exist or we don't have permission to view it. 45 | 46 | <%= curl_example(:get, "files?ids=1,2,6502", :file, {:response => :collection}) do |h| 47 | second = h["data"][0].clone() 48 | second["id"] = "2" 49 | h["data"].unshift(second) 50 | end %> 51 | 52 | ## Retrieve my Files 53 | 54 | Returns a stream of all Files the current user has created. 55 | 56 | <%= general_params_note_for "file" %> 57 | 58 | <%= pagination_note %> 59 | 60 | <%= endpoint "GET", "users/me/files", "User", "files"%> 61 | 62 | #### Example 63 | 64 | <%= curl_example(:get, "users/me/files", :file, {:response => :paginated}) %> 65 | -------------------------------------------------------------------------------- /content/reference/authentication/flows/app-access-token.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "App Access Token Flow" 3 | --- 4 | 5 | # App Access Token Flow 6 | 7 | * TOC 8 | {:toc} 9 | 10 | The App Access Token Flow is used to request a token that is tied to your application instead of a specific user. **App access tokens cannot be distributed and must only be used from a server. You should consider them secret.** If you would like a client (i.e. mobile) application to use an app access token, that app must connect to a server you control that stores the app access token. 11 | 12 | To retrieve an app access token, your app must make the following request: 13 | 14 | POST https://account.app.net/oauth/access_token 15 | 16 | with URL-encoded POST body: 17 | 18 | client_id=[your client ID] 19 | &client_secret=[your client secret] 20 | &grant_type=client_credentials 21 | 22 | Example: 23 | 24 | <%= curl_example(:post, "access_token", :none, { 25 | :subdomain => "account", 26 | :path_prefix => "/oauth/", 27 | :pretty_json => false, 28 | :token => nil, 29 | :content_type => nil, 30 | :data => { 31 | "grant_type" => "client_credentials", 32 | "client_id" => "[your client_id]", 33 | "client_secret" => "[your client secret]", 34 | } 35 | }) %> 36 | 37 | 38 | > We also accept the `client_id` and `client_secret` parameters via the Authorization header, as described in [section 2.3.1 of the OAuth 2 spec](http://tools.ietf.org/html/rfc6749#section-2.3.1). 39 | 40 | App.net will respond with a JSON-encoded token: 41 | 42 | {"access_token": "[app access token]", "token": {...Token object...}} 43 | 44 | You can use this access_token to make authenticated calls to the App.net API on behalf of your app. 45 | -------------------------------------------------------------------------------- /content/reference/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "App.net API Reference" 3 | --- 4 | # App.net API Reference 5 | 6 | These pages contain the complete specification of how the App.net API works. We try to follow standard practices to make our API easy to use from one of our [client libraries](/docs/libraries/) or from any normal HTTP client. 7 | 8 | ## Authentication 9 | 10 | We use the [OAuth 2.0 protocol](http://tools.ietf.org/html/rfc6749) to authenticate clients to the API. There are multiple ways to get a token to a user's account. Please read our [Authentication Overview](/reference/authentication/) to choose the right one for your app. 11 | 12 | ## Responses 13 | 14 | Our [API responses](/reference/make-request/responses/) are always JSON encoded. We use HTTP status codes to indicate success or failures. 15 | 16 | ## Migrations 17 | 18 | From time to time, we'll need to change the API. If we change the behavior of an endpoint or remove a field, we will provide a migration so clients can opt into the new behavior when their code is updated. [Migrations](/reference/make-request/migrations) are our way of versioning the App.net API. They allow your app the flexibility to control which version of the API it uses on a per request or global basis. 19 | 20 | ## Rate Limits 21 | 22 | In order to ensure a high quality of service and prevent abuse, our API is rate limited. We use standard HTTP headers and status codes to rate limit requests. For more information (and to view the current rate limits), please see the [Rate Limits documentation](/reference/make-request/rate-limits/). 23 | 24 | ## Errors 25 | 26 | If there is an error, we return an [HTTP status code](/reference/make-request/responses/#possible-http-status-codes) and a JSON response describing it. 27 | 28 | -------------------------------------------------------------------------------- /content/reference/resources/message/lookup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Message Lookup" 3 | --- 4 | 5 | # Lookup 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve a Message 11 | 12 | Returns a specific [Message](/reference/resources/message/). 13 | 14 | *You can always retrieve a message you created even if you are no longer able to view the rest of the Channel anymore.* 15 | 16 | <%= general_params_note_for "message" %> 17 | 18 | <%= endpoint "GET", "channels/[channel_id]/messages/[message_id]", "Any" %> 19 | 20 | <%= url_params [ 21 | ["channel_id", "The id of the Channel containing the Message."], 22 | ["message_id", "The id of the Message to retrieve."] 23 | ]%> 24 | 25 | #### Example 26 | 27 | <%= curl_example(:get, "channels/1/messages/1", :message) %> 28 | 29 | ## Retrieve multiple Messages 30 | 31 | Returns multiple Messages requested by id. At most 200 messages can be requested. Messages may be requested from more than one channel at a time. Messages which do not exist or which the requesting user does not have authorization to view will not be returned. 32 | 33 | <%= general_params_note_for "message" %> 34 | 35 | <%= endpoint "GET", "channels/messages", "Any" %> 36 | 37 | <%= query_params [ 38 | ["ids", "A comma separated list of ids of the Messages to retrieve."] 39 | ]%> 40 | 41 | #### Example 42 | 43 | <%= curl_example(:get, "channels/messages?ids=1,2", :message, {:response => :collection}) %> 44 | 45 | ## Retrieve my Messages 46 | 47 | Retrieve a stream of the Messages the current user has created. 48 | 49 | <%= general_params_note_for "message" %> 50 | 51 | <%= pagination_note %> 52 | 53 | <%= endpoint "GET", "users/me/messages", "User", "public_messages or messages" %> 54 | 55 | #### Example 56 | 57 | <%= curl_example(:get, "users/me/messages", :message, {:response => :paginated}) %> 58 | -------------------------------------------------------------------------------- /content/reference/resources/token/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Token" 3 | --- 4 | 5 | # Token 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve current token 11 | 12 | Returns info about the current [OAuth access token](/reference/authentication/#access-tokens). If the token is a user token the response will include a [User](/reference/resources/user/) object. 13 | 14 | <%= endpoint "GET", "token", "Any" %> 15 | 16 | #### Example (App Token) 17 | 18 | <%= curl_example(:get, "token", :user_token, {:token => ""}) %> 19 | 20 | #### Example (User Token) 21 | 22 | <%= curl_example(:get, "token", :user_token) %> 23 | 24 | 25 | ## Deauthorize current token 26 | 27 | Deauthorize the current [OAuth access token](/reference/authentication/#access-tokens). This works for User tokens and App tokens. 28 | 29 | <%= endpoint "DELETE", "token", "Any" %> 30 | 31 | #### Example 32 | 33 | Requested with a user access token: 34 | 35 | <%= curl_example(:delete, "token", :user_token) %> 36 | 37 | ## Retrieve authorized User IDs for an app 38 | 39 | Returns a list of ids of Users that have authorized an app. Must be requested using an [app access token](/reference/authentication/#access-tokens). 40 | 41 | <%= endpoint "GET", "apps/me/tokens/user_ids", "App" %> 42 | 43 | #### Example 44 | 45 | <%= curl_example(:get, "apps/me/tokens/user_ids", ["2", "3"], {:token => ""}) %> 46 | 47 | ## Retrieve authorized User tokens for an app 48 | 49 | Returns a list of User tokens corresponding to an app token. Must be requested using an [app access token](/reference/authentication/#access-tokens). 50 | 51 | <%= pagination_note %> 52 | 53 | <%= endpoint "GET", "apps/me/tokens", "App" %> 54 | 55 | #### Example 56 | 57 | <%= curl_example(:get, "apps/me/tokens", :user_token, {:response => :paginated, :token => ""}) do |h| 58 | h["data"][0]["pagination_id"] = "10723" 59 | end %> 60 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/filter.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
DescriptionMethodPathToken
Create a FilterPOST/stream/0/filtersUser
Retrieve a FilterGET/stream/0/filters/{filter_id}User
Update a FilterPUT/stream/0/filters/{filter_id}User
Delete a FilterDELETE/stream/0/filters/{filter_id}User
Get the current User's FiltersGET/stream/0/filtersUser
Delete the current User's FiltersDELETE/stream/0/filtersUser
49 | -------------------------------------------------------------------------------- /content/reference/resources/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Resources" 3 | --- 4 | 5 | # Resources 6 | 7 | * TOC 8 | {:toc} 9 | 10 | The App.net API is a JSON API. 11 | 12 | Guiding principles are: 13 | 14 | * Always return JSON. If you are using JSONP, the returned JSON will be wrapped in a function call. 15 | * Utilize HTTP error codes and methods. 16 | * In general, required parameters are in URLs; optional parameters are specified in the query string. **This is not always the case.** 17 | * If we need complex data structures from you, you should send them as a JSON string. We don't need any more conventions for putting arrays and dictionaries directly into URL-encoded GET/POST values. 18 | * We follow a convention of including the API version number in the resource path. The current API version is version 0. 19 | 20 | ## Hostname 21 | Please use https://alpha-api.app.net/ to access the APIs. 22 | 23 | ## User 24 | 25 | <%= render 'partials/endpoints/user' %> 26 | 27 | ## Post 28 | 29 | <%= render 'partials/endpoints/post' %> 30 | 31 | ## Channel 32 | 33 | <%= render 'partials/endpoints/channel' %> 34 | 35 | ## Message 36 | 37 | <%= render 'partials/endpoints/message' %> 38 | 39 | ## File 40 | 41 | <%= render 'partials/endpoints/file' %> 42 | 43 | ## App Stream 44 | 45 | <%= render 'partials/endpoints/app-stream' %> 46 | 47 | ## User Stream 48 | 49 | <%= render 'partials/endpoints/user-stream' %> 50 | 51 | ## Filter 52 | 53 | <%= render 'partials/endpoints/filter' %> 54 | 55 | ## Interaction 56 | 57 | <%= render 'partials/endpoints/interaction' %> 58 | 59 | ## Stream Marker 60 | 61 | <%= render 'partials/endpoints/stream-marker' %> 62 | 63 | ## Text Processor 64 | 65 | <%= render 'partials/endpoints/text-processor' %> 66 | 67 | ## Token 68 | 69 | <%= render 'partials/endpoints/token' %> 70 | 71 | ## Place 72 | 73 | <%= render 'partials/endpoints/place' %> 74 | 75 | ## Explore Stream 76 | 77 | <%= render 'partials/endpoints/explore-stream' %> 78 | 79 | ## Configuration 80 | 81 | <%= render 'partials/endpoints/config' %> 82 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/app-stream.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
DescriptionMethodPathToken
Create an App StreamPOST/stream/0/streamsApp
Retrieve an App StreamGET/stream/0/streams/{stream_id}App
Update an App StreamPUT/stream/0/streams/{stream_id}App
Delete an App StreamDELETE/stream/0/streams/{stream_id}App
Retrieve all App Streams for the current TokenGET/stream/0/streamsApp
Delete all App Streams for the current TokenDELETE/stream/0/streamsApp
49 | -------------------------------------------------------------------------------- /content/reference/resources/user-stream/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Stream Lifecycle" 3 | --- 4 | 5 | # User Stream Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Delete a User Stream 11 | 12 | Delete a [User Stream](/reference/resources/user-stream/). The User Stream must belong to the current token. It disconnects any sockets with this User Stream open and returns an HTTP 204 No Content on success. 13 | 14 | If you'd like your user stream to be automatically deleted when you disconnect from it, please add the [`auto_delete=1`](/reference/resources/user-stream/#limits) query string parameter when you create the user stream. 15 | 16 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 17 | 18 | <%= endpoint "DELETE", "users/me/streams/[connection_id]", "User" %> 19 | 20 | <%= url_params [ 21 | ["connection_id", "The connection id of the User Stream to delete."] 22 | ]%> 23 | 24 | ### Example 25 | 26 | <%= curl_example(:delete, "streams/sxousNClc4Cq12du3f6GTZXNUvaHoJnFnjdOt6fH2xhJolPdDfR3rOxxjdPfPOIf", "204 No Content", { 27 | :response => :raw 28 | }) %> 29 | 30 | 31 | ## Delete a User Stream subscription 32 | 33 | Delete a subscription of a [User Stream](/reference/resources/user-stream/). The User Stream must belong to the current token. It returns an HTTP 204 No Content on success. 34 | 35 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 36 | 37 | <%= endpoint "DELETE", "users/me/streams/[connection_id]/[subscription_id]", "User" %> 38 | 39 | <%= url_params [ 40 | ["connection_id", "The connection id of the User Stream the subscription belongs to."], 41 | ["subscription_id", "The subscription id of the subscription to cancel"] 42 | ]%> 43 | 44 | ### Example 45 | 46 | <%= curl_example(:delete, "streams/sxousNClc4Cq12du3f6GTZXNUvaHoJnFnjdOt6fH2xhJolPdDfR3rOxxjdPfPOIf/bf42ca05-e67e-4e26-8bd0-8b042dd5b04c", "204 No Content", { 47 | :response => :raw 48 | }) %> 49 | -------------------------------------------------------------------------------- /content/reference/authentication/authorize-with-appnet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Web Flow Integration Guide" 3 | --- 4 | 5 | # Web Flow Integration Guide 6 | 7 | Now that you've identified which [web flow](/reference/authentication/flows/web/) to use with your app, it's time to expose this to end users. 8 | 9 | * TOC 10 | {:toc} 11 | 12 | ## Authorize With App.net Button 13 | 14 | The easiest way to integrate a web flow into your app is through an "Authorize with App.net" Button, which allows current App.net users to enjoy the ease of authorizing your app in two clicks. Less means more, as they'll be able to start using your app even faster. 15 | 16 | As an added benefit, this button will also allow new users to sign up for a free account and then authorize your app. 17 | 18 | ### Benefits 19 | 20 | 1. **It's easy**: Add an Authorize with App.net button to your site in seconds. 21 | 1. **It's beautiful**: The minimal style of the button is versatile and users will recognize the App.net branding. 22 | 1. **It's useful**: Your potential users can either sign up or sign in to your app with the same button. 23 | 24 | ### Implementation 25 | 26 | To implement the button on your site, you must: 27 | 28 | 1. Build [Your authentication URL](/reference/authentication/flows/web/). 29 | 1. Replace the variables inside the brackets 30 | 1. Copy and paste the snippet below into your HTML where you want the button to show up 31 | 32 | 33 | ~~~html 34 | Authorize with App.net 35 | ~~~ 36 | 37 | If you do everything correctly you should see a button like this: 38 | 39 | ![example button](/assets/images/button.png) 40 | 41 | ### Best Practices 42 | 43 | We suggest that you put the following copy directly above or below the button: 44 | 45 | An App.net account is required to use [Your App Name]. You can create an account and sign in by clicking this button. -------------------------------------------------------------------------------- /content/reference/resources/channel/muting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Channel Muting" 3 | --- 4 | 5 | # Channel Muting 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Get current user's muted Channels 11 | 12 | Retrieve a list of the channels the current user has muted. A user cannot be [auto-subscribed](/docs/guides/messaging/#subscriptions) to muted channels. 13 | 14 | This endpoint is **not** paginated and does **not** respond to the [general channel parameters](/reference/resources/channel/#general-parameters). 15 | 16 | <%= endpoint "GET", "users/me/channels/muted", "User", "public_messages
or messages"%> 17 | 18 | #### Example 19 | 20 | <%= curl_example(:get, "users/me/channels/muted", :channel, {:response => :collection}) do |h| 21 | h["data"][0]["you_muted"] = true 22 | end %> 23 | 24 | ## Mute a Channel 25 | 26 | Mute a Channel. If a user doesn't want to see a channel until there is a new message, they should [unsubscribe from the channel](/reference/resources/channel/subscriptions/#unsubscribe-from-a-channel) instead of muting it. If a user mutes a channel, they will automatically be unsubscribed from it and cannot be [auto-subscribed](/docs/guides/messaging/#subscriptions) to it. 27 | 28 | <%= general_params_note_for "channel" %> 29 | 30 | <%= endpoint "POST", "channels/[channel_id]/mute", "User", "public_messages or messages"%> 31 | 32 | <%= url_params [ 33 | ["channel_id", "The id of the Channel to mute."] 34 | ]%> 35 | 36 | #### Example 37 | 38 | <%= curl_example(:post, "channels/1/mute", :channel) do |h| 39 | h["data"]["you_muted"] = true 40 | h["data"]["you_subscribed"] = false 41 | end %> 42 | 43 | ## Unmute a Channel 44 | 45 | Unmute a Channel. This allows you to be resubscribed to the channel (but it does not happen automatically). 46 | 47 | <%= general_params_note_for "channel" %> 48 | 49 | <%= endpoint "DELETE", "channels/[channel_id]/mute", "User", "public_messages or messages"%> 50 | 51 | <%= url_params [ 52 | ["channel_id", "The id of the Channel to unmute."] 53 | ]%> 54 | 55 | #### Example 56 | 57 | <%= curl_example(:delete, "channels/1/mute", :channel) do |h| 58 | h["data"]["you_muted"] = false 59 | h["data"]["you_subscribed"] = false 60 | end %> 61 | -------------------------------------------------------------------------------- /content/reference/resources/post/stars.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Stars" 3 | --- 4 | 5 | # Stars 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Star a Post 11 | 12 | Save a given Post to the current User's stars. This is just a "save" action, not a sharing action. A User's stars are visible to others, but they are not automatically added to your followers' streams. 13 | 14 | *A repost cannot be starred. Please star the parent Post.* 15 | 16 | <%= general_params_note_for "post" %> 17 | 18 | <%= endpoint "POST", "posts/[post_id]/star", "User", "write_post" %> 19 | 20 | <%= url_params [ 21 | ["post_id", "The id of the Post to star."] 22 | ]%> 23 | 24 | #### Example 25 | 26 | <%= curl_example(:get, "posts/#{get_id(:post)}/star", :post) do |h| 27 | h["data"]["num_stars"] += 1 28 | h["data"]["you_starred"] = true 29 | end %> 30 | 31 | ## Unstar a Post 32 | 33 | Remove a Star from a Post. 34 | 35 | <%= general_params_note_for "post" %> 36 | 37 | <%= endpoint "DELETE", "posts/[post_id]/star", "User", "write_post" %> 38 | 39 | <%= url_params [ 40 | ["post_id", "The id of the Post to unstar."] 41 | ]%> 42 | 43 | #### Example 44 | 45 | <%= curl_example(:delete, "posts/#{get_id(:post)}/star", :post) do |h| 46 | h["data"]["you_starred"] = false 47 | end %> 48 | 49 | ## Retrieve Posts starred by a User 50 | 51 | Get the most recent [Posts](/reference/resources/post/) starred by a specific [User](/reference/resources/user/) in reverse post order. Stars are a way for Users to save posts without rebroadcasting the Post to their followers. 52 | 53 | <%= general_params_note_for "post" %> 54 | 55 | <%= pagination_note %> 56 | 57 | <%= endpoint "GET", "users/[user_id]/stars", "None" %> 58 | 59 | <%= url_params [ 60 | ["user_id", "The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 61 | ]%> 62 | 63 | *See [General Parameters](/reference/resources/post/#general-parameters) for optional parameters you can use with this query.* 64 | 65 | #### Example 66 | 67 | <%= curl_example(:get, "users/#{get_id(:user)}/stars", :post, {:response => :paginated}) do |h| 68 | h["data"][0]["num_stars"] += 1 69 | h["data"][0]["you_starred"] = true 70 | end %> -------------------------------------------------------------------------------- /content/reference/resources/text-processor/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Text Processor" 3 | --- 4 | 5 | # Text Processor 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Process text 11 | 12 | When a request is made to [create a Post](/reference/resources/post/lifecycle/#create-a-post) or [Message](/reference/resources/message/lifecycle/#create-a-message), or [update a User profile](/reference/resources/user/profile/#update-a-user) description, the provided body text is processed for [entities](/reference/meta/entities). You can use this endpoint to test how App.net will parse text for entities as well as render text as html. This endpoint must always be called with a JSON body as documented under [Post creation](/reference/resources/post/lifecycle/#create-a-post). Calls to this endpoint will not create or update any objects in App.net. 13 | 14 | <%= endpoint "POST", "text/process", "Any" %> 15 | 16 | <%= post_params [ 17 | ["text", "The raw text to process."] 18 | ]%> 19 | 20 | #### Example 21 | 22 | <% response = { 23 | "entities" => { 24 | "hashtags" => [ 25 | { 26 | "len" => 8, 27 | "name" => "awesome", 28 | "pos" => 8 29 | } 30 | ], 31 | "links" => [ 32 | { 33 | "len" => 17, 34 | "pos" => 39, 35 | "text" => "http://google.com", 36 | "url" => "http://google.com" 37 | } 38 | ], 39 | "mentions" => [ 40 | { 41 | "id" => "3", 42 | "len" => 10, 43 | "name" => "voidfiles", 44 | "pos" => 22 45 | } 46 | ] 47 | }, 48 | "html" => "This is #awesome tell @voidfiles about http://google.com", 49 | "text" => "This is #awesome tell @voidfiles about http://google.com" 50 | } %> 51 | 52 | <% data = { 53 | "text" => "This is #awesome tell @voidfiles about http://google.com" 54 | } %> 55 | 56 | <%= curl_example(:post, "text/process", response, {:data => data}) %> 57 | -------------------------------------------------------------------------------- /content/reference/resources/post/reposts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Reposts" 3 | --- 4 | 5 | # Reposts 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Repost a Post 11 | 12 | Share a Post (specified with post_id) with your followers. Reposts are intended solely as a routing mechanism; a repost's text, entities, and html are "inherited" from the original Post. If a user would like to quote, comment on, or alter a Post, reposts are not the solution. Reposts are meant to be pointers to another Post. 13 | 14 | For compatibility with clients who don't wish to show reposts specially, we set a repost's text field to be `>> @username: original text`. **Thus the text field could actually be slightly longer than 256 characters.** Most clients will probably want to display the original post (with some indication that is has been reposted). When rendering a repost, we recommend you pull most of your information from `repost_of` and make use of the `repost_of.reposters` field. 15 | 16 | - Reposts cannot be reposted, starred, or replied to. Please take those actions on the parent post. 17 | - Reposts do not show up in the hashtags, mentions or global streams. 18 | - A repost of Post A will only show up in a User's stream if they have not seen Post A (or another repost of Post A) in a reasonable amount of time (currently 1 week). 19 | 20 | <%= general_params_note_for "post" %> 21 | 22 | <%= endpoint "POST", "posts/[post_id]/repost", "User", "write_post" %> 23 | 24 | <%= url_params [ 25 | ["post_id", "The id of the Post to repost."] 26 | ]%> 27 | 28 | #### Example 29 | 30 | <%= curl_example(:get, "posts/#{get_id(:post)}/repost", :repost) do |h| 31 | h["data"]["repost_of"]["you_reposted"] = true 32 | end %> 33 | 34 | ## Unrepost a Post 35 | 36 | Given the original `post_id`, delete the current user's repost. *This same functionality can be accomplished by [deleting using the repost's post_id](/reference/resources/post/lifecycle/#delete-a-post)*. 37 | 38 | <%= general_params_note_for "post" %> 39 | 40 | <%= endpoint "DELETE", "posts/[post_id]/repost", "User", "write_post" %> 41 | 42 | <%= url_params [ 43 | ["post_id", "The id of the Post to unrepost."] 44 | ]%> 45 | 46 | #### Example 47 | 48 | <%= curl_example(:delete, "posts/#{get_id(:post)}/repost", :post) do |h| 49 | h["data"]["you_reposted"] = false 50 | end %> -------------------------------------------------------------------------------- /layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= @item[:title] %> - App.net API Documentation 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |
21 | 23 | 26 | 27 |
28 |
29 |
30 | 37 |
38 |
39 |
40 | <%= yield %> 41 |
42 |
43 |
44 |
45 | 46 | 47 | 48 | 49 | 50 | 53 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/message.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
DescriptionMethodPathToken
Retrieve the Messages in a ChannelGET/stream/0/channels/{channel_id}/messagesVaries
Create a MessagePOST/stream/0/channels/{channel_id}/messagesUser
Retrieve a MessageGET/stream/0/channels/{channel_id}/messages/{message_id}Varies
Retrieve multiple MessagesGET/stream/0/channels/messagesAny
Retrieve my MessagesGET/stream/0/users/me/messagesUser
Delete a MessageDELETE/stream/0/channels/{channel_id}/messages/{message_id}User
Search for MessagesGET/stream/0/channels/messages/searchAny
55 | -------------------------------------------------------------------------------- /content/assets/js/app.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var _token = null; 3 | var verify_token = function (token) { 4 | if (token && token.match(/^[\-_a-zA-Z0-9]{98}$/)) { 5 | return $.ajax({ 6 | url: "https://alpha-api.<%= lanai_hostname %>/stream/0/token", 7 | headers: { 8 | "Authorization": "BEARER " + token 9 | } 10 | }).promise(); 11 | } else { 12 | return $.Deferred().reject().promise(); 13 | } 14 | }; 15 | 16 | var Auth = { 17 | login: function (new_token) { 18 | var deferred = $.Deferred(); 19 | 20 | var valid_token = verify_token(new_token); 21 | valid_token.fail(function () { 22 | if (_token === null && typeof(localStorage.token) !== 'undefined') { 23 | _token = JSON.parse(localStorage.token); 24 | } 25 | }).done(function () { 26 | _token = { 27 | user_token: new_token 28 | }; 29 | localStorage.token = JSON.stringify(_token); 30 | }).always(function () { 31 | if (_token && _token.user_token) { 32 | deferred.resolve(_token); 33 | } else { 34 | deferred.reject(); 35 | } 36 | }); 37 | 38 | return deferred.promise(); 39 | }, 40 | logout: function () { 41 | localStorage.token = null; 42 | token = null; 43 | _is_logged_in = false; 44 | }, 45 | verify_token: verify_token 46 | }; 47 | 48 | ADN.auth = Auth; 49 | }()); 50 | 51 | $(function() { 52 | // make it easy to upgrade scopes, if there's a new token just log in with that even if we're already logged in 53 | var new_token = $.url(window.location).fparam('access_token'); 54 | var login = ADN.auth.login(new_token); 55 | 56 | login.fail(function () { 57 | $('.authorize-prompt').removeClass('hide'); 58 | }).done(function (token) { 59 | var needle = "<YOUR ACCESS TOKEN>"; 60 | $('pre code').each(function () { 61 | var el = $(this); 62 | el.html(el.html().replace(needle, token.user_token)); 63 | }); 64 | }); 65 | 66 | $(".content h1, .content h2, .content h3, .content h4").each(function(e){ 67 | var id = $(this).attr("id"); 68 | if (!id) return; 69 | 70 | $(this).append(""); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /content/reference/resources/channel/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Channel Search" 3 | --- 4 | 5 | # Search 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Search for Channels 11 | 12 | Returns [Channel](/reference/resources/channel/) objects which match a given search query. Because channels have no inherent notion of description or name, we take textual data from common channel annotations which contain such fields, e.g. net.patter-app.settings. We also allow filtering on specific channel properties, such as channel type. No matter what query data is supplied, the search results will respect channel ACLs, and results are limited to non-private channels if the requesting access token does not have the messages scope. 13 | 14 | Separate lists of terms by spaces. 15 | 16 | <%= general_params_note_for "channel" %> 17 | 18 | <%= endpoint "GET", "channels/search", "User", "public_messages
or messages" %> 19 | 20 | <%= query_params_typed 'General Parameters', [ 21 | 22 | ["order", :optional, "string", "One of: popularity (default), id, or activity. Searches of ordering popularity are returned in an order that roughly matches the popularity of the channels. activity searches will order results roughly by time of last message (precise sorting of very recent messages is not guaranteed)."], 23 | 24 | ]%> 25 | 26 | <%= query_params_typed 'Search Query Parameters', [ 27 | 28 | ["q", :optional, "string", "Searches any textual fields extracted from channel annotations. We may tweak which annotations and fields are included by this search over time."], 29 | 30 | ]%> 31 | 32 | 33 | <%= query_params_typed 'Filter Parameters', [ 34 | ["type", :optional, "string", "Only include channels which were created with a specific channel type"], 35 | ["creator_id", :optional, "string", "Only include channels which were created by a user with a certain id"], 36 | ["tags", :optional, "string", "Only include channels which are tagged with certain tags. This data is extracted from channel annotations"], 37 | ["is_private", :optional, "boolean", "Only include channels which have any_user and public set to false for read and write ACLs"], 38 | ["is_public", :optional, "boolean", "Only include channels which have public set to true for read ACLs"], 39 | 40 | ]%> 41 | 42 | #### Example 43 | 44 | <%= curl_example(:get, "channels/search?q=kerbal&order=popularity", :channel, {:response => :paginated}) do |h| 45 | h["meta"]["count"] = 1 46 | h["data"][0]["pagination_id"] = "10000" 47 | end %> 48 | -------------------------------------------------------------------------------- /content/reference/resources/explore/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Explore Stream" 3 | --- 4 | 5 | # Explore Stream 6 | 7 | * TOC 8 | {:toc} 9 | 10 | An Explore Stream is a subset of all public posts flowing through App.net's Global Stream. These Explore Streams are defined by App.net to provide developers and users new ways to discover posts. **We will be adding and removing Explore Streams so in your app please [Retrieve all Explore Streams](#retrieve-all-explore-streams) and cache that list for up to 24 hours instead of hardcoding the current Explore Streams into your app.** 11 | 12 | <%= json(:explore_stream) %> 13 | 14 | ## Explore Stream Fields 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
FieldTypeDescription
slugstringPrimary identifier for an explore stream. A lowercase alphanumeric string.
titlestringA human-friendly name for this Explore Stream.
descriptionstringA short description of this Explore Stream for displaying to the User.
urlstringThe fully qualified url to the Explore Stream.
43 | 44 | ## Retrieve all Explore Streams 45 | 46 | Retrieve a list of all Explore Streams. The list of Explore Streams are dynamic and will sometimes change. **Please cache them for 24 hours in your app.** Also, please note that this endpoint is not paginated. 47 | 48 | <%= endpoint "GET", "posts/stream/explore", "None" %> 49 | 50 | #### Example 51 | 52 | <%= curl_example(:get, "posts/stream/explore", :explore_stream, {:response => :collection}) %> 53 | 54 | ## Retrieve an Explore Stream 55 | 56 | Retrieve the Posts in an Explore Stream. 57 | 58 | <%= pagination_note %> 59 | 60 | <%= endpoint "GET", "posts/stream/explore/[slug]", "None" %> 61 | 62 | <%= url_params [ 63 | ["slug", "The slug of the Explore Stream to retrieve."] 64 | ]%> 65 | 66 | #### Example 67 | 68 | <%= curl_example(:get, "posts/stream/explore/photos", :explore_stream, {:response => :paginated}) do |h| 69 | h["meta"].merge!({ 70 | "max_id" => "3382496", 71 | "min_id" => "3382480", 72 | "marker" => { 73 | "name" => "explore:photos" 74 | }, 75 | "explore_stream" => get_hash(:explore_stream) 76 | }) 77 | h["data"] = ["...post objects..."] 78 | end %> 79 | -------------------------------------------------------------------------------- /content/reference/resources/user/muting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Muting" 3 | --- 4 | 5 | # Muting 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Mute a User 11 | 12 | Hide all posts for a User in all streams. *If you still explicitly request this User's stream or a Post from this User, it will not be hidden.* 13 | 14 | <%= general_params_note_for "user" %> 15 | 16 | <%= endpoint "POST", "users/[user_id]/mute", "User", "follow" %> 17 | 18 | <%= url_params [ 19 | ["user_id","The id of the User to mute. You can also specify @username as a user_id."] 20 | ]%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:post, "users/#{get_id(:user)}/mute", :user) do |h| 25 | h["data"]["you_muted"] = true 26 | end %> 27 | 28 | ## Unmute a User 29 | 30 | Stop hiding all posts for a given user. 31 | 32 | <%= general_params_note_for "user" %> 33 | 34 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 35 | 36 | <%= endpoint "DELETE", "users/[user_id]/mute", "User", "follow" %> 37 | 38 | <%= url_params [ 39 | ["user_id","The id of the User to mute. You can also specify @username as a user_id."] 40 | ]%> 41 | 42 | #### Example 43 | 44 | <%= curl_example(:delete, "users/#{get_id(:user)}/mute", :user) do |h| 45 | h["data"]["you_muted"] = false 46 | end %> 47 | 48 | ## List muted Users 49 | 50 | Retrieve a list of muted users. 51 | 52 | <%= general_params_note_for "user" %> 53 | 54 | <%= endpoint "GET", "users/[user_id]/muted", "Any" %> 55 | 56 | <%= url_params [ 57 | ["user_id",'The id of the user to retrieve a list of muted users for. If requested with a user token you can request muted users for the current user by using me as the user id. If requested with an app token you can request muted users for any user that has authorized your app.'] 58 | ]%> 59 | 60 | #### Example 61 | 62 | <%= curl_example(:get, "users/me/muted", :user, {:response => :collection}) do |h| 63 | h["data"][0]["you_muted"] = true 64 | end %> 65 | 66 | ## Retrieve muted User IDs for multiple Users 67 | 68 | Returns a list of muted User ids for each User id requested. At most 200 User ids can be requested. 69 | 70 | <%= endpoint "GET", "users/muted/ids", "App" %> 71 | 72 | <%= query_params [ 73 | ["ids","A comma separated list of User ids to retrieve muted User ids for."] 74 | ]%> 75 | 76 | #### Example 77 | 78 | <%= curl_example(:get, "users/muted/ids?ids=1,2", { 79 | "1" => ["3", "29"], 80 | "2" => [] 81 | }, {:token => ""}) %> 82 | -------------------------------------------------------------------------------- /content/reference/resources/channel/lookup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Channel Lookup" 3 | --- 4 | 5 | # Lookup 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve a Channel 11 | 12 | Returns a specific [Channel](/reference/resources/channel/). 13 | 14 | <%= general_params_note_for "channel" %> 15 | 16 | <%= endpoint "GET", "channels/[channel_id]", "Any", "public_messages
or messages"%> 17 | 18 | <%= url_params [ 19 | ["channel_id", "The id of the Channel to retrieve."] 20 | ]%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:get, "channels/1", :channel) %> 25 | 26 | ## Retrieve multiple Channels 27 | Returns multiple Channels requested by id. At most 200 channels can be requested. Channels which do not exist or which the requesting user does not have authorization to view will not be returned. 28 | 29 | <%= general_params_note_for "channel" %> 30 | 31 | <%= endpoint "GET", "channels", "Any" %> 32 | 33 | <%= query_params [ 34 | ["ids", "A comma separated list of ids of Channels to retrieve."] 35 | ]%> 36 | 37 | #### Example 38 | 39 | In the following example, Channel 6502 is omitted because it doesn't exist or we don't have permission to view it. 40 | 41 | <%= curl_example(:get, "channels?ids=1,2,6502", :channel, {:response => :collection}) do |h| 42 | second = h["data"][0].clone() 43 | second["id"] = "2" 44 | h["data"].unshift(second) 45 | end %> 46 | 47 | ## Retrieve my Channels 48 | Returns a stream of all Channels the current user has created. 49 | 50 | <%= general_params_note_for "channel" %> 51 | 52 | <%= pagination_note %> 53 | 54 | <%= endpoint "GET", "users/me/channels", "User", "public_messages or messages"%> 55 | 56 | #### Example 57 | 58 | <%= curl_example(:get, "users/me/channels", :channel, {:response => :paginated}) %> 59 | 60 | ## Retrieve number of unread PM Channels 61 | Returns the current number of `net.app.core.pm` Channels where `has_unread: true` for the current user. 62 | 63 | <%= endpoint "GET", "users/me/channels/pm/num_unread", "User", "messages"%> 64 | 65 | #### Example 66 | 67 | <%= curl_example(:get, "users/me/channels/pm/num_unread", 5) %> 68 | 69 | ## Retrieve number of unread Broadcast Channels 70 | Returns the current number of `net.app.core.broadcast` Channels where `has_unread: true` for the current user. 71 | 72 | <%= endpoint "GET", "users/me/channels/broadcast/num_unread", "User", "messages"%> 73 | 74 | #### Example 75 | 76 | <%= curl_example(:get, "users/me/channels/broadcast/num_unread", 3) %> 77 | 78 | 79 | ## Mark all Broadcast Channels as read 80 | Mark all `net.app.core.broadcast` Channels as read for the current user. 81 | 82 | <%= endpoint "DELETE", "users/me/channels/broadcast/num_unread", "User", "messages"%> 83 | 84 | #### Example 85 | 86 | <%= curl_example(:delete, "users/me/channels/broadcast/num_unread", 0) %> 87 | -------------------------------------------------------------------------------- /content/reference/resources/post/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Post Lifecycle" 3 | --- 4 | 5 | # Post Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Create a Post 11 | 12 | Create a new Post object. Mentions and hashtags will be parsed out of the post text, as will bare URLs. 13 | 14 | You can also create a Post by sending JSON in the HTTP post body that matches the post schema with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `text`, `reply_to`, `machine_only`, `annotations` and `entities`. To create complex posts (including [machine only posts](/reference/resources/post/#machine-only-posts)), you must use the JSON interface. See the [JSON example](#json-example) below. If you would like to specify your own entities, please refer to the [user specified entities](/reference/meta/entities/#user-specified-entities) documentation. 15 | 16 | If you want to test how your text will be processed you can use the [text processor](/reference/resources/text-processor). 17 | 18 | *You cannot reply to a repost. Please reply to the parent Post.* 19 | 20 | <%= general_params_note_for "post" %> 21 | 22 | <%= endpoint "POST", "posts", "User", "write_post" %> 23 | 24 | <%= post_params [ 25 | ["text", "The raw text of the post."], 26 | ["reply_to", "(Optional) The id of the Post that this new Post is replying to."] 27 | ]%> 28 | 29 | #### Example 30 | 31 | <% text = get_hash(:post)["text"] %> 32 | <%= curl_example(:post, "posts", :post, {:data => {"text" => text}, :content_type => nil}) %> 33 | 34 | #### Example (JSON Data) 35 | 36 | <% data = { 37 | "text" => text, 38 | "annotations" => [{ 39 | "type" => "net.app.core.geolocation", 40 | "value" => { 41 | "latitude" => 74.0064, 42 | "longitude" => 40.7142 43 | } 44 | }] 45 | } %> 46 | <%= curl_example(:post, "posts?include_post_annoations=1", :post, {:data => data}) do |h| 47 | h["data"]["annotations"] = data["annotations"] 48 | end %> 49 | 50 | ## Delete a Post 51 | 52 | Delete a Post. The current user must be the same user who created the Post. It returns the deleted Post on success. 53 | 54 | <%= general_params_note_for "post" %> 55 | 56 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 57 | 58 | <%= endpoint "DELETE", "posts/[post_id]", "User", "write_post" %> 59 | 60 | <%= url_params [ 61 | ["post_id", "The id of the Post to delete."] 62 | ]%> 63 | 64 | #### Example 65 | 66 | <%= curl_example(:delete, "posts/#{get_id(:post)}", :post) do |h| 67 | h["data"]["is_deleted"] = true 68 | h["data"].delete("text") 69 | h["data"].delete("html") 70 | h["data"]["entities"].each { |k, v| h["data"]["entities"][k] = []} 71 | end %> 72 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/file.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
DescriptionMethodPathToken
Create a FilePOST/stream/0/filesUser
Create a Derived FilePOST/stream/0/files/{file_id}/{derived_key}User
Retrieve a FileGET/stream/0/files/{file_id}Varies
Retrieve multiple FilesGET/stream/0/filesUser
Delete a FileDELETE/stream/0/files/{file_id}User
Retrieve my FilesGET/stream/0/users/me/filesUser
Update a FilePUT/stream/0/files/{file_id}User
Get File contentGET/stream/0/files/{file_id}/contentUser
Set File contentPUT/stream/0/files/{file_id}/contentUser
Set Derived File contentPUT/stream/0/files/{file_id}/content/{derived_key}User
73 | -------------------------------------------------------------------------------- /content/reference/resources/file/content.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "File Content" 3 | --- 4 | 5 | # Content 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Get File content 11 | 12 | Get the content for a complete File. 13 | 14 | This endpoint will return a 302 Redirect to a temporary URL for the content of this file. This endpoint is useful for fetching private content from a file. 15 | 16 | <%= endpoint "GET", "files/[file_id]/content", "User" %> 17 | 18 | <%= file_token_reminder %> 19 | 20 | <%= url_params [ 21 | ["file_id", "The id of the File to retrieve content for."] 22 | ]%> 23 | 24 | ## Set File content 25 | 26 | Set the content for an incomplete File. The content type for this request must be the content type of the file you are uploading. This endpoint can optionally accept a header field `x-adn-filename` to set the File's name. 27 | 28 | This endpoint could return a `507 Insufficient Storage` error if the user doesn't have enough space for this file. For more information, see [file storage limits](/reference/resources/file/#limits). 29 | 30 | When successful, this endpoint will return a `204 No Content` response. 31 | 32 | <%= endpoint "PUT", "files/[file_id]/content", "User" %> 33 | 34 | <%= file_token_reminder %> 35 | 36 | <%= url_params [ 37 | ["file_id", "The id of the File to set content for."] 38 | ]%> 39 | 40 | #### Example 41 | 42 | <%= curl_example(:put, "files/1/content", "204 No Content", { 43 | :content_type => "image/png", 44 | :data_binary => "@filename.png", 45 | :response => :raw 46 | }) %> 47 | 48 | ## Get Derived File content 49 | 50 | Get the content for a derived file of a complete File. 51 | 52 | This endpoint will return a 302 Redirect to a temporary URL for the content of this derived file. 53 | 54 | <%= endpoint "GET", "files/[file_id]/content/[derived_file_key]", "User" %> 55 | 56 | <%= file_token_reminder %> 57 | 58 | <%= url_params [ 59 | ["file_id", "The id of the File to retrieve content for."], 60 | ["derived_file_key", "The key identifying the derived file you want the content for."] 61 | ]%> 62 | 63 | ## Set Derived File content 64 | 65 | Set the content for a derived file of an incomplete File. The content type for this request must be the content type of the file you are uploading. This endpoint can optionally accept a header field `x-adn-filename` to set the Derived File's name. 66 | 67 | This endpoint could return a `507 Insufficient Storage` error if the user doesn't have enough space for this derived file. For more information, see [file storage limits](/reference/resources/file/#limits). 68 | 69 | <%= endpoint "PUT", "files/[file_id]/content/[derived_file_key]", "User" %> 70 | 71 | <%= file_token_reminder %> 72 | 73 | <%= url_params [ 74 | ["file_id", "The id of the File to set content for."], 75 | ["derived_file_key", "The key identifying the derived file you want to create."] 76 | ]%> 77 | 78 | #### Example 79 | 80 | <%= curl_example(:put, "files/1/content/thumbnail_png", "204 No Content", { 81 | :content_type => "image/png", 82 | :data_binary => "@filename.png", 83 | :response => :raw 84 | }) %> 85 | -------------------------------------------------------------------------------- /content/reference/other/web-intents.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Web Intents" 3 | --- 4 | 5 | # Web Intents 6 | 7 | * TOC 8 | {:toc} 9 | 10 | Web intents are an easy way to integrate with App.net; you don't even need to use Javascript. Intents in their most basic form are just carefully constructed URLs. By clicking on an intent link, a user will be taken to a page on App.net with a prompt to carry out an action, such as creating a post. If the user is not logged in to App.net, she/he will first authenticate before being presented with the action dialog. 11 | 12 | 13 |
14 |

If you just want a simple follow or share button you can use button builder instead. We've also open sourced the buttons so that you could host them your self. Checkout the github repo for more information on how to do that.

15 |
16 | 17 | ## The Post Intent 18 | 19 | The post intent allows you to create a link that will present the user with a post creation box and any pre-filled text that you may have supplied. 20 | 21 | The base URL for this intent is `https://alpha.app.net/intent/post/`. 22 | 23 | You may optionally prepopulate the post creation box by supplying a `text` query parameter to the URL. 24 | 25 | For example, this URL `https://alpha.app.net/intent/post/?text=%40adn%20When%20is%20the%20next%20meetup%3F` will create a post that reads: 26 | 27 | > @adn When is the next meetup? 28 | 29 | At this point the end user will be able to edit and then submit the post. 30 | 31 | There is a second optional parameter: `url`. This allows you to automatically appended a URL to a post. 32 | 33 | For example, this URL: `https://alpha.app.net/intent/post/?text=%40adn%20Does%20this%20place%20work%3F&url=https%3A%2F%2Fmaps.google.com%2Fmaps%3Fq%3Dpublic%2Bhouse%2Bsf%26fb%3D1%26gl%3Dus%26hq%3Dpublic%2Bhouse%26hnear%3D0x80859a6d00690021%3A0x4a501367f076adff%2CSan%2BFrancisco%2C%2BCA%26cid%3D0%2C0%2C2651066427117992613%26t%3Dm%26z%3D16%26iwloc%3DA` will create a post that reads: 34 | 35 | > @adn Does this place work? https://maps.google.com/maps?q=public+… 36 | 37 | You'll notice that the displayed URL is automatically truncated to 40 chars. The full URL is included though. If your URL is less then 40 chars it will be included as is. 38 | 39 | 40 | ## The Follow Intent 41 | 42 | The follow intent is an easy way to link to a page on App.net that will present the user with an opportunity to follow a selected user. 43 | 44 | The base URL for this intent is `https://alpha.app.net/intent/follow/`. 45 | 46 | You must include a user that is the intended target of the follow action. To do this include a `user_id` query parameter in the URL. The `user_id` can be a username prepended by a @, like @adn, or it can be the numeric user_id, like 136. 47 | 48 | For example, this URL `https://alpha.app.net/intent/follow/?user_id=136` will show page where the user can choose to follow the user @adn. 49 | -------------------------------------------------------------------------------- /content/reference/resources/post/streams.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Post Streams" 3 | --- 4 | 5 | # Post Streams 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Retrieve the Global stream 11 | 12 | Return the 20 most recent [Posts](/reference/resources/post/) from the Global stream. 13 | 14 | <%= general_params_note_for "post" %> 15 | 16 | <%= pagination_note %> 17 | 18 | <%= endpoint "GET", "posts/stream/global", "None" %> 19 | 20 | #### Example 21 | 22 | <%= curl_example(:get, "posts/stream/global", :post, {:response => :paginated}) %> 23 | 24 | ## Retrieve Posts created by a User 25 | 26 | Get the most recent [Posts](/reference/resources/post/) created by a specific [User](/reference/resources/user/) in reverse post order. 27 | 28 | <%= general_params_note_for "post" %> 29 | 30 | <%= pagination_note %> 31 | 32 | <%= endpoint "GET", "users/[user_id]/posts", "None" %> 33 | 34 | <%= url_params [ 35 | ["user_id", "The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 36 | ]%> 37 | 38 | #### Example 39 | 40 | <%= curl_example(:get, "users/#{get_id(:user)}/posts", :post, {:response => :paginated}) %> 41 | 42 | ## Retrieve Posts mentioning a User 43 | 44 | Get the most recent [Posts](/reference/resources/post/) mentioning by a specific [User](/reference/resources/user/) in reverse post order. 45 | 46 | <%= general_params_note_for "post" %> 47 | 48 | <%= pagination_note %> 49 | 50 | <%= endpoint "GET", "users/[user_id]/mentions", "Any" %> 51 | 52 | <%= url_params [ 53 | ["user_id", "The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 54 | ]%> 55 | 56 | #### Example 57 | 58 | <%= curl_example(:get, "users/2/mentions", :post, {:response => :paginated}) %> 59 | 60 | ## Retrieve a User's personalized stream 61 | 62 | Return the 20 most recent [Posts](/reference/resources/post/) from the current User and the Users they follow. 63 | 64 | <%= general_params_note_for "post" %> 65 | 66 | <%= stream_facet_note %> 67 | 68 | <%= pagination_note %> 69 | 70 | <%= endpoint "GET", "posts/stream", "User", "stream" %> 71 | 72 | #### Example 73 | 74 | <%= curl_example(:get, "posts/stream", :post, {:response => :paginated}) %> 75 | 76 | ## Retrieve a User's unified stream 77 | 78 | Return the 20 most recent [Posts](/reference/resources/post/) from the current user's [personalized stream](#retrieve-a-users-personalized-stream) and [mentions stream](#retrieve-posts-mentioning-a-user) merged into one stream. 79 | 80 | <%= general_params_note_for "post" %> 81 | 82 | <%= pagination_note %> 83 | 84 | <%= stream_facet_note %> 85 | 86 | <%= endpoint "GET", "posts/stream/unified", "User", "stream" %> 87 | 88 | #### Example 89 | 90 | <%= curl_example(:get, "posts/stream/unified", :post, {:response => :paginated}) %> 91 | 92 | ## Retrieve tagged Posts 93 | 94 | Return the 20 most recent [Posts](/reference/resources/post/) for a specific hashtag. 95 | 96 | <%= general_params_note_for "post" %> 97 | 98 | <%= pagination_note %> 99 | 100 | <%= endpoint "GET", "posts/tag/[hashtag]", "None" %> 101 | 102 | #### Example 103 | 104 | <%= curl_example(:get, "posts/tag/adnhack", :post, {:response => :paginated}) %> 105 | -------------------------------------------------------------------------------- /content/reference/make-request/rate-limits.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Rate Limits" 3 | --- 4 | 5 | # Rate Limits 6 | 7 | * TOC 8 | {:toc} 9 | 10 | Fundamental limits of server resources and network infrastructure make it necessary for us to limit the rate at which we handle requests. By enforcing request rate limits, we make it feasible to fairly and evenly distribute our capacity amongst our users and prevent apps from monopolizing these resources. 11 | 12 | ## Enforcement 13 | 14 | Any request, authorized or unauthorized, may be subject to multiple rate limits. At present, authorized calls are limited per access token, while unauthorized calls are limited per IP address. When more than one limit applies to a request, the request will apply against each of those limits, but information will be returned on only the most restrictive of those limits. 15 | 16 | ## Response Headers 17 | 18 | The following sample shows a set of three headers which might be returned with a response to a call to the API. 19 | 20 | X-RateLimit-Remaining: 4959 21 | X-RateLimit-Limit: 5000 22 | X-RateLimit-Reset: 3600 23 | 24 | The first header, `X-RateLimit-Remaining`, indicates the total number of requests remaining for this cycle (4959). `X-RateLimit-Limit` indicates the total capacity (5000). `X-RateLimit-Reset` gives the number of seconds until the remaining number of requests will be reset to the capacity; in this case, `X-RateLimit-Remaining` will be reset to 5000 requests in 3600 seconds, irrespective of how many additional requests are made between now and then. 25 | 26 | ## Exceeding Limits 27 | 28 | Should your request exceed any applicable rate limits, we will return a status code `429` (Too many requests). We ask that any app which is accessing our API respect this response code. The `Retry-After` header will contain the number of seconds before another request of this type can be made -- if your request receives a `429` code, your application should wait until the `Retry-After` period has elapsed before attempting the same kind of request. 29 | 30 | ## Limits 31 | 32 | At present, these are the limit values we use: 33 | 34 | ### Authenticated Requests (per token) 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
TypeLimitPeriodNotes
Global50001 hour (3600 seconds)Affects all authenticated endpoints, even if other limits apply as well.
Write201 minute (60 seconds)POST/DELETE requests.
60 | 61 | ### Unauthenticated Requests (per IP address) 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
TypeLimitPeriodNotes
Global501 minute (60 seconds)Affects all unauthenticated endpoints.
81 | -------------------------------------------------------------------------------- /content/reference/resources/user/blocking.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Blocking" 3 | --- 4 | 5 | # Blocking 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Block a User 11 | 12 | Block a user from seeing your App.net content. This means the user will not be able to see, star, reply to, or repost your content. This user will also effectively be muted for you. This will automatically unfollow both users from each other. A user may be able to tell if they've been blocked by a user. For instance if @mthurman blocks @berg and @berg logs out of alpha.app.net, he could see @mthurman's profile. 13 | 14 | In most cases, [muting a user](/reference/resources/user/muting/#mute-a-user) is probably sufficient since that hides all of a user's content from you. If a user is aggressively reposting or starring your content, blocking them will prevent them from interacting with your content at all. 15 | 16 | <%= general_params_note_for "user" %> 17 | 18 | <%= endpoint "POST", "users/[user_id]/block", "User", "follow" %> 19 | 20 | <%= url_params [ 21 | ["user_id","The id of the User to block. You can also specify @username as a user_id."] 22 | ]%> 23 | 24 | #### Example 25 | 26 | <%= curl_example(:post, "users/#{get_id(:user)}/block", :user) do |h| 27 | h["data"]["you_blocked"] = true 28 | h["data"]["you_follow"] = false 29 | end %> 30 | 31 | ## Unblock a User 32 | 33 | Allow a blocked user to interact with my content. 34 | 35 | <%= general_params_note_for "user" %> 36 | 37 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 38 | 39 | <%= endpoint "DELETE", "users/[user_id]/block", "User", "follow" %> 40 | 41 | <%= url_params [ 42 | ["user_id","The id of the User to block. You can also specify @username as a user_id."] 43 | ]%> 44 | 45 | #### Example 46 | 47 | <%= curl_example(:delete, "users/#{get_id(:user)}/block", :user) do |h| 48 | h["data"]["you_blocked"] = false 49 | h["data"]["you_follow"] = false 50 | end %> 51 | 52 | ## List blocked Users 53 | 54 | Retrieve a list of blocked users. 55 | 56 | <%= general_params_note_for "user" %> 57 | 58 | <%= endpoint "GET", "users/[user_id]/blocked", "Any" %> 59 | 60 | <%= url_params [ 61 | ["user_id",'The id of the user to retrieve a list of muted users for. If requested with a user token you can request blocked users for the current user by using me as the user id. If requested with an app token you can request blocked users for any user that has authorized your app.'] 62 | ]%> 63 | 64 | #### Example 65 | 66 | <%= curl_example(:get, "users/me/blocked", :user, {:response => :collection}) do |h| 67 | h["data"][0]["you_blocked"] = true 68 | h["data"][0]["you_follow"] = false 69 | end %> 70 | 71 | ## Retrieve blocked User IDs for multiple Users 72 | 73 | Returns a list of blocked User ids for each User id requested. At most 200 User ids can be requested. 74 | 75 | <%= endpoint "GET", "users/blocked/ids", "App" %> 76 | 77 | <%= query_params [ 78 | ["ids","A comma separated list of User ids to retrieve blocked User ids for."] 79 | ]%> 80 | 81 | #### Example 82 | 83 | <%= curl_example(:get, "users/blocked/ids?ids=1,2", { 84 | "1" => ["3", "29"], 85 | "2" => [] 86 | }, {:token => ""}) %> 87 | -------------------------------------------------------------------------------- /content/reference/make-request/migrations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Migrations" 3 | --- 4 | 5 | # Migrations 6 | 7 | * TOC 8 | {:toc} 9 | 10 | We reserve the right to make incremental changes to the API as we deem necessary. In order to make it possible to change the API but still support legacy applications, we will make use of migrations. Migrations are a per-app feature that developers may toggle for their own apps from the time that the old behavior is deprecated until the time that it has reached the end of its life (EOL). Once the EOL date is reached, the migration will be enabled for all apps with no legacy mode available. 11 | 12 | ## Accessing Migration Data 13 | 14 | We offer a single toggle for each migration and app that will globally turn the migration on (current mode) or off (legacy mode) for that app as well as a per-call header mechanism that overrides the global behavior. 15 | 16 | ### Global Toggle 17 | 18 | You can toggle the global migration behavior of your apps by editing your apps listed at [https://account.app.net/developer/apps/](https://account.app.net/developer/apps/). 19 | 20 | By default, new apps will come with all existing migrations toggled to "Current" mode. This reflects the fact that support for legacy mode will eventually be removed. However, any migrations that are released after the app is created will be initially toggled to "Legacy" mode, so app developers can expect that the API behavior will not unexpectedly change for existing apps. 21 | 22 | ### Per-call Toggle 23 | In addition to using the edit app toggles, we offer the `X-ADN-Migration-Overrides` header as a way for developers to override migration behavior on a per-call basis. This header should contain a **query-string encoded** list of valid [migration keys](#current-migrations) and values (0 or 1). For example, providing `X-ADN-Migration-Overrides: foo=0` would disable the migration named `foo`. We expect that some apps may be distributed in such a way that some users may be running old versions while others are running newer versions, so this override header may make it easier to adopt new functionality without causing regressions. As with the toggle, though, migration override keys cannot be used past their EOL dates. Also, `X-ADN-Migration-Overrides` is whitelisted for CORS, so we expect that it should be usable in all contexts. 24 | 25 | ### Migration Response Header 26 | All calls to our endpoints will return `X-ADN-Migrations-Enabled`, a query-string encoded list of migration keys that are enabled for that particular API call. This list will take into account globally toggled migrations as well as those enabled by `X-ADN-Migration-Overrides`. 27 | 28 | ### Using Migrations with JSONP 29 | For JSONP requests we offer the ability to override the default migration behavior on a per-call basis. To do this, add a list of valid [migration keys](#current-migrations) and values (0 or 1) to the query string. For example, `https://alpha-api.app.net/stream/0/posts/stream/global?callback=json_callback&foo=0` 30 | 31 | **Toggling migrations with the query string is ONLY available for JSONP requests.** Use the header mechanism for all other requests. 32 | 33 | ## Current Migrations 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
KeyMigration (name)DescriptionEnd-Of-Life Date
There are no active migrations.
53 | -------------------------------------------------------------------------------- /content/reference/resources/interaction/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Interactions" 3 | --- 4 | 5 | # Interactions 6 | 7 | * TOC 8 | {:toc} 9 | 10 | Interactions are objects that represent users taking certain actions on App.net. Interactions are structured to form a sentence like: User X took action Y on object Z. If multiple users take the same action (e.g. multiple users reply to one post) within a set time window those events will be combined into a single Interaction. 11 | 12 | > The `objects` list of an Interaction will vary based on the `action` 13 | 14 | (Example) @dalton and @berg reposted post 1: 15 | 16 | <%= json_output(:repost_interaction) %> 17 | 18 | (Example) @berg started following @dalton: 19 | 20 | <%= json(:follow_interaction) %> 21 | 22 | ## Interactions Fields 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
FieldTypeDescription
actionstringWhat users did. Currently one of follow, reply, repost, star, welcome, broadcast_create, broadcast_subscribe, or broadcast_unsubscribe.
event_datestringThe time of the most recent interaction occurred at in ISO 8601 format.
objectslistusers took action on. These objects will be Users if action=follow. For star, repost, reply these objects will be Posts. For broadcast_create, broadcast_subscribe, broadcast_subscribe these will be channels. For welcome this will be empty.
userslistA list of User objects that took action on objects.
55 | 56 | ## List User interactions with me 57 | 58 | List all the [Interactions](/reference/resources/interaction/) other users have had with me. 59 | 60 | <%= pagination_note %> 61 | 62 | > You can only request this list for the current user. 63 | 64 | 65 | > Although this endpoint supports paging, a user's Interactions stream is continuously rebuilt as new actions in the system occur, so developers should generally plan to refetch the stream whenever switching to display it as Interactions may have shifted their position, with users being added or removed. If you need to keep track of activity in a more precise manner, you should using the [Streaming API](/reference/resources/app-stream/) to monitor the global feed for relevant activity. 66 | 67 | This endpoint accepts the `interaction_actions` as a query string parameter whose value is a comma separated list of actions you're interested in. For instance, if you're only interested in repost and follow interactions you could request `stream/0/users/me/interactions?interaction_actions=repost,follow`. 68 | 69 | <%= endpoint "GET", "users/me/interactions", "User" %> 70 | 71 | #### Example 72 | 73 | <%= curl_example(:get, "users/me/interactions", :repost_interaction, {:response => :paginated}) do |h| 74 | h["data"][0]["pagination_id"] = "10" 75 | end %> 76 | -------------------------------------------------------------------------------- /content/reference/resources/channel/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Channel Lifecycle" 3 | --- 4 | 5 | # Channel Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Create a Channel 11 | 12 | Create a new [Channel](/reference/resources/channel/). 13 | 14 | Send a JSON document that matches the [Channel schema](/reference/resources/channel/) with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `readers`, `writers`, `annotations`, and `type`. The owner will be auto-subscribed to this channel. 15 | 16 | ### Creating a PM Channel 17 | 18 | [PM Channels](/reference/resources/channel/#private-message) (channels of type `net.app.core.pm`) cannot be directly created. Instead they are created for you as necessary when sending a [Message](/reference/resources/message/) using `pm` as a `channel_id`. For more information, see the [Create a Message](/reference/resources/message/lifecycle/#create-a-message) endpoint. 19 | 20 | <%= general_params_note_for "channel" %> 21 | 22 | <%= endpoint "POST", "channels", "User", "public_messages
or messages"%> 23 | 24 | ### Example 25 | 26 | <% data = { 27 | "type" => "com.example.channel", 28 | "writers" => { 29 | "user_ids" => ["@berg", "1"] 30 | } 31 | } %> 32 | <%= curl_example(:post, "channels", :channel, {:data => data}) do |h| 33 | h["data"]["id"] = "2" 34 | h["data"]["readers"]["public"] = false 35 | h["data"]["writers"]["user_ids"] = ["1", "2"] 36 | h["data"].delete("recent_message_id") 37 | h["data"].delete("recent_message") 38 | end %> 39 | 40 | ## Update a Channel 41 | 42 | Updates a specific [Channel](/reference/resources/channel/) object. You can update a channel by PUTing an object that matches the [Channel schema](/reference/resources/channel/) with an HTTP header of `Content-Type: application/json`. The only keys that can be updated are `annotations`, `readers`, and `writers` (and the ACLs can only be updated if `immutable=false`). The `you_can_edit` property tells you if you are allowed to update a channel. Currently, only the Channel owner can edit a channel. 43 | 44 | If you want to add or update a Channel's annotations, you may include the optional `annotations` key and pass in the annotations that are changing. 45 | 46 | This endpoint currently works identically for the `PUT` and `PATCH` HTTP methods. 47 | 48 | <%= general_params_note_for "channel" %> 49 | 50 | <%= endpoint "PUT", "channels/[channel_id]", "User", "public_messages or messages"%> 51 | 52 | <%= url_params [ 53 | ["channel_id", "The id of the Channel to update."] 54 | ]%> 55 | 56 | #### Example 57 | 58 | <%= curl_example(:put, "channels/1", :channel, {:data => {"readers" => {"public" => true}}}) %> 59 | 60 | ## Deactivate a Channel 61 | 62 | Mark a channel as inactive. This **does not** delete the contents of the Channel. It prevents new messages from being added to the channel and unsubscribes all users from the Channel. This channel will be hidden unless it is explicitly requested by id or the `include_inactive=1` parameter is used. This is irreversible. 63 | 64 | The current user must be the same user who created the Channel. *Editors cannot delete a channel* 65 | 66 | *net.app.core.pm* channels cannot be marked as inactive. 67 | 68 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 69 | 70 | <%= general_params_note_for "channel" %> 71 | 72 | <%= endpoint "DELETE", "channels/[channel_id]", "User" %> 73 | 74 | <%= url_params [ 75 | ["channel_id", "The id of the Channel to delete."] 76 | ]%> 77 | 78 | ### Example 79 | 80 | <%= curl_example(:delete, "channels/1", :channel) do |h| 81 | h["data"]["is_inactive"] = true 82 | h["data"]["counts"]["subscribers"] = 0 83 | h["you_subscribed"] = false 84 | end %> 85 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | # Nanoc really doesn't have any sense of an environment 2 | # Instead we have a different config file for each enviroment 3 | # If you make a change to one config file, you need to make a change to all of them 4 | 5 | 6 | # A list of file extensions that nanoc will consider to be textual rather than 7 | # binary. If an item with an extension not in this list is found, the file 8 | # will be considered as binary. 9 | text_extensions: [ 'coffee', 'css', 'erb', 'haml', 'handlebars', 'hb', 'htm', 'html', 'js', 'less', 'markdown', 'md', 'ms', 'mustache', 'php', 'rb', 'sass', 'scss', 'txt', 'xhtml', 'xml' ] 10 | 11 | # The path to the directory where all generated files will be written to. This 12 | # can be an absolute path starting with a slash, but it can also be path 13 | # relative to the site directory. 14 | output_dir: output 15 | 16 | # A list of index filenames, i.e. names of files that will be served by a web 17 | # server when a directory is requested. Usually, index files are named 18 | # “index.html”, but depending on the web server, this may be something else, 19 | # such as “default.htm”. This list is used by nanoc to generate pretty URLs. 20 | index_filenames: [ 'index.html' ] 21 | 22 | # Whether or not to generate a diff of the compiled content when compiling a 23 | # site. The diff will contain the differences between the compiled content 24 | # before and after the last site compilation. 25 | enable_output_diff: false 26 | 27 | prune: 28 | # Whether to automatically remove files not managed by nanoc from the output 29 | # directory. For safety reasons, this is turned off by default. 30 | auto_prune: false 31 | 32 | # Which files and directories you want to exclude from pruning. If you version 33 | # your output directory, you should probably exclude VCS directories such as 34 | # .git, .svn etc. 35 | exclude: [ '.git', '.hg', '.svn', 'CVS' ] 36 | 37 | # The data sources where nanoc loads its data from. This is an array of 38 | # hashes; each array element represents a single data source. By default, 39 | # there is only a single data source that reads data from the “content/” and 40 | # “layout/” directories in the site directory. 41 | data_sources: 42 | - 43 | # The type is the identifier of the data source. By default, this will be 44 | # `filesystem_unified`. 45 | type: filesystem_unified 46 | 47 | # The path where items should be mounted (comparable to mount points in 48 | # Unix-like systems). This is “/” by default, meaning that items will have 49 | # “/” prefixed to their identifiers. If the items root were “/en/” 50 | # instead, an item at content/about.html would have an identifier of 51 | # “/en/about/” instead of just “/about/”. 52 | items_root: / 53 | 54 | # The path where layouts should be mounted. The layouts root behaves the 55 | # same as the items root, but applies to layouts rather than items. 56 | layouts_root: / 57 | 58 | # Whether to allow periods in identifiers. When turned off, everything 59 | # past the first period is considered to be the extension, and when 60 | # turned on, only the characters past the last period are considered to 61 | # be the extension. For example, a file named “content/about.html.erb” 62 | # will have the identifier “/about/” when turned off, but when turned on 63 | # it will become “/about.html/” instead. 64 | allow_periods_in_identifiers: false 65 | 66 | - 67 | type: static 68 | items_root: /static 69 | 70 | redirects: 71 | - 72 | from: /docs/basics/messaging/ 73 | to: /docs/guides/messaging/ 74 | - 75 | from: /docs/resources/stream/(.*) 76 | to: /reference/resources/app-stream/$1 77 | - 78 | from: /docs/(resources|authentication|meta|other)/(.*) 79 | to: /reference/$1/$2 80 | - 81 | from: /docs/basics/(.*) 82 | to: /reference/make-request/$1 83 | - 84 | from: /docs/guides/getting-started/ 85 | to: / 86 | -------------------------------------------------------------------------------- /static/css/pygments.css: -------------------------------------------------------------------------------- 1 | pre code .hll { background-color: #ffffcc } 2 | pre code .c { color: #408080; font-style: italic } /* Comment */ 3 | pre code .err { border: 1px solid #FF0000 } /* Error */ 4 | pre code .k { color: #008000; font-weight: bold } /* Keyword */ 5 | pre code .o { color: #666666 } /* Operator */ 6 | pre code .cm { color: #408080; font-style: italic } /* Comment.Multiline */ 7 | pre code .cp { color: #BC7A00 } /* Comment.Preproc */ 8 | pre code .c1 { color: #408080; font-style: italic } /* Comment.Single */ 9 | pre code .cs { color: #408080; font-style: italic } /* Comment.Special */ 10 | pre code .gd { color: #A00000 } /* Generic.Deleted */ 11 | pre code .ge { font-style: italic } /* Generic.Emph */ 12 | pre code .gr { color: #FF0000 } /* Generic.Error */ 13 | pre code .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 14 | pre code .gi { color: #00A000 } /* Generic.Inserted */ 15 | pre code .go { color: #808080 } /* Generic.Output */ 16 | pre code .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 17 | pre code .gs { font-weight: bold } /* Generic.Strong */ 18 | pre code .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 19 | pre code .gt { color: #0040D0 } /* Generic.Traceback */ 20 | pre code .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ 21 | pre code .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ 22 | pre code .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ 23 | pre code .kp { color: #008000 } /* Keyword.Pseudo */ 24 | pre code .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ 25 | pre code .kt { color: #B00040 } /* Keyword.Type */ 26 | pre code .m { color: #666666 } /* Literal.Number */ 27 | pre code .s { color: #BA2121 } /* Literal.String */ 28 | pre code .na { color: #7D9029 } /* Name.Attribute */ 29 | pre code .nb { color: #008000 } /* Name.Builtin */ 30 | pre code .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 31 | pre code .no { color: #880000 } /* Name.Constant */ 32 | pre code .nd { color: #AA22FF } /* Name.Decorator */ 33 | pre code .ni { color: #999999; font-weight: bold } /* Name.Entity */ 34 | pre code .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 35 | pre code .nf { color: #0000FF } /* Name.Function */ 36 | pre code .nl { color: #A0A000 } /* Name.Label */ 37 | pre code .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 38 | pre code .nt { color: #008000; font-weight: bold } /* Name.Tag */ 39 | pre code .nv { color: #19177C } /* Name.Variable */ 40 | pre code .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 41 | pre code .w { color: #bbbbbb } /* Text.Whitespace */ 42 | pre code .mf { color: #666666 } /* Literal.Number.Float */ 43 | pre code .mh { color: #666666 } /* Literal.Number.Hex */ 44 | pre code .mi { color: #666666 } /* Literal.Number.Integer */ 45 | pre code .mo { color: #666666 } /* Literal.Number.Oct */ 46 | pre code .sb { color: #BA2121 } /* Literal.String.Backtick */ 47 | pre code .sc { color: #BA2121 } /* Literal.String.Char */ 48 | pre code .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ 49 | pre code .s2 { color: #BA2121 } /* Literal.String.Double */ 50 | pre code .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 51 | pre code .sh { color: #BA2121 } /* Literal.String.Heredoc */ 52 | pre code .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 53 | pre code .sx { color: #008000 } /* Literal.String.Other */ 54 | pre code .sr { color: #BB6688 } /* Literal.String.Regex */ 55 | pre code .s1 { color: #BA2121 } /* Literal.String.Single */ 56 | pre code .ss { color: #19177C } /* Literal.String.Symbol */ 57 | pre code .bp { color: #008000 } /* Name.Builtin.Pseudo */ 58 | pre code .vc { color: #19177C } /* Name.Variable.Class */ 59 | pre code .vg { color: #19177C } /* Name.Variable.Global */ 60 | pre code .vi { color: #19177C } /* Name.Variable.Instance */ 61 | pre code .il { color: #666666 } /* Literal.Number.Integer.Long */ 62 | -------------------------------------------------------------------------------- /content/reference/resources/user/following.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "User Following" 3 | --- 4 | 5 | # Following 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Follow a User 11 | 12 | Returns the User object of the user being followed. 13 | 14 | <%= general_params_note_for "user" %> 15 | 16 | <%= endpoint "POST", "users/[user_id]/follow", "User", "follow" %> 17 | 18 | <%= url_params [ 19 | ["user_id","The user id to be followed. You can also specify @username as a user_id."] 20 | ]%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:post, "users/#{get_id(:user)}/follow", :user) do |h| 25 | h["data"]["you_follow"] = true 26 | end %> 27 | 28 | ## Unfollow a User 29 | 30 | Returns the User object of the user being unfollowed. 31 | 32 | <%= general_params_note_for "user" %> 33 | 34 | *Remember, access tokens cannot be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 35 | 36 | <%= endpoint "DELETE", "users/[user_id]/follow", "User", "follow" %> 37 | 38 | <%= url_params [ 39 | ["user_id","The user id to stop following. You can also specify @username as a user_id."] 40 | ]%> 41 | 42 | #### Example 43 | 44 | <%= curl_example(:delete, "users/#{get_id(:user)}/follow", :user) do |h| 45 | h["data"]["you_follow"] = false 46 | end %> 47 | 48 | ## List users a user is following 49 | 50 | Returns a list of User objects the specified user is following. 51 | 52 | <%= general_params_note_for "user" %> 53 | 54 | <%= pagination_note %> 55 | 56 | <%= endpoint "GET", "users/[user_id]/following", "Any" %> 57 | 58 | <%= url_params [ 59 | ["user_id","The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 60 | ]%> 61 | 62 | #### Example 63 | 64 | <%= curl_example(:get, "users/2/following", :user, {:response => :paginated}) do |h| 65 | h["meta"]["more"] = true 66 | h["data"][0]["pagination_id"] = "4621" 67 | end %> 68 | 69 | ## List users following a user 70 | 71 | Returns a list of User objects for users following the specified user. Please note that the pagination is not based on user or post ids. 72 | 73 | <%= general_params_note_for "user" %> 74 | 75 | <%= pagination_note %> 76 | 77 | <%= endpoint "GET", "users/[user_id]/followers", "Any" %> 78 | 79 | <%= url_params [ 80 | ["user_id","The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 81 | ]%> 82 | 83 | #### Example 84 | 85 | <%= curl_example(:get, "users/2/followers", :user, {:response => :paginated}) do |h| 86 | h["meta"]["more"] = true 87 | h["data"][0]["pagination_id"] = "2889" 88 | end %> 89 | 90 | ## List user ids a User is following 91 | 92 | Returns an array of user ids the specified user is following. 93 | 94 | <%= endpoint "GET", "users/[user_id]/following/ids", "Any" %> 95 | 96 | <%= url_params [ 97 | ["user_id","The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 98 | ]%> 99 | 100 | #### Example 101 | 102 | <%= curl_example(:get, "users/#{get_id(:user)}/following/ids", ["2", "3"]) %> 103 | 104 | ## List user ids following a user 105 | 106 | Returns an array of user ids for users following the specified user. 107 | 108 | <%= endpoint "GET", "users/[user_id]/followers/ids", "Any" %> 109 | 110 | <%= url_params [ 111 | ["user_id","The user id. If the user id is me the current authenticated user will be used. You can also specify @username as a user_id."] 112 | ]%> 113 | 114 | #### Example 115 | 116 | <%= curl_example(:get, "users/#{get_id(:user)}/followers/ids", ["2", "3"]) %> 117 | -------------------------------------------------------------------------------- /content/reference/resources/stream-marker/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Stream Marker" 3 | --- 4 | 5 | # Stream Marker 6 | 7 | * TOC 8 | {:toc} 9 | 10 | Stream markers allows a User's position in a stream of Posts to be synced between multiple App.net clients. Then when you go from the browser to your phone, your stream is right where you left off. The current stream marker will be included in the [response envelope](/reference/make-request/responses/#response-envelope) from any stream that returns Posts. 11 | 12 | ## Example Stream Marker 13 | 14 | If a Stream Marker hasn't yet been set, you will receive the following format: 15 | 16 | <%= json(:marker) %> 17 | 18 | A marker that has been set will look like this: 19 | 20 | <%= json(:full_marker) %> 21 | 22 | ## Stream Marker fields 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
FieldTypeDescription
idstringThe Post id of the Post at the top of the stream when this Stream's position was last synced.
last_read_idstringThe largest `id` the App.net server has seen for this stream marker. This is useful when determining what posts a user has seen regardless of whether they've scrolled backward in time. This value always increases unless it's explicitly set backwards.
namestringThe name of the Stream this marker is for.
percentageintegerAn optional field that indicate what percentage this post has been scrolled in the stream. It defaults to 0. This allows for very precise stream syncing but since different clients render Posts with different heights it won't be consistent across different clients.
updated_atstringThe time this marker was last updated in ISO 8601 format.
versionstringA unique identifier updated every time this Stream Marker is updated.
61 | 62 | ## Update a Stream Marker 63 | 64 | Update the User's current place in a Stream. To update a Stream Marker, you can POST an object that matches the [Stream Marker schema](/reference/resources/stream-marker/) with an HTTP header of `Content-Type: application/json`. Only the `id`, `name`, and `percentage` fields will be used. `name` will come from the marker you received in the last GET request you made for the stream. You can update multiple stream markers at once by POSTing a list of stream markers instead of a single one. 65 | 66 | The purpose of a Stream Marker is _not_ to allow a user to scroll a stream on one device and see the scroll happen on another device in realtime. A stream marker should only be updated when a user has stopped scrolling (i.e. the stream's position hasn't changed in multiple seconds) or when the app is being closed. Please make sure your code understands our [rate limit headers](/reference/make-request/rate-limits/#response-headers) so if the rate limits for this endpoint change in the future your app handles this gracefully. 67 | 68 | The `last_read_id` is updated if the provided `id` is larger than the current value of `last_read_id`. If you would like to explicitly set the `last_read_id` to a smaller value, you can pass the query string parameter `reset_read_id=1` when updating a stream marker. 69 | 70 | <%= endpoint "POST", "posts/marker", "User" %> 71 | 72 | #### Example 73 | 74 | <% data = { 75 | "name" => "global", 76 | "id" => "2" 77 | } %> 78 | 79 | <%= curl_example(:post, "posts/marker", :full_marker) do |h| 80 | h["data"]["id"] = h["data"]["last_read_id"] = data["id"] 81 | h["data"]["name"] = data["name"] 82 | h["data"]["updated_at"] = "2012-11-12T20:04:58Z" 83 | h["data"]["version"] = "d95o2uzYI7q7tY7bHI4U1xBug7s" 84 | end %> 85 | -------------------------------------------------------------------------------- /content/reference/resources/channel/subscriptions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Channel Subscriptions" 3 | --- 4 | 5 | # Channel Subscription 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Get current user's subscribed channels 11 | 12 | Retrieve an "inbox" of the channels the user is currently subscribed to. This stream is ordered like an inbox with the stream containing the most recent post first. 13 | 14 | The `meta` response will contain unread counts for common channel types. 15 | 16 | <%= general_params_note_for "channel" %> 17 | 18 | <%= pagination_note %> 19 | 20 | <%= endpoint "GET", "channels", "User", "public_messages
or messages"%> 21 | 22 | #### Example 23 | 24 | <%= curl_example(:get, "channels", :channel, {:response => :paginated}) do |h| 25 | h["data"][0]["pagination_id"] = "146" 26 | h["meta"]["more"] = true 27 | h["meta"]["unread_counts"] = { 28 | "net.app.core.pm" => 5, 29 | "net.app.core.broadcast" => 3 30 | } 31 | end %> 32 | 33 | ## Subscribe to a Channel 34 | 35 | Subscribe to a Channel. This adds it to your [Channel stream](#get-current-users-subscribed-channels). If a user has [muted this Channel](/reference/resources/channel/muting/#mute-a-channel), this call will automatically unmute the Channel. 36 | 37 | <%= general_params_note_for "channel" %> 38 | 39 | <%= endpoint "POST", "channels/[channel_id]/subscribe", "User", "public_messages or messages"%> 40 | 41 | <%= url_params [ 42 | ["channel_id", "The id of the Channel to subscribe to."] 43 | ]%> 44 | 45 | #### Example 46 | 47 | <%= curl_example(:post, "channels/1/subscribe", :channel) do |h| 48 | h["data"]["you_subscribed"] = true 49 | end %> 50 | 51 | ## Unsubscribe from a Channel 52 | 53 | Unsubscribe from a Channel. This removes it from your [Channel stream](#get-current-users-subscribed-channels). 54 | 55 | <%= general_params_note_for "channel" %> 56 | 57 | <%= endpoint "DELETE", "channels/[channel_id]/subscribe", "User", "public_messages or messages"%> 58 | 59 | <%= url_params [ 60 | ["channel_id", "The id of the Channel to unsubscribe from."] 61 | ]%> 62 | 63 | #### Example 64 | 65 | <%= curl_example(:delete, "channels/1/subscribe", :channel) do |h| 66 | h["data"]["counts"]["subscribers"] -= 1 67 | h["data"]["you_subscribed"] = false 68 | end %> 69 | 70 | ## Retrieve users subscribed to a Channel 71 | 72 | Retrieve the users who are subscribed to a Channel. 73 | 74 | <%= general_params_note_for "channel" %> 75 | 76 | <%= pagination_note %> 77 | 78 | <%= endpoint "GET", "channels/[channel_id]/subscribers", "Any", "public_messages or messages"%> 79 | 80 | <%= url_params [ 81 | ["channel_id", "The id of the Channel to retrieve subscribers for."] 82 | ]%> 83 | 84 | #### Example 85 | 86 | <%= curl_example(:get, "channels/1/subscribers", :channel, {:response => :paginated}) do |h| 87 | h["meta"]["more"] = true 88 | h["data"][0]["pagination_id"] = "82" 89 | end %> 90 | 91 | ## Retrieve user ids subscribed to a Channel 92 | 93 | Retrieve all the user ids who are subscribed to a Channel. 94 | 95 | <%= endpoint "GET", "channels/[channel_id]/subscribers/ids", "Any", "public_messages or messages"%> 96 | 97 | <%= url_params [ 98 | ["channel_id", "The id of the Channel to retrieve subscriber ids for."] 99 | ]%> 100 | 101 | #### Example 102 | 103 | <%= curl_example(:get, "channels/1/subscribers/ids", ["1"]) %> 104 | 105 | ## Retrieve user ids subscribed to multiple Channels 106 | 107 | For each requested Channel, retrieve the ids of all Users who are subscribed to that Channel. Up to 200 Channels may be requested at one time. Channels which do not exist or which the requesting user does not have authorization to view will not be returned. 108 | 109 | <%= endpoint "GET", "channels/subscribers/ids", "Any", "public_messages or messages"%> 110 | 111 | <%= query_params [ 112 | ["ids", "A comma separated list of Channel ids to retrieve subscriber ids for."] 113 | ]%> 114 | 115 | #### Example 116 | 117 | Channels 3 and 5 are omitted as if they are not visible or do not exist 118 | 119 | <%= curl_example(:get, "channels/1/subscribers/ids?ids=1,2,3,5", { 120 | "1" => ["5", "10"], 121 | "2" => ["5", "20"] 122 | }) %> 123 | -------------------------------------------------------------------------------- /content/reference/resources/message/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Message Lifecycle" 3 | --- 4 | 5 | # Message Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Create a Message 11 | 12 | Create a [Message](/reference/resources/message/) in the specified Channel. 13 | 14 | Send a JSON document that matches the [Message schema](/reference/resources/message/) with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `text`, `reply_to`, `annotations`, `entities`, and `machine_only`. 15 | 16 | If you would like to specify your own entities, please refer to the [user specified entites](/reference/meta/entities/#user-specified-entities) documentation, otherwise we will parse out links, hashtags, and mentions from the `text` field. 17 | 18 | If you want to test how your text will be processed you can use the [text processor](/reference/resources/text-processor). 19 | 20 | #### Creating Private Messages for use with net.app.core.pm Channels 21 | 22 | To create private group messages for use in `net.app.core.pm` channels, you can specify the special `channel_id` of `pm`. With this parameter, the server will look for an extra field in the provided message object called `destinations` which is a list of user ids to send this message to. If a private message channel already exists between this group of users, its `channel_id` will be reused. Otherwise, a new channel will be created and the users specified in the `destinations` list will be auto-subscribed (according to their [subscription preferences](https://account.app.net/settings/privacy/#messaging)) and able to write to that channel. Note that the `destinations` value may include user ids in the form of "@username" or integer id. 23 | 24 | <%= general_params_note_for "message" %> 25 | 26 | <%= endpoint "POST", "channels/[channel_id]/messages", "User" %> 27 | 28 | <%= url_params [ 29 | ["channel_id", 'The id of the Channel in which to create the Message. Alternatively, you can specify pm to auto-create/reuse a net.app.core.pm private message channel.'] 30 | ]%> 31 | 32 | #### Generic Channel Example 33 | 34 | <% data = { 35 | "text" => "Hello channel!", 36 | } %> 37 | <%= curl_example(:post, "channels/1/messages", :message, {:data => data}) %> 38 | 39 | #### PM Channel Example 40 | 41 | <% data = { 42 | "text" => "Hello channel!", 43 | "destinations" => ["@berg", 1] 44 | } %> 45 | <%= curl_example(:post, "channels/pm/messages", :message, {:data => data}) do |h| 46 | h["data"]["channel_id"] = "2" 47 | h["data"]["id"] = "105" 48 | h["data"]["thread_id"] = "105" 49 | end %> 50 | 51 | ## Delete a Message 52 | 53 | Delete a message. The current user must be the same user who created the Message. It returns the deleted Message on success. 54 | 55 | *You can always delete a message you created even if you are no longer able to view the rest of the Channel anymore.* 56 | 57 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 58 | 59 | <%= general_params_note_for "message" %> 60 | 61 | <%= endpoint "DELETE", "channels/[channel_id]/messages/[message_id]", "User", "public_messages or messages" %> 62 | 63 | <%= url_params [ 64 | ["channel_id", "The id of the Channel this Message belongs to."], 65 | ["message_id", "The id of the Message to delete."] 66 | ]%> 67 | 68 | #### Example 69 | 70 | <%= curl_example(:delete, "channels/1/messages/1", :message) do |h| 71 | h["data"]["is_deleted"] = true 72 | h["data"].delete("text") 73 | h["data"].delete("html") 74 | h["data"]["entities"].each { |k, v| h["data"]["entities"][k] = []} 75 | end %> 76 | 77 | 78 | ## Retrieve the Messages in a Channel 79 | 80 | Retrieve a stream of the Messages in a channel. 81 | 82 | <%= general_params_note_for "message" %> 83 | 84 | <%= pagination_note %> 85 | 86 | <%= endpoint "GET", "channels/[channel_id]/messages", "User", "public_messages or messages" %> 87 | 88 | <%= url_params [ 89 | ["channel_id", "The id of the Channel to retrieve Messages from."] 90 | ]%> 91 | 92 | #### Example 93 | 94 | <%= curl_example(:get, "channels/1/messages", :message, {:response => :paginated}) do |h| 95 | h["meta"]["marker"] = {"name" => "channel:1"} 96 | end %> 97 | -------------------------------------------------------------------------------- /content/reference/resources/filter/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Filter Lifecycle" 3 | --- 4 | 5 | # Filter Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Create a Filter 11 | 12 | Create a [Filter](/reference/resources/filter/) for the current user. 13 | 14 | Send a JSON document that matches the [Filter schema](/reference/resources/filter/) with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `name`, `match_policy` and `clauses`. 15 | 16 | <%= endpoint "POST", "filters", "User" %> 17 | 18 | #### Data 19 | 20 | A JSON object representing the [Filter](/reference/resources/filter/) to create. 21 | 22 | #### Example 23 | 24 | <% data = { 25 | "clauses" => [ 26 | { 27 | "field" => "/data/entities/hashtags/*/name", 28 | "object_type" => "post", 29 | "operator" => "matches", 30 | "value" => "rollout" 31 | } 32 | ], 33 | "id" => "1", 34 | "match_policy" => "include_any", 35 | "name" => "Posts about rollouts", 36 | }%> 37 | <%= curl_example(:post, "filters", :filter, {:data => data}) %> 38 | 39 | ## Retrieve a Filter 40 | 41 | Returns a specific [Filter](/reference/resources/filter/) object. 42 | 43 | <%= endpoint "GET", "filters/[filter_id]", "User" %> 44 | 45 | <%= url_params [ 46 | ["filter_id", "The id of the Filter to retrieve."] 47 | ]%> 48 | 49 | #### Example 50 | 51 | <%= curl_example(:get, "filters/1", :filter) %> 52 | 53 | ## Get current user's Filters 54 | 55 | Return the [Filter](/reference/resources/filter/) for the current user. 56 | 57 | <%= endpoint "GET", "filters", "User" %> 58 | 59 | #### Example 60 | 61 | <%= curl_example(:get, "filters", :filter, {:response => :collection}) %> 62 | 63 | ## Update a Filter 64 | 65 | Updates a specific [Filter](/reference/resources/filter/) object. When a filter is updated, all the streams using the filter will start using the new filter criteria. You can update a filter by PUTing an object that matches the [Filter schema](/reference/resources/filter/) with an HTTP header of `Content-Type: application/json`. The entire filter will be replaced with new value but it's `id` will remain the same. Please refer to the documentation on [how to create a Filter](#create-a-filter) for more information. 66 | 67 | <%= endpoint "PUT", "filters/[filter_id]", "User" %> 68 | 69 | <%= url_params [ 70 | ["filter_id", "The id of the Filter to update."] 71 | ]%> 72 | 73 | #### Example 74 | 75 | <% data = { 76 | "match_policy" => "include_any", 77 | "clauses" => [ 78 | { 79 | "operator" => "matches", 80 | "field" => "/data/entities/hashtags/*/name", 81 | "object_type" => "post", 82 | "value" => "rollout" 83 | }, { 84 | "operator" => "matches", 85 | "field" => "/data/entities/hashtags/*/name", 86 | "object_type" => "post", 87 | "value" => "bug" 88 | } 89 | ], 90 | "name" => "Posts about rollouts or bugs" 91 | } %> 92 | <%= curl_example(:put, "filters/1", :filter, {:data => data}) do |h| 93 | h["data"]["clauses"] = data["clauses"] 94 | h["data"]["name"] = data["name"] 95 | end %> 96 | 97 | ## Delete a Filter 98 | 99 | Delete a [Filter](/reference/resources/filter/). The Filter must belong to the current User. It returns the deleted Filter on success. 100 | 101 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 102 | 103 | <%= endpoint "DELETE", "filters/[filter_id]", "User" %> 104 | 105 | <%= url_params [ 106 | ["filter_id", "The id of the Filter to delete."] 107 | ]%> 108 | 109 | #### Example 110 | 111 | <%= curl_example(:delete, "filters/1", :filter) %> 112 | 113 | ## Delete all of the current user's Filters 114 | 115 | Delete all [Filters](/reference/resources/filter/) for the current user. It returns the deleted Filters on success. 116 | 117 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 118 | 119 | <%= endpoint "DELETE", "filters", "User" %> 120 | 121 | #### Example 122 | 123 | <%= curl_example(:delete, "filters", :filter, {:response => :collection}) %> 124 | -------------------------------------------------------------------------------- /content/reference/resources/app-stream/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "App Stream Lifecycle" 3 | --- 4 | 5 | # App Stream Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Create a Stream 11 | 12 | Create a [Stream](/reference/resources/app-stream/) for the current token. 13 | 14 | Send a JSON document that matches the [stream schema](/reference/resources/app-stream/) with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `object_types`, `type`, `filter_id` and `key`. If you don't want to specify a filter, omit `filter_id`. If you don't want to specify a key, omit `key`. 15 | 16 | You can create up to 5 streams per App token. 17 | 18 | <%= endpoint "POST", "streams", "App" %> 19 | 20 | #### POST Data 21 | 22 | A JSON object representing the stream to create. See [the stream object](/reference/resources/app-stream/) for more information. Specify `filter_id` instead of `filter` if you want to filter this stream. (Omit the `id` and `endpoint` parameters). 23 | 24 | #### Example 25 | 26 | <% data = { 27 | "object_types" => ["post"], 28 | "type" => "long_poll", 29 | "filter_id" => "1", 30 | "key" => "rollout_stream" 31 | } %> 32 | <%= curl_example(:post, "streams", :app_stream, {:data => data, :token => ""})%> 33 | 34 | 35 | ## Retrieve a Stream 36 | 37 | Returns a specific [Stream](/reference/resources/app-stream/) object. 38 | 39 | <%= endpoint "GET", "streams/[stream_id]", "App" %> 40 | 41 | <%= url_params [ 42 | ["stream_id", "The id of the Stream to retrieve."] 43 | ]%> 44 | 45 | #### Example 46 | 47 | <%= curl_example(:get, "streams/1", :app_stream, {:token => ""}) %> 48 | 49 | ## Get current token's Streams 50 | 51 | Return the [Streams](/reference/resources/app-stream/) for the current token. 52 | 53 | <%= endpoint "GET", "streams", "App" %> 54 | 55 | <%= query_params [ 56 | ["key", "(Optional) Only retrieve the stream that matches the given key."] 57 | ]%> 58 | 59 | #### Example 60 | 61 | <%= curl_example(:get, "streams?key=rollout_stream", :app_stream, {:response => :collection, :token => ""}) %> 62 | 63 | ## Update a Stream 64 | 65 | Update a [Stream](/reference/resources/app-stream/). You can update a Stream by PUTing a JSON document that matches the [stream schema](/reference/resources/app-stream/) with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `object_types`, `type`, `filter_id` and `key`. If you don't want to specify a filter, omit `filter_id`. If you don't want to specify a key, omit `key`. 66 | 67 | <%= endpoint "PUT", "streams/[stream_id]", "App" %> 68 | 69 | <%= url_params [ 70 | ["stream_id", "The id of the Stream to update."] 71 | ]%> 72 | 73 | #### Example 74 | 75 | <% data = { 76 | "object_types" => ["post","star"], 77 | "type" => "long_poll", 78 | "filter_id" => "1", 79 | "key" => "rollout_stream" 80 | } %> 81 | <%= curl_example(:put, "streams/1", :app_stream, {:data => data, :token => ""}) do |h| 82 | h["data"]["object_types"] = data["object_types"] 83 | end %> 84 | 85 | ## Delete a Stream 86 | 87 | Delete a [Stream](/reference/resources/app-stream/). The Stream must belong to the current User. It returns the deleted Stream on success. 88 | 89 | If you'd like your app stream to be automatically deleted when you disconnect from it, please add the [`auto_delete=1`](/reference/resources/user-stream/#limits) query string parameter when you connect to your app stream. 90 | 91 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 92 | 93 | <%= endpoint "DELETE", "streams/[stream_id]", "App" %> 94 | 95 | <%= url_params [ 96 | ["stream_id", "The id of the Stream to delete."] 97 | ]%> 98 | 99 | #### Example 100 | 101 | <%= curl_example(:delete, "streams/1", :app_stream, {:token => ""}) %> 102 | 103 | ## Delete all of the current user's Streams 104 | 105 | Delete all [Streams](/reference/resources/app-stream/) for the current token. It returns the deleted Streams on success. 106 | 107 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 108 | 109 | <%= endpoint "DELETE", "streams", "App" %> 110 | 111 | #### Example 112 | 113 | <%= curl_example(:delete, "streams", :app_stream, {:response => :collection, :token => ""}) %> 114 | -------------------------------------------------------------------------------- /content/docs/guides/messaging.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Messaging Overview" 3 | --- 4 | 5 | # App.net Messaging 6 | 7 | The App.net Messaging API allows a User to create public, private, semi-private messages between an arbitrary number of users. If you'd like to create public messages that your App.net followers see in their streams, you should [create a post](/reference/resources/post/lifecycle/#create-a-post) with the Stream API. If you need a more flexible messaging solution, the Messaging API is for you. 8 | 9 | Our messaging API is built around 2 central objects: [Channels](/reference/resources/channel/) and [Messages](/reference/resources/message/). If you're familiar with the App.net Stream API, here are some analogies: 10 | 11 | * Messages are like Posts 12 | * Channels are like streams of Posts 13 | * Stream markers work on Channels just like they work on streams of Posts 14 | 15 | When you create a Channel, you decide who can read and write to that channel. This flexibility lets you: 16 | 17 | * Create a private group chat between multiple App.net users 18 | * Create a moderated group that can be read by a set of users and written to by a different set of users 19 | * Create a chat room where App.net users can read and write messages while they're in the room and leave whenever they want 20 | 21 | If a user is authorized to read a Channel, they can also subscribe to a channel. This allows you to keep track of channels an messages at a more granular level. 22 | 23 | ## Authorization 24 | 25 | Access to Messages in a given Channel is determined by the [ACL fields](/reference/resources/channel/#acl-fields) on the Channel itself. 26 | 27 | Channels can be public or private. For the purpose of access tokens, a Channel is considered public if it is readable by unauthenticated users (the `public` flag) or any authenticated ADN user (the `any_user` flag). 28 | 29 | Application access to messages is governed by two scopes: `messages` and `public_messages`. The `messages` scope grants a superset of the permissions granted by the `public_messages` scope — it is unnecessary to request both scopes for a given application. The difference between the two is that only public Channels are visible to applications authorized with the `public_messages` scope. 30 | 31 | In addition, an App access token has read access to a Channel and its contents when: 32 | 33 | 1. the Channel is public, or 34 | 2. the Channel is private, and at least one user with read permission has authorized the application with the `messages` scope. 35 | 36 | ## Subscriptions 37 | 38 | Users indicate their interest in a given channel by subscribing to it. When a channel is created, no one is subscribed to it. 39 | 40 | [Private message channels](/reference/resources/channel/#private-message) (type `net.app.core.pm`) auto-subscribe all participants to the channel in accordance with each user's [subscription preferences](https://account.app.net/settings/privacy/#messaging). 41 | 42 | To get this same behavior for non-pm channels, you include the key `auto_subscribe: true` when you create or update the Channel. This will auto-subscribe all the users on the ACLs (according to their preferences). 43 | 44 | If a user has [muted a channel](/reference/resources/channel/muting/#mute-a-channel) they will never be auto-subscribed to it. 45 | 46 | ## Annotations 47 | 48 | Both Channel and Message objects allow for annotations; however, the details of each annotation implementation vary. Channel annotations act like User annotations — they are unique by type and mutable by the Channel's owner. Message annotations act like Post annotations — they are immutable. 49 | 50 | ## Markers 51 | 52 | The unread state of each Channel is tracked by a stream marker like those used for Posts. We suggest you do not advance a channel stream marker in reverse. When requested with a specific user token, each Channel exposes whether it contains a newer Message than the current marker position for the purpose of displaying an 'unread' indicator. 53 | 54 | ## Streaming 55 | 56 | Messages, channel updates and marker updates are pushed as objects over the streaming API. Channel permissions for the streaming API are related to the App access token as described above. Objects retrieved from the streaming API are not personalized to a given user. 57 | 58 | ## Types 59 | 60 | Much like annotation types, channel types are freeform strings; we suggest you use a reversed-domain format for any custom channel types. Core channel types are prefixed with `net.app.core` and may have additional validation imposed by the App.net API. Currently defined core channel types are: 61 | 62 | * [Private Message](/reference/resources/channel/#private-message): net.app.core.pm 63 | * [Broadcast Channel](/reference/resources/channel/#broadcast-channel): net.app.core.broadcast 64 | -------------------------------------------------------------------------------- /content/docs/guides/create-an-app.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Create an App" 3 | --- 4 | 5 | # Getting Started With Development 6 | 7 | To start accessing parts of the API that require authentication you will need an **access token**. The easiest way to create an access token is to register an app in your [account dashboard](https://account.app.net/settings/). 8 | 9 | ## Creating an App 10 | 11 | 1. Start by visiting [account.app.net/settings/](https://account.app.net/settings/). Click on "[Your Apps](https://account.app.net/developer/apps/)" in the bottom left hand corner to go to Your Apps Dashboard. 12 | 13 | ![Your Account Dashboard](https://files.app.net/01q1LmOn.png) 14 | 15 | 2. Click "[Create An App](https://account.app.net/developer/app/create/)." 16 | 17 | ![Your Apps Dashboard](https://files.app.net/2z0jz2E7Z.png) 18 | 19 | 3. Fill in information about your app. 20 | 21 | All of the form details are required but you can always edit them later if you'd like to change anything. Give your app a unique name and provide a URL for users to find out more information. If it doesn't make sense for you to enter a website feel free to use your Alpha profile URL: `https://app.net/{YOUR USERNAME}`. This will let others know who is responsible for this app. 22 | 23 | The *Redirect URL* is used when your app [authenticates new users](/reference/authentication/). If you're not sure what to fill in, you can use `http://localhost:8000` (which we've already filled in for you). 24 | 25 | Once all the fields are filled in, click "Create." 26 | 27 | ![Create Your App](https://files.app.net/01qdir2Q.png) 28 | 29 | 4. Your app is now created. From here you can copy your *Client ID* and *Client Secret* into your code and use them. You can also add additional *Redirect URLs* for other development or production environments. To generate an access token, follow the instructions in the next section of this page. 30 | 31 | ![Your New App](https://files.app.net/01qb1llv.png) 32 | 33 | ## Generating an Access Token 34 | 35 | There are a few ways to get an access token, but the easiest way to get an access token for personal use or experimentation is to generate one from your app detail page. 36 | 37 | 1. Visit [account.app.net/developer/apps/](https://account.app.net/developer/apps/). Find the app you would like to generate an access token for and click on the name. 38 | 39 | ![Your Apps Dashboard](https://files.app.net/01qlWgpd.png) 40 | 41 | 2. Click "Generate a user token for yourself" 42 | 43 | ![Generate a token](https://files.app.net/0q1t3Zt2.png) 44 | 45 | 3. Select the scopes for this token. 46 | 47 | To find out more about scopes your can [read the scope docs](/reference/authentication/#scopes). If you have previously generated a token, some of these boxes may already be checked. 48 | 49 | Once you have determined which scopes you will need select them in the form and then click "Generate." 50 | 51 | ![Scope Selection Screen](https://files.app.net/01qv_Geq.png) 52 | 53 | 4. You now have a user access token for your app. You can copy that into your code and use it with a [client library](/docs/libraries/) or directly from curl. 54 | 55 |
56 | Remember: An access token is just like a password. It will allow applications to interact with the API on your behalf. So, keep it secret. 57 |
58 | 59 | ![Your new access token](https://files.app.net/01lz9mQt.png) 60 | 61 | ## Launching your app 62 | 63 | Before you learn more about the API and start building your app, we want to make sure you know about some other opportunities for when you're ready to launch your app. 64 | 65 | ### Directory 66 | 67 | We want to make sure App.net users can find all the great apps that get created so we created the [App.net Directory](https://directory.app.net/). To include your app in the directory, you must [**register your app with us**](https://alpha.app.net/developer/apps/). For more information about how the directory, please see the [Directory Requirements](https://mml.desk.com/customer/portal/articles/779115-what-are-the-criteria-for-being-accepted-into-the-app-net-directory-). 68 | 69 | 70 | ### Developer Incentive Program 71 | 72 | To financially reward the development of great apps, [we announced the Developer Incentive Program](http://blog.app.net/2012/09/27/announcing-the-app-net-developer-incentive-program/). If you'd like to include your app you must [**register for the Developer Incentive Program**](https://alpha.app.net/developer/enrollment/). 73 | 74 | ## What's Next? 75 | 76 | Now that you have an access token you can use it to access authenticated parts of the API. 77 | 78 | You could: 79 | 80 | * [Send a broadcast](/docs/guides/send-a-broadcast/) 81 | * [Create a post](/docs/guides/create-a-post/) 82 | 83 | Or, you could build something completely new. We always love to see new apps. 84 | -------------------------------------------------------------------------------- /content/docs/guides/using-annotations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using Annotations" 3 | --- 4 | 5 | # Using Annotations 6 | 7 | * TOC 8 | {:toc} 9 | 10 | Annotations are metadata that can be attached to Users, Posts, Channels, Messages, or Files. This allows developers and users to add extra information to App.net objects outside of the fields App.net has already defined. 11 | 12 | ## What's so great about annotations? 13 | 14 | Annotations give developers a tremendous degree of freedom to expand upon the core functionality of App.net. They provide a way for developers to add arbitrary data to App.net objects, enabling richer content and new services. 15 | 16 | Let's say I'm at a restaurant eating a great dinner, but instead of just telling my followers about this restaurant I want them to be able to see a map of where it is. My Post could include geographic information about the address for the restaurant in an annotation and then clients that support this geographic annotation could show the restaurant on a map (in addition to showing my post). If the restaurant is on [OpenTable](http://www.opentable.com), I could include an annotation indicating that and my followers could see the menu and make a reservation in their own App.net client. 17 | 18 | ## Anatomy of an annotation 19 | 20 | Annotations are a list of objects that have a `type` and a `value`. 21 | 22 | <%= json_output([ 23 | { 24 | "type" => "com.example.awesome", 25 | "value" => { 26 | "annotations work" => "beautifully" 27 | } 28 | } 29 | ]) %> 30 | 31 | The `type` field identifies essentially a schema for the `value` of the annotation. Please see the [annotations reference](/reference/meta/annotations/#documenting-annotations) for more information about different kinds of annotations. 32 | 33 | ## Example: Attach an image to a post 34 | 35 | When you see an image included in an App.net post, you see the results of annotations at work. We'll be using the [`net.app.core.oembed`](https://github.com/appdotnet/object-metadata/blob/master/annotations/net.app.core.oembed.md) annotation to embed a photo in an App.net post. 36 | 37 | <% data = { 38 | "text" => "Hello App.net from curl, with a photo!", 39 | "annotations" => [ 40 | { 41 | "type" => "net.app.core.oembed", 42 | "value" => { 43 | "type" => "photo", 44 | "version" => "1.0", 45 | "width" => 870, 46 | "height" => 106, 47 | "url" => "https://files.app.net/2jxk2CoP4", 48 | "thumbnail_width" => 200, 49 | "thumbnail_height" => 24, 50 | "thumbnail_url" => "https://files.app.net/2jxk12R7F", 51 | "embeddable_url" => "https://app.net" 52 | } 53 | } 54 | ] 55 | } %> 56 | <%= curl_example(:post, "posts?include_annotations=1", :none, {:data => data}) %> 57 | 58 | Most clients expect `thumbnail_url`, `thumbnail_width`, and `thumbnail_height` to render a preview inline with the post. 59 | 60 | ## Example: Attach an App.net file to a post as an image 61 | 62 | Most apps that include images don't generate a raw oembed annotation to an image hosted somewhere else, they use the [App.net File storage](/reference/resources/files/). To do this, first you have to upload a file to App.net and then you have to create the post with an annotation as we did above. 63 | 64 | ### Upload a file 65 | 66 | <%= curl_example(:post, "files", :none, { 67 | :files => { 68 | "type" => "testing.image", 69 | "content" => "@filename.png;type=image/png", 70 | } 71 | }) %> 72 | 73 | 74 | This will return a JSON blob similar with the following fields we care about: 75 | 76 | <%= json_output({ 77 | "data" => { 78 | "file_token" => "1234567NQD4isqELTZlIiEd9fp24e5wC1NACSYFI_Svc7-hkvCKWOTsOPQLrrMiVu-9x2L400MbKlG4T8-WA97HokUdApqXwtQjJt9wOJ12ZZX_hZSFmj_O0xFlvJt8rwqaTAOvK7qECaj1LS131baLjJojErPB5TwZiQQJko0BU", 79 | "id" => "123", 80 | }, 81 | }) %> 82 | 83 | ### Attach the file to a post 84 | 85 | Once we've uploaded the file, we can attach it to a post and let App.net generate the correct oembed annotation: 86 | 87 | <% data = { 88 | "text" => "Hello App.net from curl, with an App.net hosted photo!", 89 | "annotations" => [{ 90 | "type" => "net.app.core.oembed", 91 | "value" => { 92 | "+net.app.core.file" => { 93 | "file_id" => "", 94 | "file_token" => "", 95 | "format" => "oembed" 96 | } 97 | } 98 | }] 99 | } %> 100 | <%= curl_example(:post, "posts?include_annotations=1", :none, {:data => data}) %> 101 | 102 | Since annotations can contain up to [8192 bytes of data](/reference/meta/annotations/#limit), they are not returned by default. We have to explicitly request that App.net return annotations by passing the `include_annotations=1` query string parameter. 103 | -------------------------------------------------------------------------------- /content/reference/other/feeds.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Feeds" 3 | --- 4 | 5 | # Feeds 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Basic Use 11 | 12 | Feeds describe our system for simple syndication of public posts on App.net. We currently support RSS as a syndication format. This means you should be able to use them anywhere you currently use RSS feeds. 13 | 14 | There are 2 different kinds of feeds, but they all follow the same pattern: 15 | 16 | * Users Post feed: A feed for a single User's public posts on App.net. This is a feed version of the [Retrieve Posts created by a User](/reference/resources/post/streams/#retrieve-posts-created-by-a-user) endpoint. 17 | * Hashtag feed: A feed containing all public Posts that are tagged with a specific hashtag. This is a feed version of the [Retrieve tagged Posts](/reference/resources/post/streams/#retrieve-tagged-posts) endpoint. 18 | 19 | We intend to support more feed formats and richer support for filters in the near future. 20 | 21 | While the URLs are similar to other API URLs feeds, they are under a different root. 22 | 23 | ## Filters 24 | 25 | Feeds do not currently support filters or general parameters like the JSON API. 26 | 27 | ## Response Format 28 | 29 | All responses are returned as RSS. We are following the spec for RSS 2.0 as described in the [RSS 2.0 specification](http://cyber.law.harvard.edu/rss/rss.html). 30 | 31 | ## Retrieve a feed for a User 32 | 33 | Retrieve a feed for the User [@voidfiles](http://alpha.app.net/voidfiles). This endpoint is similar to the [Retrieve Posts created by a User](/reference/resources/post/streams/#retrieve-posts-created-by-a-user) endpoint. 34 | 35 | ### URL 36 | > https://alpha-api.app.net/feed/rss/users/@username/posts 37 | 38 | ### Example 39 | 40 | <% response = %q{ 41 | 42 | 43 | Posts from voidfiles on App.net 44 | https://alpha.app.net/voidfiles 45 | Hi, I work at App.net 46 | 47 | 48 | Posts from voidfiles on App.net 49 | https://alpha.app.net/voidfiles 50 | https://dqdwyydysypcm.cloudfront.net/image/4/Go50UQd5N9mi_APkpQt9JAp4ZsDfMlOTnoB4P-0N5rmpFGtnro2b52yUcUr_bPbxKlxx_4EHHiujdE-RRpSB6oZd0bHGy4xKlwInNBClbebDS7DoyyPHtIK9LY5x-kQSdnPKyKhtogJxD04SGOQMLPkCasZM42nLVgZIIhcbmbBrzxNJaoRoCNOrzS1ib9fQcAwPEg 51 | 52 | 53 | voidfiles: #hashtag test 54 | 55 | #hashtag test 56 | 57 | Fri, 31 Aug 2012 17:15:31 +0000 58 | https://alpha.app.net/voidfiles/post/1387 59 | https://alpha.app.net/voidfiles/post/1387 60 | hashtag 61 | 62 | 63 | } %> 64 | 65 | <%= curl_example(:get, "users/@voidfiles/posts", response, { 66 | :token => nil, 67 | :response => :raw, 68 | :response_syntax => "xml", 69 | :path_prefix => "/feed/rss/", 70 | }) %> 71 | 72 | ## Retrieve a feed for a hashtag 73 | 74 | Retrieve a feed for the specified hashtag. This endpoint is similar to the [Retrieve tagged Posts](/reference/resources/post/streams/#retrieve-tagged-posts) endpoint. 75 | 76 | ### URL 77 | > https://alpha-api.app.net/feed/rss/posts/tag/hashtag 78 | 79 | ### Example 80 | 81 | <% response = %q{ 82 | 83 | 84 | #hashtag - App.net 85 | https://alpha.app.net/hashtags/hashtag 86 | Posts about #hashtag 87 | 88 | 89 | voidfiles: #hashtag test 90 | 91 | #hashtag test 92 | 93 | Fri, 31 Aug 2012 17:15:31 +0000 94 | https://alpha.app.net/voidfiles/post/1387 95 | https://alpha.app.net/voidfiles/post/1387 96 | hashtag 97 | 98 | 99 | } %> 100 | 101 | <%= curl_example(:get, "posts/tag/hashtag", response, { 102 | :token => nil, 103 | :response => :raw, 104 | :response_syntax => "xml", 105 | :path_prefix => "/feed/rss/", 106 | }) %> 107 | -------------------------------------------------------------------------------- /content/reference/resources/message/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Message Search" 3 | --- 4 | 5 | # Search 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Search for Messages 11 | 12 | Returns [Message](/reference/resources/message/) objects which match a given search query. This endpoint responds to a list of channel IDs which can either given specifically or performed on all PM or Broadcast channels that the user is subscribed to. Searches can either be ordered by `id` or `score`. Searches ordered by `id` require at least one query or filter to be specified; searches ordered by `score` require at least one query and zero or more filters to be specified. All parameters should be passed in the query string. 13 | 14 | All queries and filters are combined with an AND operation. Query parameters (not filter parameters) can use "quoted strings" for phrases, search syntax like +foo -bar and foo OR baz for boolean queries. Separate lists of terms by spaces. 15 | 16 | <%= general_params_note_for "message" %> 17 | 18 | <%= endpoint "GET", "channels/messages/search", "Any" %> 19 | 20 | <%= query_params_typed 'General Parameters', [ 21 | 22 | ["index", :optional, "string", "Type of index to use. The default (and currently, the only) index is complete, which searches all messages. We may add additional index types later (e.g., an index only of recent messages, for speed.)"], 23 | 24 | ["order", :optional, "string", "One of: id (default), score. Searches of ordering id are returned in roughly the same order as other streams. Searches of ordering score are returned by a relevance score."], 25 | 26 | ]%> 27 | 28 | <%= query_params_typed 'Search Query Parameters', [ 29 | 30 | ["query", :optional, "string", "Automatically attempts to extract hashtags and mentions while searching text. If you do not want this behavior, you can use more specific parameters below."], 31 | ["text", :optional, "string", "Include messages containing certain text."], 32 | ["channel_ids", :required, "string", "Specifies the list of channels to search through. This must either be a list of IDs or one of `pm`, `broadcast`. Channel ACLs will be respected (read permission must be granted to the user)."], 33 | 34 | 35 | ]%> 36 | 37 | <%= query_params_typed 'Filter Parameters', [ 38 | ["hashtags", :optional, "string", "Only include messages tagged with certain hashtags. Do not include #"], 39 | ["links", :optional, "string", "Only include messages linking to certain URLs"], 40 | ["link_domains", :optional, "string", "Only include messages linking to certain domains. Do not include \"www.\""], 41 | ["mentions", :optional, "string", "Only include messages mentioning certain users, by username. Do not include @"], 42 | ["leading_mentions", :optional, "string", "Only include messages directed at users, by username. Do not include @"], 43 | ["annotation_types", :optional, "string", "Only include messages with a specific annotation type, e.g., net.app.core.fallback_url"], 44 | ["attachment_types", :optional, "string", "Only include messages with a specific file type attached via the net.app.core.file_list annotation"], 45 | ["place_id", :optional, "string", "Only include messages which are check-ins at a specific place, via the net.app.core.checkin annotation"], 46 | 47 | ["is_reply", :optional, "int (0 or 1)", "Only include replies"], 48 | ["is_directed", :optional, "int (0 or 1)", "Only include messages with leading mentions, i.e., messages which were directed at other users"], 49 | ["has_location", :optional, "int (0 or 1)", "Only include messages containing geo coordinates, i.e., tagged with the net.app.core.geolocation annotation"], 50 | ["has_checkin", :optional, "int (0 or 1)", "Only include messages containing place IDs, i.e., tagged with the net.app.core.checkin annotation"], 51 | ["has_attachment", :optional, "int (0 or 1)", "Only include messages with file attachments"], 52 | ["has_oembed_photo", :optional, "int (0 or 1)", "Only include messages with photo oembed annotations"], 53 | ["has_oembed_video", :optional, "int (0 or 1)", "Only include messages with video (not html5video) oembed annotations"], 54 | ["has_oembed_html5video", :optional, "int (0 or 1)", "Only include messages with html5video oembed annotations"], 55 | ["has_oembed_rich", :optional, "int (0 or 1)", "Only include messages with rich oembed annotations"], 56 | 57 | ["language", :optional, "string", "Only include messages with a certain language tagged with the net.app.core.language annotation."], 58 | ["client_id", :optional, "string", "Only include messages created by a certain app. Use the alphanumeric client_id"], 59 | ["creator_id", :optional, "string", "Only include messages created by a specific user. Use the user ID, not the username"], 60 | ["reply_to", :optional, "string", "Only include immediate replies to a given message ID"], 61 | ["thread_id", :optional, "string", "Only include messages on a specific thread"], 62 | 63 | ]%> 64 | 65 | #### Example 66 | 67 | <%= curl_example(:get, "channels/messages/search?query=hello&channel_ids=1&count=1", :message, {:response => :paginated}) do |h| 68 | h["meta"]["count"] = 1 69 | end %> 70 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/post.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
DescriptionMethodPathToken
Create a PostPOST/stream/0/postsUser
Retrieve a PostGET/stream/0/posts/{post_id}None
Delete a PostDELETE/stream/0/posts/{post_id}User
Repost a PostPOST/stream/0/posts/{post_id}/repostUser
Unrepost a PostDELETE/stream/0/posts/{post_id}/repostUser
Star a PostPOST/stream/0/posts/{post_id}/starUser
Unstar a PostDELETE/stream/0/posts/{post_id}/starUser
Retrieve multiple PostsGET/stream/0/postsAny
Retrieve a User's postsGET/stream/0/users/{user_id}/postsNone
Retrieve a User's starred postsGET/stream/0/users/{user_id}/starsNone
Retrieve Posts mentioning a UserGET/stream/0/users/{user_id}/mentionsAny
Retrieve Posts containing a hashtagGET/stream/0/posts/tag/{hashtag}None
Retrieve replies to a PostGET/stream/0/posts/{post_id}/repliesAny
Retrieve a User's personalized streamGET/stream/0/posts/streamUser
Retrieve a User's unified streamGET/stream/0/posts/stream/unifiedUser
Retrieve the Global streamGET/stream/0/posts/stream/globalNone
Report a PostPOST/stream/0/posts/{post_id}/reportUser
Search for PostsGET/stream/0/posts/searchAny
121 | -------------------------------------------------------------------------------- /content/reference/resources/post/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Post Search" 3 | --- 4 | 5 | # Search 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Search for Posts 11 | 12 | Returns [Post](/reference/resources/post/) objects which match a given search query. Searches ordered by `id` require at least one query or filter to be specified; searches ordered by `score` require at least one query and zero or more filters to be specified. Searches require an ordering and at least one search query to be specified, and allow for zero or more filters to be added. All parameters should be passed in the query string. 13 | 14 | All queries and filters are combined with an AND operation. Query parameters (not filter parameters) can use "quoted strings" for phrases, search syntax like +foo -bar and foo OR baz for boolean queries. Machine-only posts are not included in the search index. Separate lists of terms by spaces. 15 | 16 | <%= general_params_note_for "post" %> 17 | 18 | <%= endpoint "GET", "posts/search", "Any" %> 19 | 20 | <%= query_params_typed 'General Parameters', [ 21 | 22 | ["index", :optional, "string", "Type of index to use. The default (and currently, the only) index is complete, which searches all posts. We may add additional index types later (e.g., an index only of recent posts, for speed.)"], 23 | 24 | ["order", :optional, "string", "One of: id (default), score. Searches of ordering id are returned in roughly the same order as other streams. Searches of ordering score are returned by a relevance score."], 25 | 26 | ]%> 27 | 28 | <%= query_params_typed 'Search Query Parameters', [ 29 | 30 | ["query", :optional, "string", "Automatically attempts to extract hashtags and mentions while searching text. If you do not want this behavior, you can use more specific parameters below."], 31 | ["text", :optional, "string", "Include posts containing certain text."], 32 | 33 | 34 | ]%> 35 | 36 | <%= query_params_typed 'Filter Parameters', [ 37 | ["hashtags", :optional, "string", "Only include posts tagged with certain hashtags. Do not include #"], 38 | ["links", :optional, "string", "Only include posts linking to certain URLs"], 39 | ["link_domains", :optional, "string", "Only include posts linking to certain domains. Do not include \"www.\""], 40 | ["mentions", :optional, "string", "Only include posts mentioning certain users, by username. Do not include @"], 41 | ["leading_mentions", :optional, "string", "Only include posts directed at users, by username. Do not include @"], 42 | ["annotation_types", :optional, "string", "Only include posts with a specific annotation type, e.g., net.app.core.fallback_url"], 43 | ["attachment_types", :optional, "string", "Only include posts with a specific file type attached via the net.app.core.file_list annotation"], 44 | ["crosspost_url", :optional, "string", "Only include posts which are crossposts of a specific URL, via the net.app.core.crosspost annotation"], 45 | ["crosspost_domain", :optional, "string", "Similar to crosspost_url, but only match on the host portion of the URL. Do not include \"www.\""], 46 | ["place_id", :optional, "string", "Only include posts which are check-ins at a specific place, via the net.app.core.checkin annotation"], 47 | 48 | ["is_reply", :optional, "int (0 or 1)", "Only include replies"], 49 | ["is_directed", :optional, "int (0 or 1)", "Only include posts with leading mentions, i.e., posts which were directed at other users"], 50 | ["has_location", :optional, "int (0 or 1)", "Only include posts containing geo coordinates, i.e., tagged with the net.app.core.geolocation annotation"], 51 | ["has_checkin", :optional, "int (0 or 1)", "Only include posts containing place IDs, i.e., tagged with the net.app.core.checkin annotation"], 52 | ["is_crosspost", :optional, "int (0 or 1)", "Only include posts which are crossposts, i.e., tagged with the net.app.core.crosspost annotation"], 53 | ["has_attachment", :optional, "int (0 or 1)", "Only include posts with file attachments"], 54 | ["has_oembed_photo", :optional, "int (0 or 1)", "Only include posts with photo oembed annotations"], 55 | ["has_oembed_video", :optional, "int (0 or 1)", "Only include posts with video (not html5video) oembed annotations"], 56 | ["has_oembed_html5video", :optional, "int (0 or 1)", "Only include posts with html5video oembed annotations"], 57 | ["has_oembed_rich", :optional, "int (0 or 1)", "Only include posts with rich oembed annotations"], 58 | 59 | ["language", :optional, "string", "Only include posts with a certain language tagged with the net.app.core.language annotation."], 60 | ["client_id", :optional, "string", "Only include posts created by a certain app. Use the alphanumeric client_id"], 61 | ["creator_id", :optional, "string", "Only include posts created by a specific user. Use the user ID, not the username"], 62 | ["reply_to", :optional, "string", "Only include immediate replies to a given post ID"], 63 | ["thread_id", :optional, "string", "Only include posts on a specific thread"], 64 | 65 | ]%> 66 | 67 | #### Example 68 | 69 | <%= curl_example(:get, "posts/search?hashtags=adnhack&count=-1", :post, {:response => :paginated}) do |h| 70 | h["meta"]["count"] = 1 71 | h["data"][0]["pagination_id"] = "10000" 72 | end %> 73 | -------------------------------------------------------------------------------- /content/reference/resources/file/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "File Lifecycle" 3 | --- 4 | 5 | # File Lifecycle 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Create a File 11 | 12 | Create a new [File](/reference/resources/file/). 13 | 14 | An App.net File object can be created without setting the file content. This is called an "incomplete" file object. To create an incomplete file object, POST a JSON document that matches the [File schema](/reference/resources/file/) with an HTTP header of `Content-Type: application/json`. Currently, the only keys we use from your JSON will be `kind`, `type`, `name`, `public` and `annotations`. You can also send those keys as standard form data instead of as JSON. Once you have an incomplete file object, you can [set the file content](/reference/resources/file/content/#set-file-content) in a later request. 15 | 16 | You can also create a complete File object with one request by including the file content with the File metadata. To create a complete file object, send a POST with an HTTP header of `Content-Type: multipart/form-data`. Our API expects one part of the request body to contain a `Content-Disposition` header with a value for `filename` and `name="content"`. The data from this part will be used as the file's content. If you wish to send your data as Base64 encoded instead of as a byte stream you must include a `Content-Transfer-Encoding: base64` header. If there is a part with `name="metadata"` and `Content-Type: application/json` then we will parse that JSON as the file's metadata. Otherwise, we will construct the metadata from the `form-data` sent in the request body. If you send extra parts with a value for `filename`, the `name` 17 | 18 | When creating a complete file, this endpoint could return a `507 Insufficient Storage` error if the user doesn't have enough space for this file. For more information, see [file storage limits](/reference/resources/file/#limits). 19 | 20 | <%= general_params_note_for "file" %> 21 | 22 | <%= endpoint "POST", "files", "User" %> 23 | 24 | <%= file_token_reminder %> 25 | 26 | #### Example 27 | 28 | ##### JSON Metadata 2 29 | 30 | The most comprehensive way to to specify a file's attributes are to upload json data that fits the File schema with the file itself. 31 | 32 | <%= curl_example(:post, "files", :none, { 33 | :files => { 34 | "metadata" => "@-;type=application/json", 35 | "content" => "@filename.jpg", 36 | }, 37 | :stdin => JSON.pretty_generate({ 38 | "type" => "com.example.test", 39 | "annotations" => [ 40 | { 41 | "type" => "com.example.annotation", 42 | "value" => { 43 | "foo" => "bar" 44 | } 45 | } 46 | ] 47 | }) 48 | }) %> 49 | 50 | ##### Form-data metadata 51 | 52 | The metadata can also be submitted as normal post data. If you want to create annotations on the file, you must use the JSON metadata format to do so. 53 | 54 | Here is some [sample File upload code written in Python](https://gist.github.com/4659409). You can also use the following curl command to upload a file: 55 | 56 | <%= curl_example(:post, "files", :none, { 57 | :files => { 58 | "type" => "com.example.test", 59 | "content" => "@filename.jpg", 60 | }, 61 | }) %> 62 | 63 | ##### Custom derived files 64 | 65 | If you'd like to upload [custom derived files](/reference/resources/file/#derived-files) at the same time as the original file, you can include the derived files as extra parts: 66 | 67 | <%= curl_example(:post, "files", :file, { 68 | :files => { 69 | "type" => "com.example.test", 70 | "content" => "@filename.jpg", 71 | "derived_key1" => "@derived_file1.png;type=image/png", 72 | "derived_key2" => "@derived_file2.png;type=image/png", 73 | } 74 | }) %> 75 | 76 | ## Update a File 77 | 78 | Updates a specific [File](/reference/resources/file/) object. You can update a file by PUTing an object that matches the [File schema](/reference/resources/file/) with an HTTP header of `Content-Type: application/json`. The only keys that can be updated are `annotations`, `name` and `public`. Only the File owner can update a File. 79 | 80 | This endpoint currently works identically for the `PUT` and `PATCH` HTTP methods. 81 | 82 | <%= general_params_note_for "file" %> 83 | 84 | <%= endpoint "PUT", "files/[file_id]", "User"%> 85 | 86 | <%= file_token_reminder %> 87 | 88 | <%= url_params [ 89 | ["file_id", "The id of the File to update."] 90 | ]%> 91 | 92 | #### Example 93 | 94 | <% data = {"name" => "update_filename.jpg"}%> 95 | <%= curl_example(:put, "files/1", :file, {:data => data}) do |h| 96 | h["data"]["name"] = data["name"] 97 | end %> 98 | 99 | ## Delete a File 100 | 101 | Delete a file. The current user must be the same user who created the File. It returns the deleted File on success. *Since a File could be referenced by multiple resources we recommend that you don't automatically delete files when you delete Posts. Deleting a file should be a more explicit action taken by the user.* 102 | 103 | *Remember, access tokens can not be passed in a HTTP body for `DELETE` requests. Please refer to the [authentication documentation](/reference/authentication/#making-authenticated-api-requests).* 104 | 105 | <%= general_params_note_for "file" %> 106 | 107 | <%= endpoint "DELETE", "files/[file_id]", "User" %> 108 | 109 | <%= file_token_reminder %> 110 | 111 | <%= url_params [ 112 | ["file_id", "The id of the File to delete."] 113 | ]%> 114 | 115 | #### Example 116 | 117 | <%= curl_example(:delete, "files/1", :file) %> 118 | -------------------------------------------------------------------------------- /content/reference/authentication/flows/password.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Password Flow" 3 | --- 4 | 5 | # Password Flow 6 | 7 | * TOC 8 | {:toc} 9 | 10 | This flow is useful for obtaining an access token authorized for specific scopes when pushing the user into a browser-based flow is impractical for technical or user-experience reasons. 11 | 12 | This is referred to as the Resource Owner Password Credential flow in the OAuth 2.0 spec. However, in order to protect the integrity of `client_secret`s, we require the use of a separate token to be included with flows. 13 | 14 | ## Obtaining approval to use the password flow 15 | 16 | **Your application must be specifically approved to use this flow.** To obtain authorization, go to your [App.net developer dashboard](https://account.app.net/developer/apps/), select your app, and click **Request approval for password flow**. You will need to provide an explanation of your situation and then click the **Submit Request** button to complete your request for authorization. When your request has been approved you will receive an email with your password grant secret. The password grant secret token will also be available on your account page. 17 | 18 | ## Rules 19 | 20 | **Security of user accounts is the most important thing.** When in doubt, err on the side of securing user password information, rather than optimizing for user experience. 21 | 22 | > Some of these rules might limit what you can do with your app. Please do not attempt to circumvent them, or we will disable your application token. That may sound harsh, but it is of utmost importance that we protect the integrity of the service and the security of user accounts. 23 | 24 | > These flows should only be used in cases where browser-based authentication is impractical. For one-off applications, shell scripts, etc., please generate an access token for your app via [My Apps](https://account.app.net/developer/apps/). 25 | 26 | 1. **NEVER** store user password information, no matter how securely. Users should be able to disable access to your application at any time by revoking authorization. Access tokens are designed not to expire unless users take explicit action, so there is no need to build in a mechanism to reauthenticate that would require storing passwords. 27 | 1. **NEVER** send user password information over the network, except to the prescribed App.net OAuth endpoint. 28 | 1. **NEVER** log user password information, even debug logging to your app or device's console. It is too easy to accidentally leak password information this way. 29 | 1. Users **MUST** have a way to see which scopes are being requested by an application. This can be behind a "more info" button, but must at least be exposed on the login screen, before users are required to enter their password information to continue. 30 | 1. If an error is returned from the OAuth endpoint, it **MUST** be displayed to users verbatim. 31 | 1. If these rules are updated, application developers must make reasonable attempts to comply with new regulations wherever possible. 32 | 33 | ## Procedure 34 | 35 | > By default **users will receive an email each time they authorize an application with this flow** listing the name of the application, the scopes requested and the time that authorization was performed. 36 | 37 | Once you have been approved, using the password flow is pretty straightforward: 38 | 39 | 1. From your client, make a request to the token endpoint: 40 | 41 | POST https://account.app.net/oauth/access_token 42 | 43 | with URL-encoded POST body: 44 | 45 | client_id=[your client ID] 46 | &password_grant_secret=[your password grant secret, not your client secret] 47 | &grant_type=password 48 | &username=[user's email or username] 49 | &password=[user's password] 50 | &scope=[scopes separated by spaces] 51 | 52 | Example: 53 | 54 | <%= curl_example(:post, "access_token", :none, { 55 | :subdomain => "account", 56 | :path_prefix => "/oauth/", 57 | :pretty_json => false, 58 | :token => nil, 59 | :content_type => nil, 60 | :data => { 61 | "grant_type" => "password", 62 | "client_id" => "[your client_id]", 63 | "password_grant_secret" => "[your password grant secret that was emailed to you]", 64 | "username" => "[user's email address or username]", 65 | "password" => "[user's password]", 66 | "scope" => "[scopes separated by spaces]", 67 | } 68 | }) %> 69 | 70 | > The use of `password_grant_secret` diverges from the OAuth 2.0 specification. `password_grant_secret` is a special token that we'll send you when your use of the password flow is approved. 71 | 72 | > **You can require app-specific passwords** by providing a `require_app_specific_password=1` URL parameter. **[Two-Factor Auth users](http://blog.app.net/2013/03/13/added-security-for-your-app-net-account/) must use app-specific passwords** regardless of this parameter. We strongly encourage the use of app-specific passwords by all users as they significantly increase account security. 73 | 74 | 1. If the authorization was successful, App.net will respond with a JSON-encoded token: 75 | 76 | {"access_token": "[user access token]", "token": {...Token object...}} 77 | 78 | You can use this access_token to make authenticated calls to the App.net API on behalf of a user. 79 | 80 | 1. If authentication failed or there was another error, App.net will respond with an error: 81 | 82 | {"error": "Authentication failed"} 83 | 84 | If the `error_text` key is present in this dictionary, you **MUST** show a modal dialog or equivalent containing this text. If possible, you should include value of the `error_title` key as a title in your dialog. 85 | -------------------------------------------------------------------------------- /content/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Home" 3 | --- 4 | 5 | # App.net API Documentation 6 | 7 | App.net is a developer-friendly social infrastructure platform. Our API is the primary interface by which developers interact with the platform. The documentation is broken into two parts: these guides and our [full API reference](/reference/). 8 | 9 | ## Quick Start 10 | 11 | The App.net API is powerful and flexible -- if you're new to the API, we suggest you start with these guides. 12 | 13 |
14 |
15 |
16 |
17 |
18 | 19 |
20 |

21 | Quick Start: Broadcast
22 |

23 |

Send a broadcast with the App.net API.

24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 |
32 |

33 | Quick Start: Authentication
34 |

35 |

Learn how to make authenticated requests to the API.

36 |
37 |
38 |
39 |
40 |
41 | 42 | ## Notable API features 43 | 44 | ### Identity & Authentication 45 | 46 | Use App.net's identity layer to authenticate users and populate user profiles. For more information, see the [Authentication reference](/reference/authentication/) and [User reference](/reference/resources/user/). 47 | 48 | ### Social Graph 49 | 50 | App.net has a asymmetrical (follower-following) social graph which can be used to solve the "cold start" problem when a user signs into your app. The [Following reference](/reference/resources/user/following/) has more details. 51 | 52 | ### Messaging 53 | 54 | Channels are like chat rooms. They're a time ordered series of messages that can be public, private, or restricted to a group of App.net users. The messages inside of channels can take advantage of App.net files, places, and anything else the API provides. [Chat rooms](https://directory.app.net/app/145/patter/), [Broadcasts](http://blog.app.net/2013/11/21/announcing-app-net-broadcast/), and private messages are all built on top of [App.net Messaging](/docs/guides/messaging/). 55 | 56 | ### Places 57 | 58 | App.net has a location database that can be integrated with your app. This allows you to add location to Posts or Message to enable location aware apps. See the [Places reference](/docs/references/resources/places/) for more information. 59 | 60 | ### Annotations 61 | 62 | Annotations are machine readable metadata that can be attached to most App.net objects (posts, messages, users, and more). They power [checkins](https://alpha.app.net/browse/checkins/), [photos](https://alpha.app.net/browse/photos/) and other rich posts on App.net. See the [Annotations introduction](/docs/references/resources/meta/annotations/) to get started. 63 | 64 | ### Files 65 | 66 | App.net gives each user space to store and share files. These files can be shared publicly, attached to posts, or sent as a private message to a friend. All App.net apps share the same file storage space so if a new photo or video app comes along, you can check it out and not have to worry about migrating all your old data. See the [Files reference](/docs/references/resources/files/) for more information. 67 | 68 | 69 | ## Tracking news and announcements 70 | 71 | To see the latest updates to the API, follow [@adnapi](http://alpha.app.net/adnapi). You may also want to subscribe to the [App.net blog](https://broadcast.app.net/26283/appnet-blog/) for general news and the [App.net API Updates](https://broadcast.app.net/24368/appnet-api-updates/) Broadcast channel for developer related news. 72 | 73 | ## Getting help and providing feedback 74 | 75 | There are numerous ways for developers to get help utilizing the platform and to provide feedback. 76 | 77 | * Developers (including App.net staff) are often chatting in the [Developer Channel](http://patter-app.net/room.html?channel=1383). 78 | * For developer inquiries about the API, our Terms of Service, letting us know about something you're working on, etc., email [developers@app.net](mailto:developers@app.net). 79 | * For general inquiries about account/service related issues, email [support@app.net](mailto:support@app.net). 80 | * In addition to the above, you can report bugs and provide feedback on the API using the [issue tracker](https://github.com/appdotnet/api-spec/issues). 81 | * This documentation is open source. If you find an error or something that's unclear, let us know with a pull request or issue on the [Github repo for the documentation](https://github.com/appdotnet/api-spec/). 82 | 83 | ## Your hosts 84 | 85 | * [Bryan Berg](http://ber.gd) ([@berg](https://alpha.app.net/berg), [bryan@app.net](mailto:bryan@app.net)) 86 | * Mark Thurman ([@mthurman](https://alpha.app.net/mthurman), [mthurman@app.net](mailto:mthurman@app.net)) 87 | * [Alex Kessinger](http://alexkessinger.net) ([@voidfiles](https://alpha.app.net/voidfiles), [alex@app.net](mailto:alex@app.net)) 88 | * Brian Armstrong ([@barmstrong](https://alpha.app.net/barmstrong), [barmstrong@app.net](mailto:barmstrong@app.net)) 89 | -------------------------------------------------------------------------------- /layouts/partials/reference_nav.html: -------------------------------------------------------------------------------- 1 | 101 | -------------------------------------------------------------------------------- /content/reference/resources/config/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Configuration" 3 | --- 4 | 5 | # Configuration 6 | 7 | * TOC 8 | {:toc} 9 | 10 | The Configuration object contains variables which define the current behavior of the App.net platform. 11 | 12 | ## Example Configuration object 13 | 14 | <%= json(:config) %> 15 | 16 | ## Configuration fields 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
FieldTypeDescription
textobject 28 | Configuration that is common to all text fields (post.text, message.text, user.description.text). 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
FieldTypeDescription
uri_template_lengthobjectA mapping from each of the possible URI template replacement values to the number of characters that are "used" upon replacement.
42 |
userResource Configuration ObjectThe configuration related to User objects.
fileResource Configuration ObjectThe configuration related to File objects.
postResource Configuration ObjectThe configuration related to Post objects.
messageResource Configuration ObjectThe configuration related to Message objects.
channelResource Configuration ObjectThe configuration related to Channel objects.
70 | 71 | ## Resource Configuration 72 | 73 | <%= json(:config) { |h| 74 | user = h["user"] 75 | h.clear 76 | h.update(user) 77 | } %> 78 | 79 | A Resource Configuration object represents values that only apply to a specific App.net resource. 80 | 81 | ### Resource Configuration Fields 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
FieldTypeDescription
annotation_max_bytesintegerThe maximum number of bytes that can be attached to this type of object as an Annotation.
text_max_lengthintegerThe maximum number of characters that an instance of this object can be. For User objects, this applies to the User description. This field does not apply to Channel objects.
104 | 105 | ## How to use the Configuration object 106 | 107 | The App.net platform has platform-wide limits that all apps must respect. These limits are enforced at an API level, but can be useful to have defined as constants in your app's code, often for the purpose of displaying your user interface. Examples are things like: "how long can a Post be" or "how long can annotations be on a Channel object." This endpoint allows you to update your app's configuration so it always has the newest platform-wide configuration values available. 108 | 109 | We recommend: 110 | 111 | 1. Ship your application with a static copy of the configuration object. When your app launches for the first time, persist those static values into your application's preference store (NSUserDefaults or SharedPreferences, etc.) 112 | 2. On launch, and at most once per day, poll the configuration endpoint; if it differs from the previously persisted data, update your persisted copy of the configuration object. 113 | 3. Always use the values from your persisted configuration. 114 | 115 | This pattern will ensure that no matter whether your application has network connectivity or not, you will have values, even if they are out of date. As the majority of these variables are related to user interface, slightly outdated configuration variables are generally not a problem. 116 | 117 | This endpoint should be queried with an access token if you have one. If you are creating an app which supports multiple user accounts, you may store this data globally instead of per-user. 118 | 119 | ## Retrieve the Configuration object 120 | 121 | Returns the current Configuration object. 122 | 123 | *Your application should request this endpoint with a user or app access token if available.* 124 | 125 | <%= endpoint "GET", "config", "None" %> 126 | 127 | #### Example 128 | 129 | <%= curl_example(:get, "config", :config) %> 130 | -------------------------------------------------------------------------------- /content/reference/authentication/flows/web.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Web Flows" 3 | --- 4 | 5 | # Web Flows 6 | 7 | * TOC 8 | {:toc} 9 | 10 | ## Server-side Flow 11 | 12 | This is the easiest way to get an access token—we recommend it to most users of the API. If you're writing an app on a server using a language like Ruby, Python, PHP, Java, etc. you should use this flow. 13 | 14 | **You must keep your `client_secret` confidential**. That means that you may not include it in the source code or binary of an application that you ship to end-users, even in obscured form. 15 | 16 | Your `redirect_uri` must be registered with App.net before you can use it. 17 | 18 | 1. Direct the user that you want to authenticate to this URL: 19 | 20 | https://account.app.net/oauth/authenticate 21 | ?client_id=[your client ID] 22 | &response_type=code 23 | &redirect_uri=[your redirect URI] 24 | &scope=[scopes separated by spaces] 25 | 26 | > To avoid cross-site scripting attacks, we also support the **state** parameter. If you include a state parameter, we will append it to the query parameters when redirecting the user to your **Redirection URI**. 27 | 28 | > To comply with Apple's App Store Guidelines, you can add the query string parameter `adnview=appstore` to hide all signup links on the authentication pages. 29 | 30 | We'll request that the user log in to App.net and show them a permissions dialog allowing them to choose whether to authorize your application. 31 | 32 | > We do not show the permissions dialog if the user has already authorized your application for all scopes in your request, and will instead immediately redirect them. If you wish to force the display of the permissions dialog, use the `https://account.app.net/oauth/authorize` endpoint instead. 33 | 34 | 1. If the user decides to authorize your application, they will be redirected to: `https://[your registered redirect URI]/?code=CODE` 35 | 36 | > If you included a query string in your redirect URI, the `code` parameter will be appended. Likewise, the scheme of your redirect URI will be respected, though we strongly recommend sending all traffic over HTTPS. 37 | 38 | 1. On your server, your application should then make the following request: `POST https://account.app.net/oauth/access_token` 39 | 40 | with URL-encoded POST body: 41 | 42 | client_id=[your client ID] 43 | &client_secret=[your client secret] 44 | &grant_type=authorization_code 45 | &redirect_uri=[your registered redirect URI] 46 | &code=[code received from redirect URI] 47 | 48 | Example: 49 | 50 | <%= curl_example(:post, "access_token", :none, { 51 | :subdomain => "account", 52 | :path_prefix => "/oauth/", 53 | :pretty_json => false, 54 | :token => nil, 55 | :content_type => nil, 56 | :data => { 57 | "grant_type" => "authorization_code", 58 | "client_id" => "[your client_id]", 59 | "client_secret" => "[your client secret]", 60 | "redirect_uri" => "[your registered redirect URI]", 61 | "code" => "[code received in the previous step]" 62 | } 63 | }) %> 64 | 65 | > We also accept the `client_id` and `client_secret` parameters via the Authorization header, as described in [section 2.3.1 of the OAuth 2 spec](http://tools.ietf.org/html/rfc6749#section-2.3.1). 66 | 67 | 1. App.net will respond with a JSON-encoded token: `{"access_token": "[user access token]", "token": {...Token object...}}` 68 | 69 | You can use this access_token to make authenticated calls to the App.net API on behalf of a user. 70 | 71 | ## Client-side Flow 72 | 73 | If you're building a client-side Javascript app or a mobile app that doesn't have an associated back-end server, you'll find that you need to take some special steps to keep your `client_secret` confidential. 74 | 75 | 1. Direct the user that you want to authenticate to this URL: 76 | 77 | https://account.app.net/oauth/authenticate 78 | ?client_id=[your client ID] 79 | &response_type=token 80 | &redirect_uri=[your redirect URI] 81 | &scope=[scopes separated by spaces] 82 | 83 | > To avoid cross-site scripting attacks, we also support the **state** parameter. If you include a state parameter, we will append it to the query parameters when redirecting the user to your **Redirection URI**. 84 | 85 | > To comply with Apple's App Store Guidelines, you can add the query string parameter `adnview=appstore` to hide all signup links on the authentication pages. 86 | 87 | We'll request that the user log in to App.net and show them a permissions dialog allowing them to choose whether to authorize your application. 88 | 89 | > We do not show the permissions dialog if the user has already authorized your application for all scopes in your request, and will instead immediately redirect them. If you wish to force the display of the permissions dialog, use the `https://account.app.net/oauth/authorize` endpoint instead. 90 | 91 | 1. If the user decides to authorize your application, they will be redirected to: `https://[your registered redirect URI]/#access_token=[user access token]` 92 | 93 | > If you included a query string in your redirect URI, the `code` parameter will be appended. Likewise, the scheme of your redirect URI will be respected, though we strongly recommend sending all traffic over HTTPS. 94 | 95 | The access_token will be appended to the URI in the fragment section, encoded as if it were a query string. Your client-side code should parse this for the access_token. 96 | 97 | ## Finishing The Flow 98 | 99 | After you have decided which flow will work for your app you should read our [Web Flow Integration Guide](/reference/authentication/authorize-with-appnet/) to help you integrate the authentication flow into your app. 100 | 101 | -------------------------------------------------------------------------------- /layouts/partials/endpoints/channel.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |
DescriptionMethodPathToken
Get current user's subscribed channelsGET/stream/0/channelsUser
Create a ChannelPOST/stream/0/channelsUser
Retrieve a ChannelGET/stream/0/channels/{channel_id}Varies
Retrieve multiple ChannelsGET/stream/0/channelsAny
Retrieve my ChannelsGET/stream/0/users/me/channelsUser
Retrieve number of unread PM ChannelsGET/stream/0/users/me/channels/pm/num_unreadUser
Retrieve number of unread Broadcast ChannelsGET/stream/0/users/me/channels/broadcast/num_unreadUser
Mark all Broadcast Channels as readDELETE/stream/0/users/me/channels/broadcast/num_unreadUser
Update a ChannelPUT/stream/0/channels/{channel_id}User
Deactivate a ChannelDELETE/stream/0/channels/{channel_id}User
Subscribe to a ChannelPOST/stream/0/channels/{channel_id}/subscribeUser
Unsubscribe from a ChannelDELETE/stream/0/channels/{channel_id}/subscribeUser
Retrieve users subscribed to a ChannelGET/stream/0/channels/{channel_id}/subscribersVaries
Retrieve user ids subscribed to a ChannelGET/stream/0/channels/{channel_id}/subscribers/idsVaries
Retrieve user ids subscribed to multiple ChannelsGET/stream/0/channels/subscribers/idsVaries
Mute a ChannelPOST/stream/0/channels/{channel_id}/muteUser
Unmute a ChannelDELETE/stream/0/channels/{channel_id}/muteUser
Get current user's muted ChannelsGET/stream/0/users/me/channels/mutedUser
Search for ChannelsGET/stream/0/channels/searchUser
127 | -------------------------------------------------------------------------------- /content/docs/guides/send-a-broadcast.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Broadcasts and the API" 3 | --- 4 | 5 | # Publishing Broadcasts via the API 6 | 7 | <%= access_token_required_note %> 8 | 9 | Broadcast Channels are designed to carry low-volume, high-value updates of interest to users. We call the actual updates themselves Broadcast Messages (or sometimes just "broadcasts"). Because broadcasts are built on top of the existing App.net [Channel](/reference/resources/channel/) and [Message](/reference/resources/message/) APIs, it's helpful to be familiar with them, but for simple tasks, there's not much you need to know. 10 | 11 | Just a reminder: while you can do all of this using our API, you don't have to. We have [tools for publishers](https://broadcast.app.net/manage/) to help you quickly get started pulling content in from elsewhere on the web, and you can send them manually via the web or the App.net iOS and Android apps. To get started, **we recommend that you create and set up your broadcast channel with [our web publisher tools](https://broadcast.app.net/manage/)** and only use the API to send broadcasts via the channel you created. 12 | 13 | ## Send a Broadcast 14 | 15 | There are a number of parts to each broadcast message. To illustrate, here's a screenshot of a broadcast in the App.net iOS app: 16 | 17 | ![Anatomy of a broadcast](https://files.app.net/rw8fPgku.png) 18 | 19 | The important parts are the **Headline**, **Photo**, **Text** and **Read More Link**. Everything but the headline is optional, but we recommend that your broadcasts contain a compelling image and some context through a summary text body and a link to content. 20 | 21 | The easiest way to send a broadcast with the API is via the [ADNPy](http://adnpy.readthedocs.org) Python module, the [adn](https://github.com/adn-rb/adn) Ruby gem, the [appnet.js](https://github.com/duerig/appnet.js) library for Node.js, or the [AppDotNetPHP](https://github.com/jdolitsky/AppDotNetPHP) library. You can also use the HTTP API with your own client, if you'd like. 22 | 23 | Starting with Python, here's an example of using the ADNPy `BroadcastMessageBuilder` recipe. If you're interested in the specific API calls the library is making behind the scenes, [look at the source](https://github.com/appdotnet/ADNpy/blob/master/adnpy/recipes/broadcast.py). 24 | 25 | Once you've installed the ADNPy library, it's as simple as: 26 | 27 | ~~~ python 28 | import adnpy 29 | 30 | # Set the default access token for API calls. 31 | adnpy.api.add_authorization_token('') 32 | 33 | # Send a broadcast with the BroadcastMessageBuilder recipe. 34 | builder = adnpy.recipes.BroadcastMessageBuilder(adnpy.api) 35 | builder.channel_id = 24204 # Get this channel ID from the web publisher tools 36 | builder.headline = 'Hello World!' 37 | builder.text = 'Sending this from [ADNPy](https://github.com/appdotnet/ADNPy) was easy!' 38 | builder.parse_markdown_links = True 39 | builder.read_more_link = 'http://adnpy.readthedocs.org/' 40 | builder.send() 41 | ~~~ 42 | 43 | You can easily attach a photo: 44 | 45 | ~~~ python 46 | builder.photo = '/home/paul/celeryman.gif' 47 | ~~~ 48 | 49 | Or with the [adn](https://github.com/adn-rb/adn) Ruby gem: 50 | 51 | ~~~ ruby 52 | require 'adn' 53 | 54 | ADN.token = '' 55 | 56 | builder = ADN::Recipes::BroadcastMessageBuilder.new 57 | builder.channel_id = 24204 58 | builder.headline = 'sending from ruby' 59 | builder.read_more_link = 'https://app.net' 60 | builder.photo = '/home/mthurman/oyster-smiling.png' 61 | builder.send 62 | ~~~ 63 | 64 | If you want to send the equivalent broadcast from the API without using a library, use this curl command: 65 | 66 | <% data = { 67 | "text" => "Here is a [link](http://www.google.com) for my text body.", 68 | "annotations" => [{ 69 | "type" => "net.app.core.broadcast.message.metadata", 70 | "value" => { 71 | "subject" => "Hello world!" 72 | }, 73 | }, 74 | { 75 | "type" => "net.app.core.crosspost", 76 | "value" => { 77 | "canonical_url" => "http://www.example.com" 78 | }, 79 | }], 80 | "entities" => { 81 | "parse_markdown_links" => true, 82 | "parse_links" => true 83 | } 84 | } %> 85 | <%= curl_example(:post, "channels/24204/messages?include_annotations=1", :none, {:data => data}) %> 86 | 87 | 88 | ## Create a Broadcast Channel 89 | 90 | You can create broadcast channels with the API as well. 91 | 92 | Broadcast channels are created like any other channel, with a specific type value (`net.app.core.broadcast`) and a few special annotations. For information on creating channels, see the [Channel lifecycle documentation](/reference/resources/channel/lifecycle/). Broadcast channels fully support [ACLs](/reference/resources/channel/) for private applications. 93 | 94 | Here is an example channel body, set to be public, with multiple editors, which you can POST to us: 95 | 96 | <% data = { 97 | "type" => "net.app.core.broadcast", 98 | "readers" => { 99 | "public" => true 100 | }, 101 | "editors" => { 102 | "user_ids" => ["@samsharp", "@sfborscht"] 103 | }, 104 | "annotations" => [{ 105 | "type" => "net.app.core.broadcast.metadata", 106 | "value" => { 107 | "title" => "SF Borscht Truck Updates", 108 | "description" => "Get a notification when the SF Borscht Food Truck will be on the streets!" 109 | } 110 | }] 111 | } %> 112 | <%= json_output(data) %> 113 | 114 | Here's a sample curl command that'll create a channel: 115 | 116 | <%= curl_example(:post, "channels?include_annotations=1", :none, {:data => data}) %> 117 | 118 | This will return a fully-populated channel resource, including the `id` of the channel, a few auto-generated annotations, and the `fallback_url`, which is the short URL for the channel's detail page. 119 | 120 | <%= response(:channel) do |h| 121 | h["data"]["recent_message"] = nil 122 | h["data"]["recent_message_id"] = nil 123 | h["data"]["counts"]["messages"] = 0 124 | h["data"]["counts"]["subscribers"] = 1 125 | data["annotations"] << { 126 | "type" => "net.app.core.broadcast.freq", 127 | "value" => { 128 | "avg_freq" => "less than 1 per week", 129 | "intensity" => 0.1 130 | } 131 | } 132 | data["annotations"] << { 133 | "type" => "net.app.core.fallback_url", 134 | "value" => { 135 | "url" => "https://app.net/c/2rds" 136 | } 137 | } 138 | data["annotations"][0]["value"]["tags"] = [] 139 | h["data"]["annotations"] = data["annotations"] 140 | h["data"]["type"] = data["type"] 141 | h["data"]["editors"]["user_ids"] = ["190151", "190195"] 142 | end %> 143 | --------------------------------------------------------------------------------