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.
| Endpoint | Purpose |
|---|---|
/calculations | Calculate emissions for one or multiple "items". These items are similar to the "carbon activity items" in v1. The "carbon activity" container is gone. |
/pricing | Get a price quote for either a fixed total (for example 25 USD) or a specific amount of carbon emissions (for example 150 kg CO2e). |
/purchases | Purchase carbon credits. You must request a price quote from /pricing first. |
/refunds | Refund 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=EURIt 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}/purchaseIdempotency
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
| v1 | v2 |
|---|---|
number_of_passengers | number_of_travelers |
number_of_travelers | number_of_travelers |
number_of_visitors | number_of_travelers |
Carbon activity types
| v1 | v2 |
|---|---|
ship_freight | sea_freight |
ship_freight_inland_waterway | inland_waterways |
train_freigth | rail_freight |
truck | road_freight |
parcel | logistics |
money_amount | Removed: request a pricing for a fixed total |
general | Removed: this was just a fixed amount of carbon, so request a pricing straight for a specific amount of carbon |
co2_amount | Removed, 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 methodology | Meaning |
|---|---|
US-EPA | We use the methodology published by the "United States Environmental Protection Agency". This was formerly called "specific" or similar. |
EU-EEA | We use the methodology published by the "European Environment Agency". This was formerly called "simple" or similar. |
SQUAKE | Methodology developed by our in-house research team, based on the best available data and latest research. This was formerly called "extend" or similar. |
BASIC | Simple 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.
| Method | How |
|---|---|
| API key auth | Send your API key in the header of each request. |
| Basic auth | Send your API key as the username and leave the password empty, base64 encoded. |
| mTLS | Contact 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
| Area | v1 | v2 | Notes |
|---|---|---|---|
| Expenditure | price_in_cents | total | |
| Hotel | *_stars options for hotel_type | Removed | We now infer this from stars if the hotel type is omitted. |
| Hotel | eco_label | eco_labels | The key is pluralized, since it accepted an array of values. |
| Response from calculations | algorithm_specific | energy_and_emission_factors | The 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_type | cargo_type | Allowed values are dry and reefer. |