Shutterfly Open API  |  Call Signature


Overview

A Call Signature is a small set of extra parameters that your application calculates and appends to each Shutterfly Open API call, to digitally "sign" the call.

You calculate the signature parameters anew on each call, using the procedure detailed below (or using a library from Shutterfly that does it). Shutterfly servers verify each call signature by performing the same calculation and comparing the result to yours.

The signature helps Shutterfly know that it has received the parameters you intended to send. If you guard your "shared secret" adequately, the signature also provides MD5-level or SHA1-level proof that the call really came from your app (i.e., was not forged by a third party).

Signature generation can be tricky. For developers working in Java, Shutterfly supplies a library to hide the details discussed below.

An application signs each call by locally gathering and concatenating these pieces of data:

  1. the application ID and shared secret
  2. URL path of the Shutterfly Open API call (omitting the "http://hostname" part)
  3. URL parameters of the Shutterfly Open API call, if any
  4. these three additional Call Signature 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 itself. The app then adds the four Call Signature parameters (app ID, hash method, timestamp and signature digest) to its HTTP call. Notes:

  • App ID is always passed as an URL parameter.
  • Hash method, timestamp and signature digest may be passed either as URL parameters, or as HTTP request headers. Shutterfly will accept them as URL parameters, but generally recommends that you pass them as HTTP request headers, especially on GET calls, for better Web document caching.
  • Do NOT send the shared secret on your calls! Shared secret is needed only when your application generates the signature digest, and should be kept a secret. Do not send it in e-mails!

Signature Generation Details

First, the application must gather its own values for the following three Call Signature parameters:

oflyAppId
Type: String
Required: Yes
Example: 693228dc384ba239269fa6f80de8ce97
Description: Application ID
oflyHashMeth
Type: String
Required: Yes
Example: SHA1 -or- MD5
Description: The digest generation method (hash method) that the application is going to use when generating the app signature.
oflyTimestamp
Type: String
Required: Yes
Example: 2007-06-27T13:15:30.123-0700
Description: Current date and time, to the millisecond and formatted by the W3 profile of ISO 8601 (see http://www.w3.org/TR/NOTE-datetime). The indicated time must be within +/- 15 minutes of Shutterfly server time. For more details, see the Frequently Asked Questions at the end of this document.

Next, the app locally creates a string that concatenates these pieces, in order:

  1. your application's Shared Secret
  2. URI path for the specific API call. Include a leading slash; omit trailing slash. Example: /userid/000012345678
  3. A question mark.
  4. URL parameters for the specific API call, if any. Notes:
    1. They must be in name=value form, separated by & (ampersand).
    2. They must be in alphabetical order by parameter name, and in a case-sensitive manner (so that lowercase 'a' sorts after uppercase 'Z').
    3. The parameter values should NOT be "URL encoded" at this point - e.g., not yet substituting "%20" for blank.
  5. Finally, add the three Call Signature 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 the byte array, using SHA1 or MD5 as previously chosen.

Finally, convert the hash to a hexadecimal character string. The hex string is the signature. It will become the following parameter:

oflyApiSig
Type: String
Required: Yes
Example: f38366843e837d562ff6281ae150e386
Description: The generated call signature digest.

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.)

Example using the Authentication API

The example below does not necessarily give a real signature value, but shows you how to build one. First, if there were no call signature, your app would POST 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: [...]
[...]

with XML as the POST content body, that gives user password, etc.

To build the signature: Imagine that your app ID is "91d6d14801815dda4be4982e9c0d39fa" and shared secret is "5c2db08d7bd25c2e". Your 'concatenated string' for building the signature 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 your 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: when your app finally makes the HTTP call, the order of URL parameters does not matter and the order of HTTP request headers does not matter; their order mattered only when building the 'concatenated string'.

If, instead, your 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 (not shown) would contain XML as specified by the Authentication API document.

Example using the "Go To Shutterfly UE" API

The example below does not necessarily give a real signature value, but shows you how to build one. First, if there were no call signature, your app might redirect the user's browser to GET an URL which looks like this:

http://www.shutterfly.com/go2ue/start.sfly?oflyUserid=9BcNWjVsyg&id=5f37cab8905a7c46132ed58780f5ea666cbbd47cbb382743

To build the signature: Imagine that your app ID is "91d6d14801815dda4be4982e9c0d39fa" and shared secret is "5c2db08d7bd25c2e". Your 'concatenated string' for building the signature should look like this (but all one line):

5c2db08d7bd25c2e/go2ue/start.sfly?id=5f37cab8905a7c46132ed58780f5ea666cbbd47cbb382743&oflyUserid=9BcNWjVsyg
&oflyAppId=91d6d14801815dda4be4982e9c0d39fa&oflyHashMeth=SHA1&oflyTimestamp=2007-07-02T11:38:53.842-0700

If your app sets HTTP headers for Call Signature, the final URL and headers look something like this (but all on one line):

http://www.shutterfly.com/go2ue/start.sfly?oflyUserid=9BcNWjVsyg&id=5f37cab8905a7c46132ed58780f5ea666cbbd47cbb382743
&oflyAppId=91d6d14801815dda4be4982e9c0d39fa

GET /go2ue/start.sfly HTTP/1.1
[...]
oflyTimestamp: 2007-07-02T11:38:53.842-0700
oflyApiSig: 792c4e0a43ef00f9b23a0d8b7042030fbc8e9ddc
oflyHashMeth: SHA1
[...]

