Version 40.0.0
of the Node.js SDK represents a full rewrite of the SDK with a number of breaking changes, outlined in the following sections. When upgrading to this version or later versions, take note of the changes in the SDK, including client construction and parameter names. If necessary, you can use the legacy version of the SDK along with the latest version.
SDK versions 39.1.0
and earlier continue to function as expected, but you should plan to update your integration as soon as possible to ensure continued support.
The new Client
class has some breaking changes and is constructed in a slightly different way than the legacy version of the SDK.
Legacy | New | Additional information | |
---|---|---|---|
Client | SquareClient | The main client class for interacting with Square APIs. | |
Environment | SquareEnvironment | An enum for specifying the environment (Sandbox or Production). | |
bearerAuthCredentials.accessToken | token | The access token used for authentication. | |
customUrl | baseUrl | The base URL for API requests. | |
squareVersion | version | The Square API version to use. | |
N/A | fetcher | Provide your own fetch function for making HTTP requests. | |
timeout | Removed | Timeout can be set at individual methods. | |
additionalHeaders | Removed | Additional headers can be set at individual methods. | |
httpClientOptions | Removed | HTTP options can be set at individual methods. | |
unstable_httpClientOptions | Removed | This option has been removed. | |
userAgentDetail | Removed | This option has been removed. |
// LEGACY
import { Client, Environment } from "square/legacy";
const client = new Client({
bearerAuthCredentials: {
accessToken: process.env.SQUARE_ACCESS_TOKEN,
},
environment: Environment.Sandbox,
});
// NEW
import { SquareClient, SquareEnvironment } from "square";
const client = new SquareClient({
token: process.env.SQUARE_ACCESS_TOKEN,
environment: SquareEnvironment.Sandbox,
});
While the new SDK has many improvements, we understand that it takes time to upgrade when there are breaking changes. To make the migration easier, the new SDK exports the legacy SDK as square/legacy
. The following example shows how to use the new and legacy SDKs inside a single file:
import { randomUUID } from "crypto";
import { Square, SquareClient } from "square";
import { Client } from "square/legacy";
const client = new SquareClient({
token: process.env.SQUARE_ACCESS_TOKEN,
});
const legacyClient = new Client({
bearerAuthCredentials: {
accessToken: process.env.SQUARE_ACCESS_TOKEN!,
},
});
async function getLocation(): Promise<Square.Location> {
return (
await client.locations.get({
locationId: "YOUR_LOCATION_ID",
})
).location!;
}
async function createOrder() {
const location = await getLocation();
await legacyClient.ordersApi.createOrder({
idempotencyKey: randomUUID(),
order: {
locationId: location.id!,
lineItems: [
{
name: "New Item",
quantity: "1",
basePriceMoney: {
amount: BigInt(100),
currency: "USD",
},
},
],
},
});
}
createOrder();
Square recommends migrating to the new SDK using the following steps:
Upgrade the NPM module to
^40.0.0
.Search and replace all requires and imports from
"square"
to"square/legacy"
.- For required, replace
require("square")
withrequire("square/legacy")
. - For imports, replace
from "square"
withfrom "square/legacy"
. - For dynamic imports, replace
import("square")
withimport("square/legacy")
.
- For required, replace
Gradually introduce methods from the new SDK by importing them from
"square"
.
Note
If you're using TypeScript, make sure that the moduleResolution
setting in your tsconfig.json
is equal to node16
, nodenext
, or bundler
to consume the legacy SDK.
The previous version of the SDK relied on many positional parameters, which made it difficult for readers to understand the meaning of the parameter. For example:
// LEGACY
await client.customersApi.listCustomers(undefined, 10, undefined, "DESC");
It's not immediately clear what undefined
, 10
, undefined
, and DESC
mean. In the new version of the SDK, you specify the parameters by their name and you're not required to pass undefined
parameters. The same ListCustomers
request looks like the following:
// NEW
await client.customers.list({
limit: 10,
sortOrder: "DESC",
});
Previously, API classes were named after the resource you're interacting with and suffixed with Api
. To interact with customer resources, you used the client.customersApi
class.
The method was named based on the action you want to perform and the same resource name specified earlier. To list customers, you call client.customersApi.listCustomers
.
// LEGACY
await client.customersApi.listCustomers();
The new API classes are named by the resource without the Api
suffix, and the methods now name the action without mentioning the resource a second time.
// NEW
await client.customers.list();
When interacting with a nested resource, you can chain the resources using dot-notation.
// NEW
await client.customers.groups.list();
To find all classes and method names that might have changed, see reference.md.
Paginated endpoints now support auto-pagination with an async iterator. Callers don’t need to manually fetch the next page at all. You can now iterate over the entire list and the client automatically fetches the next page behind the scenes.
The following example shows the same code, with the legacy and new SDK:
// LEGACY
const limit = 10;
let listCustomersResponse = await customersApi.listCustomers(
undefined,
limit,
"DEFAULT",
"DESC"
);
while (!isEmpty(listCustomersResponse.result)) {
let customers = listCustomersResponse.result.customers;
customers.forEach(function (cust) {
console.log(
"customer: ID: " + cust.id,
"Version: " + cust.version + ",",
"Given name: " + cust.givenName + ",",
"Family name:" + cust.familyName
);
});
let cursor = listCustomersResponse.result.cursor;
if (cursor) {
listCustomersResponse = await customersApi.listCustomers(
cursor,
limit,
"DEFAULT",
"DESC"
);
} else {
break;
}
}
// NEW
let customerPager = await client.customers.list({
limit: 10,
sortField: "DEFAULT",
sortOrder: "DESC",
});
for await (const customer of customerPager) {
console.log(
"customer: ID: " + customer.id,
"Version: " + customer.version + ",",
"Given name: " + customer.givenName + ",",
"Family name: " + customer.familyName
);
}
If you need to paginate page by page, you can still do so with a lot less code:
- Use
customerPager.data
to get the customers of the current page. - Use
customerPage.hasNextPage()
to check whether there's another page after the current one. - Use
customerPage.getNextPage()
to retrieve the next page of customers.
let customerPager = await client.customers.list({
limit: 10,
sortField: "DEFAULT",
sortOrder: "DESC",
});
const printCustomers = (customers: Square.Customer[]) => {
for (const customer of customers) {
console.log(
"customer: ID: " + customer.id,
"Version: " + customer.version + ",",
"Given name: " + customer.givenName + ",",
"Family name: " + customer.familyName
);
}
};
printCustomers(customerPager.data);
while (customerPager.hasNextPage()) {
customerPager = await customerPager.getNextPage();
printCustomers(customerPager.data);
}
For more sample code and examples of using the new Node.js SDK, see Common Square API Patterns.