This API provides for serialized JSON storage for privly-applications-- this means it is intended to be a key-value store where the key is the URL and the value is a JSON object. To create or edit content on the server, you will need to be acquainted with how the server handles CSRF, sessions, and content. Most Privly code must run in both a hosted context (ie, a web server sent the client the web application) and locally served context (the extension serves the code). This creates some unique concerns for a web service and inspires this API.
Version: 0.1.1, Added Registration Endpoint
Version: 0.1, Wrote this document
"Cross Site Request Forgery" protection is built into Ruby on Rails by default, which means you need to have a random token established by the server before you can create or modify content. All non-get requests require you to set a CSRF header, ex:
X-CSRF-Token:QjutSPGSGq+CMsw2+RpgyVAJcjZ3sQF53wcEl9wpWdg=
Where "X-CSRF-Token" is the header name and "QjutSPGSGq+CMsw2+RpgyVAJcjZ3sQF53wcEl9wpWdg=" is the token established by the server.
You retrieve this token from the content server with a GET request to /posts/user_account_data
, which returns the following JSON:
{
csrf: "QjutSPGSGq+CMsw2+RpgyVAJcjZ3sQF53wcEl9wpWdg=",//string
burnAfter: "2014-01-26T10:35:47-07:00", //string
canPost: true, //boolean
signedIn: true //boolean
}
Users who can post will have both "canPost" and "signedIn" set to "true." "burnAfter" specifies when the content on the server will be destroyed.
The CSRF tokens are automatically saved and used for future requests when privlyNetworkService.initPrivlyService() is called in the Privly-applications.
All content on the server is tied to confirmed user accounts so users must establish a session with the server. Sessions are declared to the server either via a session cookie, or by an auth token. The auth token is generally used for devices, but the session cookie is used by extensions and hosted Privly applications.
Sessions tell the server who the user is, but the CSRF token is also required to protect the user from CSRF.
This server will set a session cookie when an acceptable username and password are sent to /users/sign_in
.
POST request parameters:
"user[email]" : "[email protected]"
"user[password]" : "password"
Requires CSRF token (see above).
To invalidate the session cookie, you should send a delete
request to /users/sign_out
.
Auth tokens can be added to requests as a parameter to identify the user and grant them access to their user account. This option is primarily used for devices with long-lived sessions.
POST request to '/token_authentications.:format'
Parameters
"email" : "[email protected]"
"password" : "password"
To experiment with token generation, you can view the forms at /token_authentications/new
.
The auth token can be automatically added to AJAX requests if you first call privlyNetworkService.setAuthTokenString() with the auth token before making requests.
Does not require CSRF token.
To destroy the current authentication token you should generate a new token and choose not to store it.
When a user wants a new account on the server they must register for the account. This endpoint generates a confirmation email sent to the specified account. The account will not be active until the user confirms their email address.
POST /users/invitation
.
Parameters
"user[email]" : "[email protected]"
Headers
Accept:application/json
Requires CSRF token (see above).
The "posts" endpoint is the storage endpoint for content. 404'd requests are also answered with 403 status codes to obscure whether content exists on the server. All requests should request JSON content.
Requires CSRF token (see above).
Create a post.
POST /posts.json
Parameters
post[content] - string - Optional
- Values: Any Markdown formatted string. No images supported.
- Default: nil
The content is rendered on the website, or for injection into web pages.
post[structured_content] - JSON - Optional
- Values: Any JSON document
- Default: nil Structured content is for the storage of serialized JSON in the database.
post[privly_application] - string - Optional
- Values: Any of the currently supported Privly application identifiers can be set here. Current examples include "PlainPost" and "ZeroBin", but no validation is performed on the string. It is only used to generate URLs into the static folder of the server.
- Default: nil
post[public] - boolean - Optional
- Values: true, false
- Default: nil
A public post is viewable by any user.
post[random_token] - string - Optional
- Values: Any string
- Default: A random sequence of Base64 characters
The random token is used to permission requests to content not owned by the requesting user. It ensures the user has access to the link, and not didn't crawl the resource identifiers.
post[seconds_until_burn] - integer - Optional
- Values: 1 to 99999999
- Default: nil
The number of seconds until the post is destroyed.
If this parameter is specified, then the burn_after_date is ignored.
post[burn_after_date(1i)] - integer - Required
- Values: 2012
- Default: 2012
The year in which the content will be destroyed
post[burn_after_date(2i)] - integer - Required
- Values: 1 to 12
- Default: current month
The month in which the content will be destroyed
post[burn_after_date(3i)] - integer - Required
- Values: 1 to 31 Default: Defaults to two days from now if the user is not logged in, otherwise it defaults to 14 days from now
The day after which the content will be destroyed. The combined day, month, and year must be within the next 14 days for users with posting permission, or 2 days for users without posting permission.
post[share[share_csv]] - csv - Optional
- Values: a single row of comma separated values
- Default: nil
Send in comma separated values representing identities like domains, emails, and IP Addresses.
post [share [can_show]] - boolean - Optional
- Values: true, false
- Default: true
Assign a show sharing permission to the share_csv row's values
post [share [can_update]] - boolean - Optional
- Values: true, false
- Default: false
Assign a update sharing permission to the share_csv row's values
post [share [can_destroy]] - boolean - Optional
- Values: true, false
- Default: false
Assign a destroy sharing permission to the share_csv row's values
**post [share [can_share]] **- boolean - Optional
- Values: true, false
- Default: false
Assign a share sharing permission to the share_csv row's values
Response Headers
- X-Privly-Url The URL for this content which should be posted to other websites.
Update a post. Requires update permission or content ownership.
PUT /posts/:id
PUT /posts/:id.:format
id - integer - Required
- Values: 0 to 9999999
- Default: None
The identifier of the post.
random_token - string - Required
- Values: Any string of non-whitespace characters
- Default: None
Either the user owns the post, or they must supply this parameter. Without this parameter, even with complete share access to the content, the user will not be able to access this endpoint.
post[content] - string - Optional
- Values: Any Markdown formatted string. No images supported.
- Default: nil
The content is rendered on the website, or for injection into web pages.
post [structured_content] - JSON - Optional
- Values: Any JSON document
- Default: nil
Structured content is for the storage of serialized JSON in the database.
post[public] - boolean - Optional
- Values: true, false
- Default: nil
A public post is viewable by any user.
post [random_token] - string - Optional
- Values: Any string
- Default: A random sequence of Base64 characters The random token is used to permission requests to content not owned by the requesting user. It ensures the user has access to the link, and not didn't crawl the resource identifiers.
post [seconds_until_burn] - integer - Optional
- Values: 1 to 99999999
- Default: nil
The number of seconds until the post is destroyed. If this parameter is specified, then the burn_after_date is ignored. Requires destroy permission.
post [burn_after_date(1i)] - integer - optional
- Values: 2012
- Default: 2012
The year in which the content will be destroyed Requires destroy permission.
post [burn_after_date(2i)] - integer - optional
- Values: 1 to 12
- Default: current month
The month in which the content will be destroyed Requires destroy permission.
post [burn_after_date(3i)] - integer - optional
- Values: 1 to 31
Default: Defaults to thirty days from now.
Response Headers
- X-Privly-Url The URL for this content which should be posted to other websites.
Destroy a post. Requires destroy permission, or content ownership.
DELETE /posts/:id
DELETE /posts/:id.:format
Parameters
id - integer - Required
- Values: 0 to 9999999
- Default: None
The identifier of the post.
random_token - string - Required
- Values: Any string of non-whitespace characters
- Default: None
Either the user owns the post, or they must supply this parameter. Without this parameter, even with complete share access to the content, the user will not be able to access this endpoint.
Shows an individual post. The "owning user" is the user who created the original content behind the link. The owning user will be the only one with access to metadata for the post.
GET: /posts/:id.:format
Example:
{"created_at":"2012-09-05T04:08:31Z", // when the content was created (owning user only)
"burn_after_date":"2012-09-19T04:08:31Z", // when the content will be destroyed
"public":false, // whether everyone has read permission
"updated_at":"2012-09-05T04:08:31Z", // when the content was updated (owning user only)
"structured_content":{ // the content serialized by and for the privly-application
"salt":"ytyzBr2OkEc",
"iv":"RSBeCnAklAbi0qvq/P8twA",
"ct":"23hqJJ7QKNkxpLVtfp9uEg"},
"id":149, //the unique id of the content
"user_id":2, //the id of the creating user. (owning user only)
"content":null, // public cleartext content. this may be deprecated
"random_token":"a53642b006", //see below
"permissions":{ //current user's permissions on contents
canshow: true,
canupdate: false,
candestroy: false,
canshare: false}
}
Parameters
random_token - string - Required
- Values: Any string of non-whitespace characters
- Default: None
Either the user owns the post, or they must supply this parameter. Without this parameter, even with complete share access to the content, the user will not be able to access this content.
Response Headers
- X-Privly-Url The URL for this content which should be posted to other websites.
Get a list of all the user's posts. The user must be authenticated.
GET: /posts.json
The result is an array of data objects similar to the one described in the "show" endpoint. Example result:
[
{"created_at":"2012-09-05T04:08:31Z",
"burn_after_date":"2012-09-19T04:08:31Z",
"public":false,
"updated_at":"2012-09-05T04:08:31Z",
"structured_content": {
"salt":"ytyzBr2OkEc",
"iv":"RSBeCnAklAbi0qvq/P8twA",
"ct":"23hqJJ7QKNkxpLVtfp9uEg"},
"id":149,
"user_id":2,
"content":null,
"random_token":"a53642b006"
},
...
]
We built rule-based authorization into the server for sharing by email, domain, IP address, and password, but this functionality is hidden by default. If you are self-hosting a server this functionality can be useful, but in general it is better to base confidentiality on cryptographic operations that remove trust from the hosting provider. Server-side authorization does not pass this test.