Fotobilder API Documentation
Introduction#↑
The FotoBilder client protocol is designed to provide client authors with a flexible, easy-to-use interface to the FotoBilder server. It supports a variety of ways to send and receive data via HTTP (including SOAP, XML-RPC, and a "Simple" mode), so clients can use whichever method is best supported on their platform. There are interfaces for uploading pictures as well as retrieving useful account information and more functionality will likely be added as the need arises.
Contents of this Document#↑
- Introduction
- Contents of this Document
- History
- Tutorial
- Data Transmission
- Supported RPC Encodings (All via HTTP transport)
- Data Structure Serialization
- Simple Encoding
- SOAP
- XML-RPC
- Writing a FotoBilder Client
- Technical Information
- RPC Method Documentation
- CreateGals
- GetChallenge
- GetChallenges
- GetGals
- GetGalsTree
- GetPics
- GetSecGroups
- Login
- UploadPrepare
- UploadTempFile
- UploadPic
- Response Error Messages
- Author
History#↑
The protocol described in this document is actually the second generation of FotoBilder's original HTTP-based client protocol. The first generation worked, but was clunky and made writing clients difficult. The one 'upload' method became extremely overloaded and nothing was every fully documented or implemented. A complete rewrite was needed to make everything clean and spur more client development, so the new protocol is less of a revision and more of a complete rewrite. With the new protocol, we've focused on providing more functionality and eliminating client development obstacles.
Major design goals for the new protocol include:
- Being friendly to HTTP (et. al) libraries in a number of languages.
- Providing support for protocol-based image and gallery backups.
- Supporting safe authentication in all modes.
- Checking for duplicate images so users don't have to send data of images they've already uploaded before.
- Allowing clients to upload binary files for temporary storage, receiving a reciept to complete the upload transaction later with an RPC encoding that doesn't support binary data (such as XML-RPC or SOAP).
Tutorial#↑
Data Transmission#←↑
Supported RPC Encodings (All via HTTP transport)#←↑
There are three popular ways to encode RPC requests over HTTP. We currently support or have plans to support the following:
- Simple: This uses HTTP headers as well as GET and POST methods to transmit serialized data to and from the server. This is the only encoding that is fully supported at this time.
- XML-RPC: Coming later.
- SOAP: Coming later.
Valid RPC Combinations#←↑
Sometimes more than one on the RPC encoding listed above can be employed at a time. Likewise, some RPC encodings may not be used together in the same request. For instance, a client could feasibly transmit information using HTTP headers, URL-Encoded GET arguments, as well as MIME-Encoded POST arguments, all at once. But transmitting URL-Encoded POST and MIME-Encoded POST at the same time would not work. The table below lists all possible combinations of RPC encodings.
| Headers | GET | PUT | MIME-Enc. POST | URL-Enc. POST | |
| Headers | X | X | X | X | |
| GET | X | X | X | X | |
| PUT | X | X | X | X | |
| MIME-Enc. POST | X | X | |||
| URL-Enc. POST | X | X |
Note: The SOAP and XML-RPC RPC encodings are not shown in the table above because they are self-contained and cannot be used in conjunction with any other RPC encoding
Data Precedence#←↑
The tree below attempts to describe the precedence relationships between the different RPC encodings. Each data set in a single request will be processed in the order shown in the tree, which should be read from top-to-bottom.
Variables and their values are read from each RPC Encoding type in the order in which they are received. As each variable is read, it will overwrite its previous value as described in the Data Structure Serialization section.
Data Structure Serialization#←↑
While SOAP and XML-RPC both support transmission of complex data structures, HTTP is based on the idea of sending flat elements which usually consist of a key (or variable name) and a value. Since the FotoBilder protocol often uses complex data structures both in requests and responses, there needs to be a standard way to represent them in HTTP's flat space. This is most useful when using the Simple RPC encoding or when using HTTP Headers with SOAP and XML-RPC requests.
Here is how to represent different variable types in this key/value system:
- Scalars
Encoded as "MethodName.VarName=value". So to pass the "MD5" variable to a call to the UploadPic method, while sending an Auth, you would send the following variables:
Auth = 0123456789abcdef:0123456789abcdef UploadPic.MD5 = 458601965397d1fe437d17fc359518b8 UploadPic.Size = 65535When a scalar value is defined multiple times, it will be overwritten as each new definition is encountered according to the processing order defined in the tree above.
- Arrays
Arrays must be instantiated to a given size using the special '_size' attribute: "MethodName.ArrayName._size=array_size". After the initial instantiation with '_size', each element is filled in using numeric keys (which are special) based on location (indexed on 0): "MethodName.ArrayName.0=value".
To encode an array named "MyArray" with elements 0-4 (size 5) to UploadPic, you would send the following headers:
UploadPic.MyArray._size: 5 UploadPic.MyArray.0 = Value 1 UploadPic.MyArray.1 = Value 2 UploadPic.MyArray.2 = Value 3 UploadPic.MyArray.3 = Value 4 UploadPic.MyArray.4 = Value 5When an array is defined multiple times via the '_size' key, it will be overwritten and re-instantiated as a new array of the given size. When a specific element is overwritten, it will follow the same rules as defined for scalars.
- Structs
Everything is essentially a struct, so encoding them is easy:
UploadPic.MyStruct.Key1 = some value UploadPic.MyStruct.Key2 = another value UploadPic.MyStruct.Key3 = yet another value
Nesting & Combining#←↑
Data structures can be nested in any fashion necessary. Some protocol modes require fairly complicated data structures to be represented. These are easy in SOAP and XML-RPC RPC encodings, but might seem a bit tricky for key/value Simple encodings. Here's an example of a two-element array whose values are structs, each storing scalar values in a one-element array:
UploadPic.ParentArray._size = 2;
UploadPic.ParentArray.0.Key1._size = 1
UploadPic.ParentArray.0.Key1.0 = Some Scalar Value
UploadPic.ParentArray.1.Key2._size = 1
UploadPic.ParentArray.1.Key2.0 = Another Scalar Value
If you're a Perl person, it might be easier to visualize what's being represented above as a Perl hash:
%UploadPic = (
ParentArray => [
{ Key1 => [ "Some Scalar Value" ] },
{ Key2 => [ "Another Scalar Value" ] },
]
);
Simple Encoding#←↑
The Simple encoding method requires the passing serialized data structures to the FotoBilder server using the key/value pair representation (discussed in the Data Serialization section). Key/value pairs can be send using HTTP headers, GET requests, and either MIME or URL encoded POST requests. For information about valid combinations, see the Valid RPC Combinations section.
In addition to global restrictions on what RPC encodings can be used together, there are some per-request restrictions which are defined by individual protocol methods. Particularly, any request sending binary data must be either a MIME-encoded POST or an HTTP PUT, since URL-encoding binary data greatly bloats file size.
Below are some examples of how to encode variables using headers, GET, and POST.
HTTP Headers#←↑
Any non-binary variable can be encoded using a special HTTP header whose name is the prefix "X-FB-" followed by the name of the variable to be encoded. The header value is then the same as the desired value to be sent. Making a HTTP header to represent a variable you want to send is probably the simplest way to encode data, depending on how well your HTTP library supports modification of your request headers.
Here is an example request using HTTP headers in conjunction with PUT to upload a picture:
PUT http://www.fb.com/interface/simple
X-FB-Mode: UploadPic
X-FB-User: bob
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-UploadPic.Meta.Filename: somefile.jpg
Content-length: 134332
<ImageData>
There is a hard limit of 25 header variables which can be sent to the protocol in a single request. This is done for 2 reasons:
- It is "improper" to send large amounts of data encoded in HTTP headers. It's simply not what they were designed to do.
- Because of reason #1, many HTTP proxies have limits on the size of headers they can handle in a single request. So sending 50k of data encoded headers would have unexpected results going through proxies.
Note that due to requirements set forth by section 4.2 of RFC 2616, all variable names sent via HTTP header RPC encoding will be interpretted as case-insensitive. However, variable names in other encodings are case-sensitive.
GET args#←↑
In most situations, GET arguments are the simplest way to pass arguments. Simply URL-Encode a string of "key=value" pairs, separated by "&" and attach it to the end of the request URI.
Though it is easy, this RPC encoding is only good for sending small amounts of data. For this reason, GET arguments are perfect for protocol methods like GetChallenge which require very few variables to be sent and poor for methods like UploadPrepare which require many variables to be sent. In fact, binary data cannot be sent using the GET method, so if a protocol method requires binary data, you'll either have to use a different RPC encoding such as MIME-Encoded POST or PUT.
Here's a simple example of using GET arguments to fetch a challenge for user 'bob':
GET http://www.fb.com/interface/simple?User=bob&GetChallenge=1 HTTP/1.x
PUT#←↑
PUT requests are allowed exclusively in conjunction with any method that accepts binary data. This is useful for the UploadPic and UploadTempFile protocol methods when a client is being written in a language that supoorts PUT better than MIME-encoded POST.
The binary image data received will be implicitly interpretted as the "ImageData" variable on the primary method specified by the "Mode" variable. Since the body of a PUT request is simply the binary value of one piece of information being sent, all other included variables will need to be encoded using either GET arguments or HTTP Headers.
PUT http://www.fb.com/interface/simple
X-FB-Mode: UploadPic
X-FB-User: bob
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-UploadPic.Meta.Filename: somefile.jpg
Content-length: 134332
<ImageData>
POST args (URL-encoded)#←↑
A URL-encoded POST request is another simple way to send data to the server. It's very similar to using a GET request in that you simply URL-encode a string of "key=value" pairs to represent the data you want to send. The difference comes in the way it's transmitted. Rather than being tacked onto the end of the request URI, it's sent in the body of the document you are "post"ing to the server, along with a "Content-length" header which specifies how long your data will be.
URL-encoded POST requests are well-supported by most HTTP libraries and work great for any protocol method which doesn't require the sending of binary data. Though it is technically possible to transmit binary data using this RPC encoding, doing so bloats the size of the information being sent. Since there are several alternative methods for sending binary data to FotoBilder, it is explicitly disallowed in POST requests.
POST http://www.fb.com/interface/simple HTTP/1.x
Content-length: 26
User=bob&GetChallenge=1
POST args (mime-encoded)#←↑
MIME-encoded POSTs are the only RPC encoding which is valid in all protocol methods. It can transmit binary data to the server with no problems. In fact, this is how most web browsers do we uploads via HTTP. That said, it is not the most efficient method for transmitting large numbers of non-binary variables. Since each variable has to be encoded in a new MIME part of the POSTed document, there is a lot of overhead in "setting up" a new variable and sending it.
The best usage of MIME-Encoded POST requests is when making a call to the UploadPic or UploadTempFile protocol methods. All others are somewhat wasteful, but still allowed.
Here's an example of a simple request to the UploadPic protocol method:
POST http://www.fb.com/interface/simple HTTP/1.x
Content-Type: multipart/form-data; boundary=---------------------------115756643718031969371809661030
Content-Length: 34662
-----------------------------115756643718031969371809661030
Content-Disposition: form-data; name="Mode"
UploadPic
-----------------------------115756643718031969371809661030
Content-Disposition: form-data; name="User"
bob
-----------------------------115756643718031969371809661030
Content-Disposition: form-data; name="Auth"
crp:0123456789abcdef:0123456789abcdef
-----------------------------115756643718031969371809661030
Content-Disposition: form-data; name="ImageData"; filename="somefile.jpg"
Content-Type: image/jpeg
<ImageData>
Simple Responses#←↑
The document returned from any "Simple" request will always be well-formed XML which you should be able to parse with your favorite XML library. Data will be enclosed in the <FBResponse> ... </FBResponse> parent element, which will contain sub-elements describing the data returned by one or more protocol methods which were invoked in your request.
Here is an example of the logical structure of what would be returned from request which contained calls to the GetChallenge and GetSecGroups protocol methods:
<FBResponse>
<GetChallengeResponse>
<Challenge>crp:230948209384902843</Challenge>
</GetChallengeResponse>
<GetSecGroupsResponse>
<SecGroup id='1'>
<Name>Privileged People</Name>
<GroupMembers>
<GroupMember id='1' user='someuser' />
<GroupMember id='2' user='otheruser' />
</GroupMembers>
</SecGroup>
</GetSecGroupsResponse>
</FBResponse>
For information on what specific information will be contained in the XML blocks returned by each individual protocol method, see the RPC Method Documentation section.
SOAP#←↑
- Image uploads most likely will be done via tempfile receipts, unless the client HTTP library supports soap encapsulated in MIME with inner document references.
- Later
XML-RPC#←↑
- Image uploads must be done via tempfile receipts
- Later
Writing a FotoBilder Client#←↑
Some sort of intro here?
Authentication#←↑
Challenge-Response Authentication#←↑
Instead of sending user passwords in the clear (where they can be intercepted) or using SSL (which is costly on the server end, and not always as well supported on the client side), the FotoBilder protocol uses challenge-response authentication.
The way challenge-response works, in a nutshell, is that you have to first ask for a "challenge" (which is just some opaque string, valid for one-time use within the next 14 days). Then when you go to do the real request, you include both the original challenge and the "response", which is typically a cryptographic hash the client computes made up of the challenge combined with the user's password and an optional "auth verifier" string (discussed later).
The server then verifies the challenge is legit, hasn't been used before, and the cryptographic response is computed correctly. The password never goes across the network, and the challenges can only be used once, preventing replay attacks.
Normally a challenge-response system would make the number of HTTP requests double (each request requiring fetching a challenge, and then doing the real request), but the FotoBilder protocol lets the client fetch a new challenge along with each request. So if you're doing 20 protocol requests, it only takes 21 total HTTP requests, the first one to get the process going.
Retrieving a Challenge#←↑
In order to calculate a response, you first need to retrieve a challenge by making a call to the GetChallenge protocol mode. This can be done with a single GET request a new challenge alone or by combining the GetChallenge with an existing request (Say, an UploadPic for the previous image if uploading in serial).
Here is an example of getting a challenge using a simple GET request:
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetChallenge
The server will respond with a challenge for you to use:
<FBResponse>
<GetChallengeResponse>
<Challenge>230948209384902843</Challenge>
</GetChallengeResponse>
</FBResponse>
Retrieving Multiple Challenges#←↑
If you are in a situation where you know you will eventually need a certain number of challenges, but constraints keep you from piggy-backing one challenge from each protocol request you will be making, then you can use the GetChallenges protocol method to retrieve up to 100 challenges at a time. Though the plural GetChallenges method is provided, the preferred method of requesting challenges is to make an initial request, then piggy-back more challenges on subsequent requests.
Here is an example of getting 3 challenges using a GET request:
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetChallenges
X-FB-GetChallenges.Qty: 3
The server will respond GetChallenges.Qty challenges:
<FBResponse>
<GetChallengesResponse>
<Challenge>ToOEY9OegNjvdI6Q0WmrZZ72aBqcsbtsi9azsWqt</Challenge>
<Challenge>Tc2zWP1hIHZPYUJCdjWDjIwsmBTkvBYr5334GmJo</Challenge>
<Challenge>v3OppsYmzLDgN7giAsAMJGyAunph7ePzZkdzNpLt</Challenge>
</GetChallengesResponse>
</FBResponse>
Calculating a Response#←↑
Once you have a challenge from the server, you'll need to combine it with some "secret" data that only you and the FotoBilder know. This is done using the MD5 Hash Algorithm to compute a hash of your password and the authentication challenge. Most languages have libraries to do this for you, so it's not nearly as scary as it sounds.
In the simplest case, you need to compute the following. The output will be your "Auth" token which can be sent to the server along with any protocol request for the next 30 seconds. Note the "crp:" prefix before the computed string. This is just to indicate to the server that the authentication string is of type challenge-response
crp:challenge_string:MD5(challenge_string, MD5(user_password))
Auth Verifiers (Currently Unimplemented)#←↑
Imagine that you send a protocol request to upload a picture of your dog. You include a valid Auth token which doesn't reveal your password in any way, so that part is safe, but there's a "man in the middle" listening to your traffic in transit (as it goes through a proxy, for instance). Even though they do not know your password, they can intercept your traffic and replace the image of your dog with pornography or anything else they deem sufficiently annoying. This is commonly known as a "man in the middle" attack. To prevent this, there needs to be some bit of information computed in the MD5 hash which ties the authentication token to the data it is actually being used with.
The FotoBilder protocol allows for an optional extra element in the response hash, which is used specifically to guard against man in the middle attacks. This extra element is called the "auth verifier" and is used in conjunction with the original challenge and user password to compute a stronger response token.
The auth verifier is just a URL-Encoded string of keys and values containing the current primary protocol mode name (this is the "mode" key) as well as any mode-specific tokens which are being included. The client needs to send the "AuthVerifier" variable to the server indicating what, if any, auth verifier elements it is including.
Exactly what types of auth verifiers are valid for a particular method vary and are documented in the RPC Method Documentation. UploadPic allows for the MD5 of the image data about to be sent, while methods like GetPics may contain nothing more than simply "mode=GetPics". Consult the method documentation for further details.
Here is an example of the "AuthVerifier" variable you would send to the server if you are sending a picture using the UploadPic protocol method:
md5=458601965397d1fe437d17fc359518b8&mode=UploadPic
Calculating an authentication response to send using an auth verifier is only slightly different. You simply compute the following MD5 and send the results as your auth token:
crp:MD5(challenge_string, "md5=458601965397d1fe437d17fc359518b8&mode=UploadPic", MD5(user_password))
Validating Username/Passwords#←↑
To check if a username and password pair is valid without performing any action, you can make a protocol request without a 'Mode' argument. The server will respond with an empty FBResponse if successful, or one with an error to indicate failure. Alternatively, you can just send a Login request immediately after the first GetChallenge.
Login#←↑
Much like the LiveJournal API, FotoBilder's client protocol has a login mode, even though it is stateless. The reason for this, rather than to establish a new stateful session, is to providate a way for clients to announce their ClientVersion as well as retrieve useful user information and server broadcast messages.
Though the name "login" is somewhat of a misnomer, the name was chosen for a number of reasons:
- It is highly encouraged that this method be called on client startup to verify the user's password and retrieve updated user/quota information.
- There is precedent in the LiveJournal API for a stateless login
- In the flow of a typical client's method calls, it should happen in what would otherwise be the login step (were the protocol stateful).
A typical client chain of method calls should go something like this:
- GetChallenge: Retrieve a bootstrap challenge
- Login: Check the challenge and get quota info / announcements
- Optionally GetPics, GetGals, GetSecGroups, etc to refresh gallery and picture information stored locally.
- UploadPrepare: See which images need to be uploaded
- UploadPic: Upload pictures
Obviously actual client flows will vary and many calls can be piggy-backed with others in the same request, but the point is that a Login request should generally be done directly after the first GetChallenge. Here is an example of what a request might look like:
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: Login
X-FB-Auth: crp:0123456789abcdef:0123456789abcde
X-FB-Login.ClientVersion: MyClient/1.0
The response will look something like this:
<FBResponse>
<LoginResponse>
<Message>hola</Message>
<Quota>
<Remaining>4291553280</Remaining>
<Total>4294966272</Total>
<Used>3412992</Used>
</Quota>
</LoginResponse>
</FBResponse>
As a final note, the nature of the Login protocol mode lends itself to frequent change. We plan on responding to client authors to provide useful information in Login responses. Since the contents may change, you should be careful to handle unexpected or missing data gracefully in your client application.
Uploading#←↑
Uploading a Single Picture#←↑
Uploading a single picture requires exactly two HTTP requests. One is required to fetch a challenge from the server, then a second is needed to actually send the image data to the server. Here is an example:
First Request
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetChallenge
Second Request
PUT /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPic
X-FB-Auth: crp:<challenge_string>:<response>
X-FB-AuthVerifier: md5=bbf4cf5c9c38f3b3c0ff13f0216cd275&mode=UploadPic
X-FB-UploadPic.MD5: bbf4cf5c9c38f3b3c0ff13f0216cd275
X-FB-UploadPic.PicSec: 255
X-FB-UploadPic.Meta.Filename: DSCN1205.JPG
X-FB-UploadPic.Gallery._size: 1
X-FB-UploadPic.Gallery.0.GalName: My New Gallery
X-FB-UploadPic.Gallery.0.GalSec: 255
Content-Length: 234324
Uploading Multiple Pictures#←↑
Uploading multiple pictures is a little different from uploading just one. One request is still required to fetch the initial challenge, but there's an optional second step which allows the client to declare what files it is about to upload and get receipts to send with the subsequent upload requests. This gives the server a chance to say if it already has the image data. In the case that an image is already "known" by the server, the client will not need to send the image data in the UploadPic request for that image.
The advantage of going through the UploadPrepare step is that if many images are to be uploaded and there's a possibility that the user already has one of the images uploaded, the sending of image data for duplicate images can be skipped by just including a receipt with the UploadPic request when the time comes. This is extremely useful in the case of an interrupted upload that needs to be resumed, so the extra one HTTP request per transaction is well worth it.
After step 1 and the optional step 2, UploadPic requests are most likely made in serial, each requesting a new challenge for the next request, until all of the images have been uploaded. Here is a sample set of requests for uploading 3 images:
First Request: Get Challenge #1
GET /interface/rest/GetChallenge HTTP/1.x
Host: www.fb.com
X-FB-User: bob
Second Request: Get Upload Receipts and Challenge #2
POST /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPrepare
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-AuthVerifier: mode=UploadPrepare
X-FB-GetChallenge: 1
X-FB-UploadPrepare.Pic._size: 3
X-FB-UploadPrepare.Pic.0.MD5: 258601965397d1fe437d17fc359518b8
X-FB-UploadPrepare.Pic.0.Magic: 2f3a4fccca6406e35bcf
X-FB-UploadPrepare.Pic.0.Size: 224234
X-FB-UploadPrepare.Pic.1.MD5: 158601965397d1fe437d17fc359518b8
X-FB-UploadPrepare.Pic.1.Magic: 1f3a4fccca6406e35bcf
X-FB-UploadPrepare.Pic.1.Size: 124234
X-FB-UploadPrepare.Pic.2.MD5: 358601965397d1fe437d17fc359518b8
X-FB-UploadPrepare.Pic.2.Magic: 3f3a4fccca6406e35bcf
X-FB-UploadPrepare.Pic.2.Size: 324234
Content-Length: 0
<Content-Length is zero because we encoded all of our variables
in headers, so the POST has no content in this case.>
Third Request: Upload Image #1, Get Challenge #3
PUT /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPic
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-AuthVerifier: md5=258601965397d1fe437d17fc359518b8&mode=UploadPic
X-FB-GetChallenge: 1
X-FB-UploadPic.MD5: 258601965397d1fe437d17fc359518b8
X-FB-UploadPic.ImageSize: 324234
X-FB-UploadPic.Sec: 255
X-FB-UploadPic.Meta.Filename: DSCN1205.JPG
X-FB-UploadPic.Gallery._size: 1
X-FB-UploadPic.Gallery.0.GalName: My Existing Gallery
Content-Length: 234324
<ImageData>
Fourth Request: Upload Image #2, Get Challenge #4
POST /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPic
X-FB-Auth: crp:<challenge_string>:<response>
X-FB-AuthVerifier: md5=158601965397d1fe437d17fc359518b8&mode=UploadPic
X-FB-GetChallenge: 1
X-FB-UploadPic.Receipt: 0123456789abcdef
X-FB-UploadPic.MD5: 158601965397d1fe437d17fc359518b8
X-FB-UploadPic.Sec: 255
X-FB-UploadPic.Meta.Filename: DSCN1205.JPG
X-FB-UploadPic.Gallery._size: 1
X-FB-UploadPic.Gallery.0.GalName: My Existing Gallery
Content-Length: 0
[no content sent, we have a receipt and the server already has the data]
Fifth Request: Upload Image #3
PUT /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPic
X-FB-Auth: crp:<challenge_string>:<response>
X-FB-AuthVerifier: md5=358601965397d1fe437d17fc359518b8&mode=UploadPic
X-FB-GetChallenge: 1
X-FB-UploadPic.MD5: 358601965397d1fe437d17fc359518b8
X-FB-UploadPic.ImageSize: 324234
X-FB-UploadPic.Sec: 255
X-FB-UploadPic.Meta.Filename: DSCN1205.JPG
X-FB-UploadPic.Gallery._size: 1
X-FB-UploadPic.Gallery.0.GalName: My Existing Gallery
Content-Length: 324234
[no receipt for this image, send full ImageData in POST content]
As you can see, uploading n pictures requires either n+1 or n+2 HTTP requests.
Uploading Temporary Files#←↑
The FotoBilder protocol has a method called "UploadTempFile" which allows clients to upload an image via HTTP PUT or MIME-Encoded POST to be stored for 30 seconds, then receive a recipt to upload it via a subsequent request later. Why would a client ever want to do this? In the case that a client is written using an RPC encoding which doesn't support the sending of binary data (SOAP, XML-RPC) the client can do a very simple HTTP PUT/POST to send the image data to the server and get a receipt, then do do the tricky part of the upload in SOAP/XML-RPC, specifying a receipt for the data. It's just meant to simplify the life of client authors writing in environments with poor HTTP libraries, but good SOAP/XML-RPC support.
Below is an example of how to upload a temporary file using HTTP PUT:
PUT /interface/rest/UploadTempFile HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Auth: crp:<challenge_string>:<response>
X-FB-AuthVerifier: md5=358601965397d1fe437d17fc359518b8&mode=UploadTempFile
Content-Length: 324234
<ImageData>
The server will respond with a receipt for the image just uploaded, which will be good for 30 seconds. This can be used in any subsequent UploadPic request to "upload" the temporary file with given gallery membership and security.
Fetching#←↑
Fetching Galleries#←↑
In order to provide a gallery selection widget to users, you'll likely want to fetch a list of galleries from the server. Doing so is very simple, but due to do the flexibility of FotoBilder's gallery relation model, interpretting the gallery hierarchy can sometimes be tricky.
Galleries can have multiple childen, as well as multiple parents (though the first is more obvious). They can also can make loops. The FotoBilder web UI always shows all paths down from the top level for each line of descent, preventing duplicate galleries from being shown per path down, not globally. Thus, assuming the following parent -> child relationships:
A -> B -> C -> A,
Top -> A,
Top -> C
The web UI would show:
- A
- B
- C
- B
- C
- A
- B
- A
And not:
- A
- B
- C
It is encouraged that your application do the same, for consistency.
Because of the complexity of the gallery relationship model, there are two ways to retrieve gallery information, depending on your intent and level of laziness:
- GetGals
Returns a flat dump of all galleries, their IDs, and parent/child relationships. When using GetGals, it is up to the client application to detect loops and breaking them when pre-populating a treeview control or similiar. If you want to handle interpretation of the gallery graph on your own, this is the best method to use.
The following is a simple request to get a flat representation of a user's galleries using the GetGals protocol method:
GET /interface/simple HTTP/1.x Host: www.fb.com X-FB-User: bob X-FB-Mode: GetGals X-FB-Auth: crp:<challenge_string>:<response> X-FB-AuthVerifier: md5=358601965397d1fe437d17fc359518b8&mode=GetGalsSee the GetGals method page for a reference to the structure of the XML response from the server.
Each Gal block returned contains individual attributes of the gallery (Name, Sec, Date, etc), a list of all pictures in the gallery, and links to its parent and child galleries (in the ParentGals and ChildGals blocks). Each relation contains the ID of the parent or child as well as a 'sortorder' attribute which defines the order in which child galleries should be displayed. Alternatively, the client could also ignore that and show it alphabetically.
- GetGalsTree
Returns a pre-formed tree representation of a user's galleries, following the same rules that are used by the FotoBilder web UI and recommended for all client applications. The data structure returned recursively represents galleries in branches stemming from the top-level (in the RootGals block), as well as branches that have been rendered unreachable and stem from nowhere (in the UnreachableGals block). If you are trying to get a suitable tree of a user's galleries in the simplest and most standard way possible, use this method.
The following is a simple request to get a tree representation of a user's galleries using the GetGalsTree protocol method:
GET /interface/simple HTTP/1.x Host: www.fb.com X-FB-User: bob X-FB-Mode: GetGalsTree X-FB-Auth: crp:<challenge_string>:<response> X-FB-AuthVerifier: md5=358601965397d1fe437d17fc359518b8&mode=GetGalsTreeSee the GetGalsTree method page for a reference to the structure of the XML response from the server.
Gal blocks in the RootGals and UnreachableGals are identical except for the way they should be interpretted by your application. Galleries under RootGals should be presented as stemming from the top level of the user's gallery tree while galleries under UnreachableGals should be presented as being effectively invisible and in need of reparenting. The UnreachableGals block should generally be empty, but it is required that you handle the case where certain branches of galleries have been rendered unreachable.
As with the GetGals method, each Gal block contains gallery-specific attributes like Name and Sec and a list of pictures within the gallery, but the relationships between galleries are handled differently. Each Gal block contains a ChildGals block, which contains any number of Gal blocks that are children of the current gallery. Though the children are returned sorted according to their 'sortorder' attributes, your application should not count on this behavior. Be sure to sort the galleries based on the numeric sortorder values after the response is received and the XML is parsed.
The GetGalstree protocol method is provided as a convenience for client authors. In most situations it is simpler on the client author to use the pre-formed tree and just write a simple recursive function to traverse the galleries when populating widgets. If for some reason this representation turns out to be a pain on your platform or you would like to build your own tree, then you should use the GetGals method instead.
Fetching a User's Pictures#←↑
You may wish to retrieve a list of all pictures a user has uploaded. This can be useful in a number of situations:
- Picture backups
- Keeping local directories in sync with FotoBilder
- Searching through pictures locally based on some criteria
- Etc
The ideas above are just that, ideas. Really there is no specific purpose for the GetPics method, but it's bound to be useful in a number of situations that only the oh-so-clever client authors of the world will foresee. Here's an example of how to use it:
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetPics
X-FB-Auth: crp:<challenge_string>:<response>
X-FB-AuthVerifier: md5=358601965397d1fe437d17fc359518b8&mode=GetPics
Account for the possibility that the server response returned by this method will likely be very large, so you'll want to limit calls to it and perhaps give the user some sort of status indicator. Also remember that data in the 'Meta' response element is just that: meta-data. So though meta-data elements such as 'title', 'description', and 'filename' are extremely useful, you'll need to always be sure to account for the possibility that they are completely undefined; both when parsing server responses and planning UI (if you have one).
Getting Image Content#←↑
Once a list or tree of pictures has been fetched using GetPics, the <URL> element of each image gives the URL at which the full-resolution image can be obtained using HTTP GET. Typically this takes the following form:
http://pics.livejournal.com/username/pic/00007y4
"00007y4" is a hexidecimal identifier for the image. The image will only be available if the proper credentials are present -- either a web session cookie or the X-FB-Auth header.
Gallery Formatting#←↑
Be careful -- by simply adding a "/" to the URL, the image will be displayed and scaled with gallery formatting. An example URL:
http://pics.livejournal.com/username/pic/00007y4/
Obviously, getting HTML instead of the expected image data would produce unexpected results in a client.
Thumbnails#←↑
Thumbnails can be obtained for any image by appending /tXXYY to the URL provided in the XML. XX is a hex value representing the maximum width in pixels, and YY is a hex value representing the maximum height. For example:
http://pics.livejournal.com/username/pic/00007y4/t8080
This would return a thumbnail of the image in which the width nor height was greater than 128 pixels. The aspect ratio will be maintained, so one side may be smaller than the size you specified, but never larger, except when the "Zoom" option is used. See "Zoomed Thumbnails" for details.
Note that EXIF data is stripped from the returned thumbnail for efficiency.
Warning: The dimensions must be smaller than or equal to 200 pixels, or C8 in hex. Anything larger will return a 404.
Zoomed Thumbnails#←↑
By appending the z argument to a thumbnail URL, the returned image will be the exact dimensions you specified, but cropped around what's called the "focus point." For example:
http://pics.livejournal.com/username/pic/00007y4/t8050z
This will return a thumbnail that is exactly 128x80, but cropped and zoomed so as to maintain aspect ratio. Note that this argument has the ability to zoom in farther than the image's resolution, which you will most likely only notice if even the full-resolution image is small.
Fetching Security Groups#←↑
Pictures and galleries have securities independent of one another. Below is a breakdown of what aspects of a picture/gallery's visibility are affected by each setting:
- Picture Security
-
- Image visibility (via direct image URL)
- Picture visibility in gallery views
- Single picture view visibility
- Gallery Security
-
- Gallery visibility in other gallery views
- Gallery links from single picture views
- Single gallery view visibility
To illustrate the interactions of gallery and picture security, consider the following situations:
- Public Gallery, Private Image
-
- Gallery: Visible to everyone, but only the image owner will see the private image in the list
- Picture (via direct image URL): Visible to only the owner
- Private Gallery, Public Image
-
- Gallery listing: Visible to owner only
- Picture (via direct image URL): Visible to everyone
The examples above only deal with public and private securities because they effectively illustrate "can view" and "cannot view" as the simplest possible terms, but security groups can be much more complicated. Inside FotoBilder, security is represented by a 1-byte unsigned integer (0-255) which identifies a "Security Group". Some groups are system-defined constants, others are user-defined, and others are defined via authentication modules (e.g. LiveJournal friend groups exported to FotoBilder). The numeric ID breakdown is like this:
- 0: Private
- Viewable only by owner
- 1-125: User-Defined Security Groups
- Arbitrary user-defined list of trusted users
- 126-250: Authentication Module-defined Security Groups
- Reserved for use by authentication modules. An example is the LiveJournal Authentication Module which stores LiveJournal friends groups in this range.
- 251-252: Reserved for system use
- Two security groups reserved for future system use. Ignore these for now.
- 253: Registered Users
- Viewable by any registered user
- 254: All groups
- Viewable by users who are a member of any security group
- 255: Public
- Public, for the whole world to see
The server will return proper names and IDs for each security group, so you don't really need to worry too much about the different types. However, if you want to break them up into different categories or give special icons to different groups (in a drop-down, for instance) you'll need to understand the significance of the security IDs.
Creating#←↑
Creating Galleries#←↑
There are two methods provided for creating galleries. Which you use will vary depending on the flow of your client application and what is most convenient.
- UploadPic
- When uploading a picture via the UploadPic protocol method, you have the option of specifying which galleries the picture should be added to by a combination of GalName and Path down the gallery tree from the root. When Specifying either a GalName or Path + GalName, new galleries will be created as necessary in order to create the gallery structure you specify. For more details about how this works, see the uploading tutorial and UploadPic method documentation.
- CreateGals
- There is a protocol method intended explicitly for creating one or more new galleries. You may specify a ParentID to create each new gallery under, or a list of GalNames to be auto-vivified as a path from the gallery root. In any case, you must specify a GalName for the new gallery to be created. If both Path and ParentID are ommitted, then the gallery will be created top-level.
The following is an example of a CreateGals request which creates four galleries. Two are top-level, one is three levels deep as specified by a path, and the fourth is to be created as a child of the gallery with GalID '13'. The GalSec and GalDate values vary.
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: CreateGals
X-FB-Auth: crp:<challenge_string>:<response>
X-FB-CreateGals.Gallery._size: 3
X-FB-CreateGals.Gallery.0.ParentID: 0
X-FB-CreateGals.Gallery.0.GalName: End of the World Party, 2001
X-FB-CreateGals.Gallery.0.GalSec: 0
X-FB-CreateGals.Gallery.1.GalDate: 2002-09-17
X-FB-CreateGals.Gallery.1.GalName: End of the World Party, 2002
X-FB-CreateGals.Gallery.1.GalSec: 255
X-FB-CreateGals.Gallery.2.Path._size: 2
X-FB-CreateGals.Gallery.2.Path.0: Parties
X-FB-CreateGals.Gallery.2.Path.1: End of the World
X-FB-CreateGals.Gallery.2.GalName: End of the World Party, 2003
X-FB-CreateGals.Gallery.2.GalSec: 255
X-FB-CreateGals.Gallery.3.GalDate: 2004
X-FB-CreateGals.Gallery.3.GalName: End of the World Party, 2004
X-FB-CreateGals.Gallery.3.ParentID: 13
X-FB-CreateGals.Gallery.3.GalSec: 255
This page will be updated as more Create* methods are created.
Technical Information#↑
RPC Method Documentation#←↑
Many, but not all of these methods can be invoked all in one RPC request.
- GetChallenge
- Request a challenge which is good for use on any one request within the next 30 seconds.
- Special in that it requires a "User" argument, but no "Auth".
- GetGals
- List of all of a user's galleries.
- GetPics
- List of all of a user's pictures.
- GetSecGroups
- List of all of a user's security groups and their members
- UploadPrepare
- Retrieve current quota info.
- Determine what pictures are already uploaded via MD5 and magic.
- UploadTempFile
- Upload a temp file which will be stored for 60 seconds and get a receipt back that can be used to "upload" the already-uploaded TempFile to one or more galleries.
- UploadPic
- Upload a picture given its full image data, token from UploadTempFile, or token from UploadPrepare.
CreateGals#←↑
des: Create one or more galleries
fmt: Simple, SOAP, XML-RPC
notes:
Request#←↑
GET /interface/simple
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: CreateGals
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-CreateGals.Gallery._size: 3
X-FB-CreateGals.Gallery.0.ParentID: 0
X-FB-CreateGals.Gallery.0.GalName: End of the World Party, 2002
X-FB-CreateGals.Gallery.0.GalSec: 0
X-FB-CreateGals.Gallery.1.GalName: End of the World Party, 2003
X-FB-CreateGals.Gallery.1.GalSec: 0
X-FB-CreateGals.Gallery.2.Path._size: 2
X-FB-CreateGals.Gallery.2.Path.0: Parties
X-FB-CreateGals.Gallery.2.Path.1: End of the World
X-FB-CreateGals.Gallery.2.GalName: End of the World Party, 2004
X-FB-CreateGals.Gallery.2.GalSec: 255
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- CreateGals
An array of Gallery structs describing the galleries to be created. Each struct must contain a GalName and optionally a ParentID or Path, but not both.
- GalName
- A string specifying the name of the gallery to be created.
- Path (array)
- An optional path under which the gallery should be created. Each element of the array should be a gallery name to be created recursively as a child of the previous element (if they don't exist), starting at the gallery root. Path must not be specified at the same time as ParentID
- ParentID
- Creates a child of the gallery specified by ParentID. This is nice if you do not want to deal with building a path array to the gallery you want to create since you already have the GalID of the desired parent. If you do not send a ParentID key, the gallery will be created top-level.
- GalSec
- The security level of the gallery to be created. Defaults to 255 (public). If gallery already exists, its security level is not changed.
- GalDate
- When creating a new gallery, the date of that gallery. Possible forms: yyyy[-mm[-dd[ hh:mm[:ss]]]]. (hh is 24 hour time) Default is to make undated gallery.
Response#←↑
<FBResponse>
<CreateGalsResponse>
<Gallery>
<GalID>38</GalID>
<GalName>End of the World Party, 2002</GalName>
<GalURL>http://pics.whitaker.lj/whitaker/gallery/0001a47q</GalURL>
</Gallery>
<Gallery>
<GalID>39</GalID>
<GalName>End of the World Party, 2003</GalName>
<GalURL>http://pics.whitaker.lj/whitaker/gallery/0001bcgp</GalURL>
</Gallery>
<Gallery>
<GalID>42</GalID>
<GalName>End of the World Party, 2004</GalName>
<GalURL>http://pics.whitaker.lj/whitaker/gallery/0001z629</GalURL>
</Gallery>
</CreateGalsResponse>
</FBResponse>
GetChallenge#←↑
des: get an authentication challenge for future usage in other methods
requiring auth
fmt: Simple, SOAP, XML-RPC
notes: Challenge is an opaque string. Its length may change in future, but
there will be a single-line of text always, without whitespace. There
could possibly be special characters that should be URL-escaped when
sending later. Challenge is valid for one-time use and expire
14 days after creation.
Request#←↑
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetChallenge
Note: If GetChallenge is specified as the primary protocol method using the 'Mode' variable, then it is assumed that no other protocol method calls will be included in the request, so authentication is not required and no others are allowed.
Required Vars#←↑
- User
- Username to fetch challenge for
Optional Vars#←↑
none
Response#←↑
<FBResponse>
<GetChallengeResponse>
<Challenge>crp:230948209384902843</Challenge>
</GetChallengeResponse>
</FBResponse>
GetChallenges#←↑
des: get up to 100 authentication challenges for future usage in other
methods requiring auth
fmt: Simple, SOAP, XML-RPC
notes: Challenge is an opaque string. Its length may change in future, but
there will be a single-line of text always, without whitespace. There
could possibly be special characters that should be URL-escaped when
sending later. Challenges are valid for one-time use and expire
14 days after creation.
Request#←↑
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetChallenges
X-FB-GetChallenges.Qty: 3
Note: Like GetChallenge, if GetChallenges is specified as the primary protocol method using the 'Mode' variable, then it is assumed that no other protocol method calls will be included in the request, so authentication is not required and no others are allowed.
Required Vars#←↑
- User
- Username to fetch challenge for
Optional Vars#←↑
- Qty
- The quantity of challenges being requested. At least 1 is required, max is 100.
Response#←↑
<FBResponse>
<GetChallengesResponse>
<Challenge>ToOEY9OegNjvdI6Q0WmrZZ72aBqcsbtsi9azsWqt</Challenge>
<Challenge>Tc2zWP1hIHZPYUJCdjWDjIwsmBTkvBYr5334GmJo</Challenge>
<Challenge>v3OppsYmzLDgN7giAsAMJGyAunph7ePzZkdzNpLt</Challenge>
</GetChallengesResponse>
</FBResponse>
GetGals#←↑
des: Get gallery info for a given user.
fmt: Simple, SOAP, XML-RPC
notes:
Request#←↑
GET /interface/simple
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetGals
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- GetGals
Response#←↑
<FBResponse>
<GetGalsResponse>
<Gal id='1' sortorder='0' [incoming='1']>
<Name>My Gallery</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000204g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ParentGals>
<ParentGal id='1' />
<ParentGal id='2' />
<ParentGal id='3' />
</ParentGals>
<ChildGals>
<ChildGal id='1' order='1'/>
<ChildGal id='2' order='2'/>
<ChildGal id='3' order='3'/>
</ChildGals>
</Gal>
<Gal id='2' sortorder='1'>
...
</Gal>
</GetGalleriesResponse>
</FBResponse>
GetGalsTree#←↑
des: Get gallery info for a given user, represented in a pre-formed tree structure.
fmt: Simple, SOAP, XML-RPC
notes:
Request#←↑
GET /interface/simple
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetGalsTree
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- GetGalsTree
Response#←↑
The response is a tree structure representing the parent-child relationships of all galleries belonging to the user. Two two top-level elements RootGals and UnreachableGals are both lists of gallery tree branches. Structurally, RootGals and UnreachableGals are the same. However, branches within the RootGals should be considered to branch off of the root (trunk) of the gallery tree, while branches within UnreachableGals should be considered to branch off of nothing. It should never be easy for a user to create unreachable galleries, but we do account for such a case and attempt to handle it as gracefully as possible. Clients should display unreachable galleries in a way that makes it clear to the user that they must be reparented to a reachable gallery before they will be visible.
Cycles in the graph are broken using the recommended method described in the gallery fetching tutorial. If you prefer to interpret the gallery graph in a different way, use the GetGals method to fetch the raw gallery and relation information and traverse the tree as you wish.
<FBResponse>
<GetGalsResponse>
<RootGals>
<Gal id='1' [incoming='1']>
<Name>Top Level Gallery 1</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000201g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
<Gal id='2' [incoming='1']>
<Name>Child Gallery 1.1</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000202g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
<Gal id='3' [incoming='1']>
<Name>Child Gallery 1.1.1</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000203g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
</ChildGals>
</Gal>
<Gal id='4' [incoming='1']>
<Name>Child Gallery 1.1.2</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000204g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
</ChildGals>
</Gal>
</ChildGals>
</Gal>
<Gal id='5' [incoming='1']>
<Name>Child Gallery 1.2</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000205g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
</ChildGals>
</Gal>
</ChildGals>
</Gal>
<Gal id='6' [incoming='1']>
<Name>Top Level Gallery 2</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000206g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
</ChildGals>
</Gal>
</RootGals>
<UnreachableGals>
<Gal id='7' [incoming='1']>
<Name>Unreachable Parent</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000207g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
<Gal id='8' [incoming='1']>
<Name>Child of Unreachable Parent</Name>
<Sec>255</Sec>
<Date>2004-01-01 01:01:01</Date>
<TimeUpdate>1096989775</TimeUpdate>
<URL>http://www.fb.com/bob/gallery/0000208g</URL>
<GalMembers>
<GalMember id='1' />
<GalMember id='2' />
</GalMembers>
<ChildGals>
</ChildGals>
</Gal>
</ChildGals>
</Gal>
</UnreachableGals>
</GetGalleriesResponse>
</FBResponse>
GetPics#←↑
des: Retrieve information about all of a user's currently stored pictures.
fmt: Simple, SOAP, XML-RPC
notes: This is basically the functionality that used to live at htdocs/manage/export.bml
Request#←↑
GET /interface/simple
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetPics
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- GetPics
Response#←↑
<FBResponse>
<GetPicsResponse>
<Pic id='1'>
<Sec>0</Sec>
<Width>2048</Width>
<Height>3072</Height>
<Bytes>1280381</Bytes>
<Format>image/jpeg</Format>
<MD5>458601965397d1fe437d17fc359518b8</MD5>
<URL>http://www.fb.com/bob/pic/00001r1h</URL>
<Meta name='filename'>somefile.jpg</Meta>
<Meta name='title'>This is my test file!</Meta>
<Meta name='description'>OMG This is a description of my first image LOL!!!</Meta>
</Pic>
<Pic>
...
</Pic>
</GetPicsResponse>
<FBResponse>
GetSecGroups#←↑
des: Get information about security groups and their members.
fmt: Simple, SOAP, XML-RPC
args: none
notes:
Request#←↑
GET /interface/simple
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: GetSecGroups
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- GetSecGroups
Response#←↑
<FBResponse>
<GetSecGroupsResponse>
<SecGroup id='1'>
<Name>Privileged People</Name>
<GroupMembers>
<GroupMember id='1' user='someuser' />
<GroupMember id='2' user='otheruser@otherdomain.com' />
</GroupMembers>
</SecGroup>
</GetSecGroupsResponse>
</FBResponse>
Login#←↑
des: "Login" via the client protocol and retrieve any messages from the
system, quota information, etc.
fmt: Simple, SOAP, XML-RPC
notes: Since the FotoBilder client protocol is stateless, this login method
is optional, though encouraged as it allows clients to display system
broadcast messages to the user and retrieve other useful information.
As described in the notes section above, this mode is completely optional due to the stateless nature of the protocol. The name is somewhat of a misnomer, but it still makes a lot of sense and there is precedent in the LiveJournal client protocol.
The Login method is meant to be an extensible method which can return useful data that client authors request. Initially, quota information will be returned in the same way it is returned via the UpladPrepare method:
FotoBilder does not natively support disk quotas for users. It is, however, implemented by optional site-specific hooks on most public installations. Therefore, your client will always receive the Quota block (shown above) from pics.livejournal.com as well picpix.com, but you cannot absolutely count on the information being present since many smaller FotoBilder installations will not have quota support implemented. Make sure that your client behaves properly in either situation.
Due to the extensible nature of this method, it is recommended that you take extra care to make sure that you properly handle cases where new data may be present, or expected data may be missing.
Request#←↑
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: Login
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-Login.ClientVersion: MyFBClient/1.0
Required Vars#←↑
- User
- Username to fetch challenge for
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- Login
- ClientVersion
- This should be a string of the form ClientName/ClientVersionMajor.Minor.Rev. For example: "MyFBClient/0.1.3". This string will be used to collect stats about what clients are most popular among users.
Response#←↑
<FBResponse>
<LoginResponse>
<ServerTime>2005-06-10 16:25:23</ServerTime>
<Message>hola</Message>
<Quota>
<Remaining>4291553280</Remaining>
<Total>4294966272</Total>
<Used>3412992</Used>
</Quota>
</LoginResponse>
</FBResponse>
UploadPrepare#←↑
des: Declare intent to upload one or more files, get receipts used
to upload them, do quota checks, and do duplicate file checks.
fmt: Simple, SOAP, XML-RPC
notes:
Request#←↑
GET /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPrepare
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-UploadPrepare.Pic._size: 2
X-FB-UploadPrepare.Pic.0.MD5: 458601965397d1fe437d17fc359518b8
X-FB.UploadPrepare.Pic.0.Magic: 2f3a4fccca6406e35bcf
X-FB.UploadPrepare.Pic.0.Size: 324234234
X-FB-UploadPrepare.Pic.1.MD5: 158601965397d1fe437d17fc359518b8
X-FB-UploadPrepare.Pic.1.Magic: 1f3a4fccca6406e35bcf
X-FB-UploadPrepare.Pic.1.Size: 124234234
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
- Pic (array)
An array of picture info to be checked, possibly returning a receipt for the already-existing image. Values of each array element are hashes with the following keys:
- MD5
- A hex MD5 hash of the image
- Magic
- The first 10 bytes, encoded in hex.
- Size
- The size of the image
The (MD5, Magic, Size) tuple is what makes up the fingerprint which is checked against existing images. The values of all keys must match for a receipt to be returned.
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- UploadPrepare
- pic_md5
- The MD5 hash of all of the MD5s specified in the Pic array concatenated together.
Response#←↑
<FBResponse>
<UploadPrepareResponse>
<Quota>
<Total>1048576</Total>
<Used>524288</Used>
<Remaining>524288</Remaining>
</Quota>
<Pic known='0'>
<MD5>458601965397d1fe437d17fc359518b8</md5>
</Pic>
<Pic known='1' id='1234'>
<MD5>458601965397d1fe437d17fc359518b8</md5>
<Receipt>[opaque-receipt]</Receipt>
</Pic>
<Pic>
<MD5>458601965397d1fe437d17fc359518b8</MD5>
<Error code='2343'>Unknown/unsupported filetype.</Error>
</Pic>
</UploadPrepareResponse>
</FBResponse>
Client checks for the "known" attribute to see if the picture existed on the server.
Quota Information#←↑
FotoBilder does not natively support disk quotas for users. It is, however, implemented by optional site-specific hooks on most public installations. Therefore, your client will always receive the Quota block (shown above) from pics.livejournal.com as well picpix.com, but you cannot absolutely count on the information being present since many smaller FotoBilder installations will not have quota support implemented. Make sure that your client behaves properly in either situation.
Receipts:#←↑
UploadPrepare receipts are given out when an image is already known so that when the client does a subsequent upload, it will not be required to include ImageData along with the request. It should be treated as an opaque string to be passed back to the server via the UploadPic method in order to add the data specified by the UploadPrepare receipt to galleries and with the security you specify in the UploadPic call.
Notes about UploadPrepare receipt usage:
- Receipts are valid for 3 days
- Must be used with the specific picture for which they were issued, not arbitrary protocol requests
- Can only be used once. They'll fail on subsequent uses. If your client supports cancelling the upload, and then user changes options (galleries/securities/etc) and re-uploads, you'll have to do a new GetChallenge and UploadPrepare to get new receipts for the pictures you'd already started to upload.
UploadTempFile#←↑
des: Upload a file for temporary storage and get a receipt back
to use in a subsequent UploadPic request.
fmt: Simple, SOAP, XML-RPC
notes: This method may either be done via a Mime-Encoded POST request
or an HTTP PUT. URL-Encoded requests will not be accepted.
Request#←↑
PUT /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadTempFile
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
Content-Length: 12345
<image data>
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
- ImageData
- The actual data of the image being uploaded. This variable is implicitly filled in with any data sent via HTTP PUT, but needs to be explicitly defined if using MIME-encoded POST.
- ImageLength
- The size of file being uploaded, if any. This variable is implicitly filled in via the request "Content-Length" header for HTTP PUT requests, but must be explicitly defined if using MIME-encoded POST.
Optional Vars#←↑
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- UploadTempFile
- md5
- A hex MD5 hash of the temporary file to be uploaded. An error will be returned if the MD5 doesn't match that of the actual image.
Response#←↑
<FBResponse>
<UploadTempFileResponse>
<Receipt>[opaque-receipt]</Receipt>
</UploadTempFileResponse>
</FBResponse>
or:
<FBResponse>
<UploadTempFileResponse>
<Error code='234'>Out of disk space, yo.</Error>
</UploadTempFileResponse>
</FBResponse>
UploadPic#←↑
des: Upload a picture and place it in a new or existing galllery.
fmt: Simple, SOAP, XML-RPC
notes: Can't do a photo upload through GET args or URL-encode post args without first
retrieving an upload receipt via the UploadTempFile method.
Request#←↑
Simple example using HTTP PUT:
PUT /interface/simple HTTP/1.x
Host: www.fb.com
X-FB-User: bob
X-FB-Mode: UploadPic
X-FB-Auth: crp:0123456789abcdef:0123456789abcdef
X-FB-AuthVerifier: md5=bbf4cf5c9c38f3b3c0ff13f0216cd275&mode=UploadPic
X-FB-UploadPic.MD5: bbf4cf5c9c38f3b3c0ff13f0216cd275
X-FB-UploadPic.ImageLength: 234324
X-FB-UploadPic.PicSec: 255
X-FB-UploadPic.Meta.Filename: DSCN1205.JPG
X-FB-UploadPic.Gallery._size: 3
X-FB-UploadPic.Gallery.0.GalName: End of the World Party, 2002
X-FB-UploadPic.Gallery.0.GalSec: 255
X-FB-UploadPic.Gallery.1.GalID: 233
X-FB-UploadPic.Gallery.2.GalID: 23
Content-Length: 234324
<image-data>
Required Vars#←↑
- User
- Username to authenticate as
- Auth
- Valid challenge/response authentication token
Optional Vars#←↑
- ImageData
- The actual data of the image being uploaded. This is only optional if there is an existing picture or temporary file associated with the given Auth variable. This variable is implicitly filled in with any data sent via HTTP PUT, but needs to be explicitly defined if using MIME-encoded POST.
- ImageLength
- The size of file being uploaded, if any. This variable is implicitly filled in via the request "Content-Length" header for HTTP PUT requests. Although this variable is not required, it is good practice to always fill this variable in. If present, it will be sanity-checked against the received data to make sure there was no error in transmission or in client libraries.
- Receipt
- A receipt given from the UploadPrepare method indicating that the data you wish to upload is already stored somewhere on FotoBilder's servers, so there's no need to retransmit the data. If this is the case, simply send the receipt as the 'Receipt' variable and omit ImageLength and ImageData.
- AuthVerifier
A valid auth verifier string as described in the "Authentication" section. Valid elements are:
- mode
- UploadPic
- md5
- The MD5 hash of the image being uploaded, either via ImageData or Receipt. An error will be returned if the MD5 does not match that of the actual image.
- MD5
- A hex MD5 hash of contents to be uploaded. If it doesn't match after upload, an error will be returned.
- Gallery (array)
An array of Gallery structs describing what galleries this image should be added to. Each struct must contain either a "GalID" or "GalName" member, not both.
- GalName
- Put in all galleries named exactly the value you give. If the gallery doesn't exist, it will be created in the tree as defined by the Path option, or as a top-level gallery if Path is not specified.
- Path (array)
- An optional path under which the gallery should be created. Each element of the array should be a gallery name to be created recursively as a child of the previous element (if they don't exist), starting at the gallery root. This applies when GalName is supplied and does not yet exist, so it needs to be created. Path must not be specified at the same time as ParentID
- ParentID
Filters the applicable galleries matched by GalName to those also having parent GalID of the given ParentID. For example, there may be a dozen galleries named "Party", all child galleries of more descriptive container galleries. If you don't send a ParentID key, the picture is added to all of them. By sending the ParentID, you're specific about which gallery you mean.
If no gallery exists with specified GalName and ParentID value, one is created. ParentID cannot be specified at the same time as Path.
- GalID
- Put uploaded image in the gallery specified by the GalID. If gallery doesn't exist, an error will be returned.
- GalSec
- When creating a new gallery, the security level of the gallery. defaults to 255 (public). If gallery already exists, its security level is not changed.
- GalDate
- When creating a new gallery, the date of that gallery. Possible forms: yyyy[-mm[-dd[ hh:mm[:ss]]]]. (hh is 24 hour time) Default is to make undated gallery.
- PicSec
Security value of picture. If not supplied, the default is public. If picture already exists in gallery, its security level is changed to match what you specified.
The entire URL-encoded value can be repeated multiple times to insert the picture into multiple galleries. Either send multiple HTTP header lines, make the values comma separated, or any mix of both.
A struct of meta-data to attach to the image. Only the following supported keys will be allowed: (others will return an error)
- Filename
- Optional filename to attach to picture, unless it's already uploaded and already has an associated filename. The filename is only kept track of as meta-data and doesn't influence URLs. Maximum of 255 bytes.
- Title
- Optional user-specified title for the picture. Maximum of 255 bytes.
- Description
- Optional user-specified description for the picture. Maximum of 65535 bytes.
Response#←↑
<FBResponse>
<UploadPicResponse>
<URL>http://www.fb.com/bob/234234324/</URL>
<PicID>23</PicID>
<Width>640</Width>
<Height>480</Height>
<Bytes>33902</Bytes>
</UploadPicResponse>
</FBResponse>
or:
<FBResponse>
<UploadPicResponse>
<Error code='234'>Out of disk space, yo.</Error>
</UploadPicResponse>
</FBResponse>
Response Error Messages#←↑
Error messages are returned from protocol requests in an "Error" element under the narrowest block to which they apply. For instance, general errors with the request itself (auth, username, etc) are top-level within the "FBResponse" block:
<FBResponse>
<Error code="101">No user specified</Error>
</FBResponse>
Simiarly, errors with a specific method call will exist within the response block of that method:
<FBResponse>
<GetChallengesResponse>
<Error code="212">Missing required argument: Qty</Error>
</GetChallengesResponse>
</FBResponse>
Error codes in one method's block do not imply success or error in other method's block. So it is completely feasible to have a mix of errors and successes, depending on how many methods you call:
<FBResponse>
<GetChallengesResponse>
<Challenge>FoksLvkdbkLSZM4geSyO0UwGn0YC4dmN8DEGcB2s</Challenge>
<Challenge>9k4Lj2VcDmfvuWmdllvjZzs5q6OsvzR2rFtkE1u1</Challenge>
<Challenge>7CVYhnQZsV1JD67HUSb3aNzm3FGWvAC6HFozKNZC</Challenge>
</GetChallengesResponse>
<CreateGalsResponse>
<Error code="512">Error creating gallery: Gallery aready exists: End of the World Party, 2002</Error>
</CreateGalsResponse>
<GetGalsResponse>
<Gal id="52">
<ChildGals>
</ChildGals>
<Date></Date>
<GalMembers>
</GalMembers>
<Name>End of the World Party, 2003</Name>
<ParentGals>
<ParentGal id="0" sortorder="0" />
</ParentGals>
<Sec>0</Sec>
<TimeUpdate></TimeUpdate>
<URL>http://pics.whitaker.lj/whitaker/gallery/0001w99c</URL>
</Gal>
<Gal id="56" incoming="1">
<ChildGals>
</ChildGals>
<Date></Date>
<GalMembers>
<GalMember id="229" />
<GalMember id="230" />
</GalMembers>
<Name>Unsorted</Name>
<ParentGals>
<ParentGal id="0" sortorder="0" />
</ParentGals>
<Sec>0</Sec>
<TimeUpdate>1114205993</TimeUpdate>
<URL>http://pics.whitaker.lj/whitaker/gallery/00020fz2</URL>
</Gal>
</GetGalsResponse>
<UploadPicResponse>
<Error code="211">Invalid argument: PicSec</Error>
</UploadPicResponse>
</FBResponse>
Error Codes and Meanings#←↑
Below is a table of possible error codes and their meanings. Note that the first number represents the class of the error, and also that the error codes are completely separate from the HTTP response codes on the request.
| 1xx: User Errors | |
| 100 | User error |
| 101 | No user specified |
| 102 | Invalid user |
| 103 | Unknown user |
| 2xx: Client Errors | |
| 200 | Client error |
| 201 | Invalid request |
| 202 | Invalid mode |
| 203 | GetChallenge(s) is exclusive as primary mode |
| 210 | Unknown argument |
| 211 | Invalid argument |
| 212 | Missing required argument |
| 213 | Invalid image for upload |
| 3xx: Access Errors | |
| 300 | Access error |
| 301 | No auth specified |
| 302 | Invalid auth |
| 303 | Account status does not allow upload |
| 4xx: Limit Errors | |
| 400 | Limit error |
| 401 | No disk space remaining |
| 402 | Insufficient disk space remaining |
| 403 | File upload limit exceeded |
| 5xx: Server Errors | |
| 500 | Internal Server Error |
| 501 | Cannot connect to database |
| 502 | Database Error |
| 503 | Application Error |
| 510 | Error creating gpic |
| 511 | Error creating upic |
| 512 | Error creating gallery |
| 513 | Error adding to gallery |
Author#↑
Brad Whitaker <whitaker@danga.com>, Danga Interactive