Overview
A Call Signature is a small set of extra parameters that your application calculates and appends to every Shutterfly Open API call, to digitally "sign" the call. Begin by obtaining a Shutterfly Open API application ID and shared secret.
The signature helps Shutterfly know that it has received the parameters you intended to send, including a timestamp. If you guard your "shared secret", the signature also provides MD5-level or SHA1-level protection against a third party forging calls in your app's name.
Signature generation can be tricky. For developers working in Java, Shutterfly supplies a library to make it easier.
An application signs each call by locally gathering and concatenating these pieces of data:
- the application's shared secret
- URL path (omitting the "http://hostname" part)
- URL parameters, if any
- these three parameters: app ID, hash method, and timestamp
The application then generates an MD5 or SHA1 digest of that "concatenated string". The digest becomes a fourth parameter, the call signature. The app then supplies app ID, hash method, timestamp and signature digest on its HTTP call. Notes:
- Do NOT send the shared secret on your calls. Shared secret is needed only when your application generates the signature digest.
- App ID must always be passed as an URL parameter.
- Hash method, timestamp and signature digest may be passed as either additional URL parameters, or as HTTP request headers. Shutterfly will accept them as URL parameters, but recommends passing them as HTTP request headers instead - especially on Get calls - because that allows the Web to cache documents better.
Signature Generation Concepts
First, the application must gather its own values for the following three parameters:
Next, the app locally creates a string that concatenates these pieces, in order:
- your application's Shared Secret
- URI path for the specific API call. Include a leading slash; omit trailing slash. Example: /userid/000012345678
- A question mark.
- URL parameters for the API, if any, in alphabetical order. Notes:
- They must be in name=value form, separated by & (ampersand).
- "Alphabetical order" means alphabetical by parameter name, and in a case-sensitive manner (so that lowercase 'a' sorts after uppercase 'Z').
- The parameter values should not be "URL encoded" at this point - e.g., NOT substituting "%20" for blank, yet.
- Finally, the three parameters, as if they were additional URL parameters (i.e., name=value, with & as a separator). They must be in this order: oflyAppId, oflyHashMeth, oflyTimestamp.
Next, if building the above string on a Unicode system, take a UTF-8 encoded byte array of the concatenated string.
Next, take a message digest (a hash) of those bytes, using SHA1 or MD5 as previously chosen.
Finally, convert the hashed bytes to a hexadecimal string. The hex string is the signature. It will become the following parameter:
Your application now has values for all four Call Signature parameters - app ID, hash method, timestamp and signature digest. At this point, build your final URL and make the call. Notes:
- When finally making your Shutterfly Open API call: URL parameters need not be in any special order.
- Again, always put
oflyAppId=as an URL parameter, and the other Call Signature parameters either as additional URL parameters or as HTTP request headers (recommended). - As a very last step, make sure the final URL is "URL encoded". (Substitute %20 for blank, %2B for plus sign, etc.)
Examples
Here is an example for the Authentication API. If there were no call signature, the developer would post to an URL like this:
https://ws.shutterfly.com/user/asdfasdf4@yahoo.com/auth POST /user/asdfasdf4@yahoo.com/auth HTTP/1.1 Content-Type: [...] Content-Length: [...] [...]
To build the signature: Imagine the app ID is "91d6d14801815dda4be4982e9c0d39fa" and the shared secret is "5c2db08d7bd25c2e". The string built at step 2, above, should look like this (but all on one line):
5c2db08d7bd25c2e/user/asdfasdf4@yahoo.com/auth?oflyAppId=91d6d14801815dda4be4982e9c0d39fa &oflyHashMeth=SHA1&oflyTimestamp=2007-07-02T11:28:36.776-0700
If the app sets HTTP headers for Call Signature, the final URL and headers look something like this:
https://ws.shutterfly.com/user/asdfasdf4@yahoo.com/auth?&oflyAppId=91d6d14801815dda4be4982e9c0d39fa POST /user/asdfasdf4@yahoo.com/auth HTTP/1.1 Content-Type: [...] Content-Length: [...] oflyTimestamp: 2007-07-02T11:28:36.776-0700 oflyApiSig: 9a2910628acc54caeac6516acdf26f2171a2ab51 oflyHashMeth: SHA1 [...]
Note: in the app's final HTTP call, the order of URL parameters does not matter and the order of HTTP request headers does not matter.
If, instead, the app sets URL parameters for Call Signature, the final URL and headers look something like this (but the URL on one line):
https://ws.shutterfly.com/user/asdfasdf4@yahoo.com/auth?&oflyAppId=91d6d14801815dda4be4982e9c0d39fa &oflyApiSig=9a2910628acc54caeac6516acdf26f2171a2ab51&oflyTimestamp=2007-07-02T11:28:36.776-0700 &oflyHashMeth=SHA1 POST /auth HTTP/1.1 Content-Type: [...] Content-Length: [...]
Again, in the above, the order of URL parameters does not matter. And the POST body contains XML (not shown) as specified by the Authentication API document.
Here is another example, for creating a new Shutterfly member. If there were no call signature, the developer would post to an URL like this:
https://ws.shutterfly.com/user
To build the signature: Imagine the app ID is "91d6d14801815dda4be4982e9c0d39fa" and the shared secret is "5c2db08d7bd25c2e". The string built at step 2, above, should look like this (but all one line):
5c2db08d7bd25c2e/user?oflyAppId=91d6d14801815dda4be4982e9c0d39fa&oflyHashMeth=SHA1 &oflyTimestamp=2007-07-02T11:38:53.842-0700
If the app sets HTTP headers for Call Signature, the final URL and headers look something like this:
https://ws.shutterfly.com/user?oflyAppId=91d6d14801815dda4be4982e9c0d39fa POST /user HTTP/1.1 [...] oflyTimestamp: 2007-07-02T11:38:53.842-0700 oflyApiSig: 792c4e0a43ef00f9b23a0d8b7042030fbc8e9ddc oflyHashMeth: SHA1 [...]
Note: in the app's final HTTP call, the order of URL parameters does not matter and the order of HTTP request headers does not matter.
If, instead, the app sets URL parameters for Call Signature, the final URL looks something like this (but all on one line):
https://ws.shutterfly.com/user?oflyAppId=91d6d14801815dda4be4982e9c0d39fa &oflyApiSig=792c4e0a43ef00f9b23a0d8b7042030fbc8e9ddc&oflyTimestamp=2007-07-02T11:38:53.842-0700 &oflyHashMeth=SHA1
Again, in the above, the order of URL parameters does not matter. And the POST body contains XML (not shown) as specified by the Authentication API document.
Responses
All Shutterfly APIs return a common set of HTTP status codes. See Error Codes
API Explorer
You can test the correctness of your signature generation process with Shutterfly's API Explorer for Call Signature.
Frequently Asked Questions
General
Library Support
- Library for Java 5.0 (and later)
- Library for Java 1.4
- Javadoc (same for both libraries)
Timestamp
YYYY-MM-DDThh:mm:ss.sssTZD, where:
| YYYY | = | four-digit year | |
| MM | = | two-digit month | (01 through 12) |
| DD | = | two-digit day of month | (01 through 31) |
| hh | = | two-digit hour | (00 through 23; am/pm NOT allowed) |
| mm | = | two-digit minute | (00 through 59) |
| ss | = | two-digit second | (00 through 59) |
| sss | = | three-digit millisecond | (000 through 999) |
| TZD | = | time zone designator | (Z or +hh:mm or -hh:mm) |
The following timestamps will cause different call signatures, but are all recognized as the same moment in universal time:
2008-02-21T17:19:54.330-00:002008-02-21T17:19:54.330Z2008-02-21T12:19:54.330-05:002008-02-21T09:19:54.330-08:002008-02-22T02:49:54.330+09:30
Because of the time zone designator, a timestamp represents a universal moment in time. The time zone designator is either the single character Z to indicate UTC (Coordinated Universal Time), or your time zone's offset from UTC described in hours and minutes.
