From v1 to v2

Migrating from v1 to v2 of the SQUAKE API

Migrate your integration from v1 to v2 of the SQUAKE API: what changed conceptually, side-by-side request examples, and every breaking change in keys and values.

Conceptual changes

Carbon activities become calculations, pricing and purchases

v1 had a single object and endpoint called "carbon activity" for creating, purchasing and refunding. One carbon activity had many "carbon activity items". A carbon activity item is a single item that is part of a carbon activity, for example a single flight from A to B. Another item could be a single train ride from C to D.

The /carbon_activities endpoint mixes calculating emissions, getting pricing information, and handling purchases and refunds.

Each emissions calculation is hard-linked to a unique ID. You use this ID to make a single purchase (or refund). If you want to offer compensations for the same activity to many end-users, you must make a separate calculation for each end-user, resulting in N+1 API calls, each with the exact same payload and same response (except for the unique ID).

v2 has multiple objects and endpoints, each with its own purpose. The three major concepts are calculations, pricing and purchases.

EndpointPurpose
/calculationsCalculate emissions for one or multiple "items". These items are similar to the "carbon activity items" in v1. The "carbon activity" container is gone.
/pricingGet a price quote for either a fixed total (for example 25 USD) or a specific amount of carbon emissions (for example 150 kg CO2e).
/purchasesPurchase carbon credits. You must request a price quote from /pricing first.
/refundsRefund a purchase. Within 14 days of a purchase, no refund is necessary: call /purchases/:id/cancel to cancel the purchase.

The calculations and pricing endpoints are now stateless. If you want to offer compensations for the same activity to many end-users, you can make a single calculation for each end-user. This results in a single API call for, for example, a flight from A to B in economy class for one traveler. You can use the returned pricing information to make a purchase for all end-users that are interested in the same flight.

Breaking down the single multi-purpose endpoint from v1 allows for a more flexible API, resulting in a simpler integration. It also lets us add functionality to the API more easily, without breaking changes and while keeping complexity low.

Project splits and portfolios become products

Initially, v1 let you choose one specific project to contribute to. Then we added multiple projects, and finally the option to split your purchase across multiple projects with a chosen percentage. This was complex and led to many errors, so we added "portfolios", which are collections of projects. You choose a portfolio, and we split your purchase across the projects in it. Then we added the option to split across multiple portfolios. To avoid a breaking change, combinations of all these options were possible.

The payload options grew complex and became incomprehensible. It also made swapping projects more complex, which is necessary in rare instances due to the volatile and complex nature of the carbon market.

v2 offers a single concept called "product" that you purchase. A product is a collection of projects (the same as a portfolio). During onboarding, we evaluate your needs and goals and custom-create one or several products for you. In the future, you may be able to create your own products, but for now, we create them for you.

The v1 payload below is one of many possible ways to split a purchase; in v2, one key-value pair is all you need.

{
  "project_split": [
    {
      "external_pricing_reference": "ps_1",
      "split": [
        {
          "project_code": "project_0110",
          "percentage": 70
        },
        {
          "project_code": "project_0007",
          "percentage": 30
        }
      ]
    },
    {
      "portfolio_id": "portfolio_abc_123"
    }
  ]
}

Expand (new in v2)

v1 returns huge responses. For example, the pricing information returns multiple keys, in different variations, some with more and some with less information. This led to confusion, convoluted logs, and a lot of unnecessary data transfer and complexity.

v2 by default returns simplified payloads with only the information that any kind of integration requires. Further, optional objects are included as an ID only. To get full, nested objects, use the expand parameter. For example, to get the full project information, use expand=project.

This concept exists throughout the API and lets you customize the complexity and amount of information the API returns. For an MVP or simple testing, you most likely want to omit expand and get the simplest response. For a more sophisticated integration, use expand to cherry-pick all the information you need.

For example, pricing without expand returns just an ID for the product, and with expand it includes more information:

{
  "product": "product_5ea9f3",

  "id": "...",
  "carbon_quantity": 89257,
  "carbon_unit": "gram",
  "currency": "EUR",
  ...
}

Code examples

A few code examples to get you started.

Get help with your payloads

Send us a sample of your typical API call payloads, and we'll send you back the respective v2 payloads and responses. Or head over to the API reference and Postman collection and give it a try. Your v1 client_secret from the OAuth flow is migrated to v2, so you can use it as an API key.

Calculation and pricing

In v1, creating a carbon activity returns emissions, a price quote, and a unique ID for a one-time purchase. In v2, the calculation request returns only emission values ("carbon quantity & unit"): no ID, no price quote.

{
  "items": [{
    "carbon_activity_type": "flight",
    "parameters": {
      "origin": "TXL",
      "destination": "HAM",
      "booking_class": "economy",
      "number_of_travelers": 2,
      "aircraft_type": "320",
      "algorithm_type": "icao"
    }
  }],
  "project_split": [
    {
      "project_code": "project_0110",
      "percentage": 100
    }
  ]
}

Flatter payloads, clearer names