Note: when your app finally makes the HTTP call, the order of URL parameters does not matter and the order of HTTP request headers does not matter; their order mattered only when building the 'concatenated string'.

If, instead, your app sets URL parameters for Call Signature, the final URL looks something like this (but all on one line):

https://ws.shutterfly.com/go2ue/start.sfly?oflyUserid=9BcNWjVsyg&id=5f37cab8905a7c46132ed58780f5ea666cbbd47cbb382743
&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.

Example using the "Interactive Sign-in" API

The example below does not necessarily give a real signature value, but shows you how to build one. First, if there were no call signature, your app might redirect the user's browser to GET an URL which looks like this:

https://www.shutterfly.com/oflyuser/createToken.sfly?oflyCallbackUrl=http%3A%2F%2Fmygreatwebsite.com%2FmyAppResumesHere

To build the signature: Imagine that your app ID is "91d6d14801815dda4be4982e9c0d39fa" and shared secret is "5c2db08d7bd25c2e". Your 'concatenated string' for building the signature should look like this (but all one line):

5c2db08d7bd25c2e/oflyuser/createToken.sfly?oflyCallbackUrl=http://mygreatwebsite.com/myAppResumesHere
&oflyAppId=91d6d14801815dda4be4982e9c0d39fa&oflyHashMeth=SHA1&oflyTimestamp=2007-07-02T11:38:53.842-0700

Note: for purposes of the 'concatenated string', your callback URL is NOT URL-encoded yet.

If your app sets HTTP headers for Call Signature, the final URL and headers look something like this (but all on one line):

http://www.shutterfly.com/oflyuser/createToken.sfly?oflyCallbackUrl=http%3A%2F%2Fmygreatwebsite.com%2FmyAppResumesHere
&oflyAppId=91d6d14801815dda4be4982e9c0d39fa

GET /oflyuser/createToken.sfly HTTP/1.1
[...]
oflyTimestamp: 2007-07-02T11:38:53.842-0700
oflyApiSig: 792c4e0a43ef00f9b23a0d8b7042030fbc8e9ddc
oflyHashMeth: SHA1
[...]

Note: when your app finally makes the HTTP call, the order of URL parameters does not matter and the order of HTTP request headers does not matter; their order mattered only when building the 'concatenated string'.

If, instead, your app sets URL parameters for Call Signature, the final URL looks something like this (but all on one line):

https://ws.shutterfly.com/oflyuser/createToken.sfly?oflyCallbackUrl=http%3A%2F%2Fmygreatwebsite.com%2FmyAppResumesHere
&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.

Responses

All Shutterfly APIs return a common set of HTTP status codes. See Common Response 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

My call gets an HTTP status code 400, "Bad request". What does that mean?
You tell us, as follows. When you get an HTTP 400, "Bad request", the response should additionally have an HTTP response body whose content is a specific error message from Shutterfly; for example, "Bad timestamp". If you contact us for support, we will need to know this content, so please look for it.
My call gets an HTTP status code 400, and the response body says "Bad api_sig". What does that mean?
It means Shutterfly does not agree with the call signature that you submitted. If you are using Shutterfly's call signature library (see below), and using it correctly, this should never happen. However, you can cause it to happen if you POST XML to Shutterfly with "Content-Type: application/x-www-form-urlencoded", which is wrong for XML content and confuses Shutterfly's attempts to verify your signature.

Library Support

Does Shutterfly supply a library so I don't have to write my own call signature code?
Yes, provided that you are working in Java. Download this file. It contains the following:
  • Call Signature .jar file for Java 5.0 and later
  • Call Signature .jar file for Java 1.4
  • Javadoc (same for both of the above)
  • A Java 5.0 Sample Program which demonstrates the library
In the Javadoc, start by looking at com.shutterfly.openfly.raf.CallSignUtils: use one of the methods such as prepareOflyParms(), prepareSignedHttpConnection() or prepareSignedUri().

Timestamp

If I write my own call signature code: must I use Shutterfly's exact timestamp format?
Yes.
What is the format?
The format is 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:00
  • 2008-02-21T17:19:54.330Z
  • 2008-02-21T12:19:54.330-05:00
  • 2008-02-21T09:19:54.330-08:00
  • 2008-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.

Does the timestamp have to include milliseconds?
Yes. If your application can't obtain accurate milliseconds, supply 1-3 invented digits between 0 and 999 that will be likely to vary, if the same instance of your application repeats a call within the same second. For example, supply a sequence number or perhaps a random number.
Shutterfly responds that my timestamp is bad. What does that mean?
Your timestamp is wrong. It indicates a time that actually isn't within 15 minutes of current moment in the real world. Check your timestamp carefully, especially its timezone designator. Example: suppose you are in the U.S. Pacific time zone, and you had stated -08:00 with Pacific Standard Time in mind, but the real world has just shifted to Pacific Daylight Time, so your timezone designator now ought to be -09:00. Then your timestamp is incorrect. You can avoid such problems by always expressing times as -00:00, that is, as GMT / UTC. But even then, you could have a bad timestamp if your machine's clock is not set accurately.
What time zone are Shutterfly's servers in?
You don't need to know. Remember, these timestamps are universal moments in time. They have a "timezone designator" indicating their numeric offset from UTC. Make sure your machine's date and time are reasonably correct, and that your application generates a current timestamp in a correct format. Shutterfly will accept any correctly-formatted timestamp that describes a moment within +/- 15 minutes of universal time.
previous
Quick Start
next
User
Authentication
© 1999-2014 Shutterfly, Inc. All rights reserved.