Your first SAP call from TypeScript — read business partners from the Business Accelerator Hub sandbox with an API key, then the same code against a real system through a BTP destination, including a write with automatic CSRF handling
Step by step with the SAP Cloud SDK for JavaScript (@sap-cloud-sdk/http-client 4.x). Get a sandbox API key and base URL from api.sap.com, then read A_BusinessPartner with OData query options. Switch to a named BTP destination, which can be Internet with OAuth or basic auth, or OnPremise through the Cloud Connector, with the same request code. Then a POST where the SDK fetches the CSRF token. Compiles with tsc --strict.
markdownguidev10K86-ZZJQstage: calltrust: officialservice: connectivityinterface: typescriptinterface: odataSAP first API callTypeScript SAPNode.js SAPSAP Cloud SDK executeHttpRequest@sap-cloud-sdk/http-clientBusiness Accelerator Hub sandboxAPIKey headerA_BusinessPartnerAPI_BUSINESS_PARTNERdestinationNamedestinations environment variable localjwtPOST with CSRFd.results
Your first SAP call from TypeScript
1. Get a sandbox key
- Sign in to the SAP Business Accelerator Hub (api.sap.com).
- Open the API you need, for example Business Partner (A2X) for S/4HANA Cloud.
- Copy two things: the sandbox URL from its Try Out section, and your API key with the header name the hub shows.
- Put them in your environment. Never put the key in code or commits:
npm install @sap-cloud-sdk/http-client@4
export SAP_BASE_URL="<sandbox URL of the service, ending in /API_BUSINESS_PARTNER>"
export SAP_API_KEY="<your key>"
2. Read, then write, with the SAP Cloud SDK
// sap-first-call.ts
import { executeHttpRequest } from "@sap-cloud-sdk/http-client";
type Partner = { BusinessPartner: string; BusinessPartnerFullName: string };
function sandboxDestination() {
const { SAP_BASE_URL: url, SAP_API_KEY: apiKey } = process.env;
if (!url || !apiKey) throw new Error("Set SAP_BASE_URL and SAP_API_KEY");
return { url, headers: { APIKey: apiKey } };
}
// Read: OData V2 query options; results are under d.results.
export async function listPartners(): Promise<Partner[]> {
const res = await executeHttpRequest(sandboxDestination(), {
method: "get",
url: "/A_BusinessPartner",
params: { $top: 5, $select: "BusinessPartner,BusinessPartnerFullName", $format: "json" },
});
return (res.data as { d: { results: Partner[] } }).d.results;
}
// Same request through a BTP destination: Internet + OAuth/basic, or OnPremise via the Cloud Connector.
// The SDK reads the `destinations` env var first, then the Destination service using the caller's JWT.
export async function listPartnersVia(destinationName: string, jwt?: string): Promise<Partner[]> {
const res = await executeHttpRequest({ destinationName, jwt }, {
method: "get",
url: "/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner",
params: { $top: 5, $format: "json" },
});
return (res.data as { d: { results: Partner[] } }).d.results;
}
// Write: the SDK fetches the X-CSRF-Token (HEAD with "fetch") and reuses its cookies automatically.
export async function createPartner(destinationName: string, fullName: string, jwt?: string): Promise<string> {
const res = await executeHttpRequest(
{ destinationName, jwt },
{
method: "post",
url: "/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner",
data: { BusinessPartnerCategory: "2", OrganizationBPName1: fullName },
headers: { "Content-Type": "application/json", Accept: "application/json" },
},
{ fetchCsrfToken: true },
);
return (res.data as { d: Partner }).d.BusinessPartner;
}
listPartners().then((p) => console.table(p)).catch((e: unknown) => {
console.error(e instanceof Error ? e.message : e);
process.exit(1);
});
Run it with npx tsx sap-first-call.ts.
- The sandbox is shared and read-oriented, so expect writes there to be refused or reset. Test writes against your own system through a destination.
- The create body is the hub's reading of the Business Partner API's minimum fields for an organisation. Check the API's specification on the hub before relying on it.
3. Run it locally against a destination
Without BTP, define the destination in the destinations environment variable. The SAP Cloud SDK reads it before asking the Destination service:
export destinations='[{"name":"S4","url":"https://<your S/4HANA API host>","username":"<communication user>","password":"<from your secret store>"}]'
- The hub's reading: the
destinationsentry shape is the SDK's local convention. Use basic credentials only for development, from a secret store. - In BTP, bind the Destination service (and the connectivity service for
OnPremise) instead, and pass the user's JWT.
Errors and their fixes: reference/connectivity/odata-calls-csrf-and-errors.md and reference/connectivity/btp-destinations-and-cloud-connector.md.