Shutterfly Open API  |  Call Signature


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 hide the details discussed below.

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

  1. the application's 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.

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

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

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 one or more of the following: 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
© Copyright Shutterfly 1999-2009. All rights reserved.