JSON crawler

When Snipcart validates an order's integrity, it uses the values specified in the data-item-url attribute of each product.

Most times, the value you'll specify for this attribute will be the unique URL where you're selling the item. However, some merchants could sometimes slightly more complex scenarios.

If that's your case, know that there's an alternative to our default HTML crawler: our JSON crawler.

When Snipcart makes the request to the URL, if your response Content-Type header is application/json, we'll use our JSON validator instead of the HTML one.

You must return us a JSON having the following properties.

{
  "id": "20",
  "price": 50.00,
  "url": "https://snipcart.com/products/1.json"
}

The id, price and url fields are mandatory, and they must be the same ones you specified in the product definition in your HTML.

Note that the object you return may contain other properties, but only those three will be considered.

If you are using our multi currencies feature, the price property can be a hash with multiple currencies.

{
  "id": "20",
  "price": {
    "usd": "30",
    "cad": "35"
  },
  "url": "/"
}

You can also return an array containing multiple objects as defined above.

[
  {
    "id": "20",
    "price": 50.00,
    "url": "https://snipcart.com/products.json"
  },
  {
    "id": "21",
    "price": 100.00,
    "url": "https://snipcart.com/products.json"
  }
]

This can be useful when your website is API-driven, using a single page application framework such as Angular.

Fetching products from a JSON document

In our dashboard you can fetch products if you need to set inventory stock for example. If you are using our JSON validator you can also use your JSON documents to fetch products.

The document can be a JSON file that contains all of your products in an array or a product individually.

The following example is a single product that can be fetched. Please note that this example also set default stock levels.

{
  "id": "JSON_PRODUCT",
  "name":  "JSON Product",
  "url": "/products.json",
  "price": 20.00,
  "image": "http://placehold.it/300x300",
  "inventoryManagementMethod":  "Variant", 
  "variants": [
    {
      "variation": [
        {
          "name": "Color",
          "option": "Red"
        },
        {
          "name": "Size",
          "option": "Small"
        }
      ],
      "stock": 10,
      "allowOutOfStockPurchases":  true
    }
  ],
  "customFields": [
    {
      "name": "Size",
      "options": "Small|Medium|Large",
      "type": "dropdown"
    },
    {
      "name": "Color",
      "options": "Red|Blue|Green",
      "type": "dropdown"
    }
  ]
}

Validating the request

If your data is protected and you want to make sure that the request is coming from Snipcart, you can use the X-Snipcart-RequestToken header. We add this header to each request made to an external website. This is also true for webhooks requests. You can then use this token and call our API back; think of it as a handshake.

The endpoint you'll need to call is: https://app.snipcart.com/api/requestvalidation/{token}.

Here's an example in PHP

protected function validateRequest($data)
{
    if (!isset($_SERVER['HTTP_X_SNIPCART_REQUESTTOKEN'])) {
        throw new Exception('Invalid request: no request token');
    }
    $requestToken = $_SERVER['HTTP_X_SNIPCART_REQUESTTOKEN'];
    $g = new Gateway();
    $g->init('https://app.snipcart.com/api/requestvalidation/' . $requestToken);
    $g->setopt('GET', 1);
    $g->setopt(CURLOPT_USERPWD, eventSnipcart::SNIPCART_API_KEY . ':');
    $g->setopt(CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    $g->setopt('HTTPHEADER', array('Accept: application/json'));
    $response = $g->exec();
    $status = $g->getInfoLast();

    if (empty($response) || $status['http_code'] != 200) {
        throw new Exception('Invalid request: no response');
    }

    $response = @json_decode($response);
    if (!$response) {
        throw new Exception('Invalid request: response not json');
    }
    if ($response->token !== $requestToken) {
        throw new Exception('Invalid request: invalid token');
    }
    return true;
}

Another example in C#

private bool RequestIsValid(HttpRequestBase request)
{
    var requestToken = Request.Headers["X-Snipcart-RequestToken"];

    if (requestToken == null)
        return false;

    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "SECRET_API_KEY:".ToBase64());
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var response = client.GetAsync("http://app.snipcart.local/api/requestvalidation/" + requestToken).Result;

    var content = response.Content.ReadAsStringAsync().Result;
    var json = JsonConvert.DeserializeObject<ValidationToken>(content);

    if (!json.Resource.EndsWith("webhooks/receive") ||
        string.IsNullOrWhiteSpace(json.Token) ||
        !json.Token.Equals(requestToken, StringComparison.InvariantCultureIgnoreCase))
        return false;

    return response.IsSuccessStatusCode;
}

public class ValidationToken
{
    public string Token { get; set; }
    public string Resource { get; set; }
}