---
cuppy_hub: sap
cuppy_path: guides/connectivity/first-call-from-typescript.md
cuppy_section: docs
cuppy_doc: 0K86-ZZJQ
cuppy_doc_uuid: 153cc58e-b3ba-45c3-8198-8c2c00d8dc25
cuppy_permalink: https://cuppy.io/sap/d/0K86-ZZJQ
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/sap/docs/guides/connectivity/first-call-from-typescript
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 408b54539e5faefcf8b87bb553c3de9ff581c29020ce4d74490c97e28c259a5f
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Your first SAP call from TypeScript

## 1. Get a sandbox key

1. Sign in to the **SAP Business Accelerator Hub** (api.sap.com).
2. Open the API you need, for example *Business Partner (A2X)* for S/4HANA Cloud.
3. Copy two things: the **sandbox URL** from its *Try Out* section, and your **API key** with the header name the hub shows.
4. Put them in your environment. Never put the key in code or commits:

```bash
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

```ts
// 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:

```bash
export destinations='[{"name":"S4","url":"https://<your S/4HANA API host>","username":"<communication user>","password":"<from your secret store>"}]'
```

- The hub's reading: the `destinations` entry 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`.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 10 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/sap/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