Payloads and responses are not deeply nested anymore, and the naming is more consistent and easier to understand. For example, algorithm_type is now methodology, and carbon_activity_type is now type. Methodologies have a consistent spelling and now express the underlying methodology that is applied. For example, "specific" is named "US-EPA", so you can research the US EPA methodology.

Request a pricing with a GET:

curl \
 -X GET https://api.squake.earth/v2/pricing \
  -d product=product_5ea9f3 \
  -d carbon_quantity=1000000 \
  -d carbon_unit=gram \
  -d currency=EUR

It returns a price quote and an ID that you can use to make one or multiple purchases for the requested carbon quantity at the price we returned.

We still offer a combined endpoint to get the calculation and pricing in one API call if needed. Use the same request body as for the calculation, and add a product and a currency:

{
  "product": "product_5ea9f3",
  "currency": "EUR",
  "items": [{
    "type": "flight",
    "methodology": "ICAO",
    "origin": "TXL",
    "destination": "HAM",
    "booking_class": "economy",
    "number_of_travelers": 2,
    "aircraft_type": "320"
  }]
}

It returns emissions, a price quote, and the ID for purchasing.

Purchase

In v2, the additional payload options to request a receipt via email, a PDF certificate and so on are the same as in v1. We have renamed a few keys and un-nested the payloads as far as possible.

curl \
 -X POST https://api.squake.earth/carbon_activities/{id}/purchase

Idempotency

The v2 purchase endpoint accepts the external_reference parameter. It works as an idempotency key: the endpoint creates a purchase for this key only once and responds with 201 (created). If you call it again with the payload and key, you get 200 (ok) and the same purchase object as before.

List of all breaking changes

Besides the obvious structural changes, a few keys and values have been renamed.

Counting human beings

v1v2
number_of_passengersnumber_of_travelers
number_of_travelersnumber_of_travelers
number_of_visitorsnumber_of_travelers

Carbon activity types

v1v2
ship_freightsea_freight
ship_freight_inland_waterwayinland_waterways
train_freigthrail_freight
truckroad_freight
parcellogistics
money_amountRemoved: request a pricing for a fixed total
generalRemoved: this was just a fixed amount of carbon, so request a pricing straight for a specific amount of carbon
co2_amountRemoved, same as general

Algorithm type to methodology

Besides renaming this property from algorithm_type to methodology, we also improved the naming of the values. All methodologies are consistently named using ALL-CAPS-WITH-DASHES.

The v1 values specific, simple, extend and others are removed. The v2 methodologies are:

v2 methodologyMeaning
US-EPAWe use the methodology published by the "United States Environmental Protection Agency". This was formerly called "specific" or similar.
EU-EEAWe use the methodology published by the "European Environment Agency". This was formerly called "simple" or similar.
SQUAKEMethodology developed by our in-house research team, based on the best available data and latest research. This was formerly called "extend" or similar.
BASICSimple approximation, useful when you have sparse data. These are either public or in-house developed approximations, for example based on industry averages. This was formerly called "simple" or similar.

We still have all the others, for example ACRISS, GLEC and so on (and a few new ones).

Authentication

v1 used OAuth2, which proved complex to implement for many customers. Generated access tokens were short-lived, and you had to implement the rotation.

In v2, API keys no longer expire automatically. You can still rotate them in the dashboard if you wish.

MethodHow
API key authSend your API key in the header of each request.
Basic authSend your API key as the username and leave the password empty, base64 encoded.
mTLSContact us if you require mTLS.

Error messages

v1 errors were not consistent and usually contained the code/message or schema_errors object.

v2 errors follow the JSON API standard. If the request fails, the response contains an errors array like this:

{
  "errors": [
    {
      "code": "invalid_params",
      "detail": "Positive number expected for 'number_of_nights', got '-1'.",
      "source": {
        "attribute": "number_of_nights",
        "model": "campingsite_parameters",
        "id": "my-test-booking"
      }
    },
    {
      "code": "invalid_params",
      "detail": "Invalid country 'FR1'. Expected one of: DE, FR, FI, NO, SE, DK, IS, FO.",
      "source": {
        "attribute": "country",
        "model": "camping_site",
        "id": "my-test-booking"
      }
    },
    {
      "code": "invalid_params",
      "detail": "Invalid camping_type: 'invalid'. Expected one of: caravan_mobile_home, semi-integrated_motorhome, integrated_motorhome, panel_van.",
      "source": {
        "attribute": "camping_type",
        "model": "camping_site",
        "id": "my-test-booking"
      }
    }
  ]
}

Other name changes

Areav1v2Notes
Expenditureprice_in_centstotal
Hotel*_stars options for hotel_typeRemovedWe now infer this from stars if the hotel type is omitted.
Hoteleco_labeleco_labelsThe key is pluralized, since it accepted an array of values.
Response from calculationsalgorithm_specificenergy_and_emission_factorsThe content is the same. It is included in the items object returned from the calculations endpoint and contains the factors used for the calculation (as required by some of the methodologies).
Sea freight (v1: "ShipFreight")freight_typecargo_typeAllowed values are dry and reefer.

On this page