> ## Documentation Index
> Fetch the complete documentation index at: https://docs.creditbenchmark.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ejemplos de scripts

> Scripts ejecutables en TypeScript y Python que firman una aserción de cliente, la canjean por un token de acceso y llaman a un punto final de metadatos.

Estos scripts coinciden con los ejemplos de su paquete de incorporación. Cada uno de ellos ejecuta el flujo completo de principio a fin:

1. Firme una aserción de cliente JWT con su clave **privada** ES256.
2. Cámbiela por un token de acceso de corta duración.
3. Realice una llamada a un punto final de metadatos con el token de acceso.

Ambos esperan que introduzca su clave privada (`private_key.pem`) junto al script. Sustituya `<OAuthClientId>` y `<KID>` con los valores de su paquete de incorporación. Consulte [Solicite un token de acceso](/api-reference/authentication/request-token) para conocer la función de cada paso.

**TypeScript**

Requiere Node.js 18 o posterior para el global `fetch`.

```bash theme={null}
npm install jsonwebtoken
npm install --save-dev typescript tsx @types/jsonwebtoken @types/node
npx tsx sample_request.ts
```

```typescript sample_request.ts theme={null}
import { randomUUID } from 'node:crypto';
import { readFileSync } from 'node:fs';
import jwt from 'jsonwebtoken';

// ---------------------------------------------------------------------------
// Configuration — fill these in for your environment.
// ---------------------------------------------------------------------------

const OAUTH_CLIENT_ID = '<OAuthClientId>'; // Your OAuth Client Id (from your onboarding pack)
const KID = '<KID>'; // The Kid whose PRIVATE key you're using to sign below
const PRIVATE_KEY_PATH = './private_key.pem'; // Path to the PRIVATE key matching that Kid's public key

const GATEWAY_BASE_URL = 'https://gateway.creditbenchmark.com';
const TOKEN_URL = 'https://gateway.creditbenchmark.com/api/security/token';
const AUDIENCE = 'cb-gateway-m2m-blue';

// Any of the metadata endpoints below — change as needed.
const METADATA_ENDPOINT = '/beta/metadata/columns';

/** Builds and signs the RFC 7523 JWT bearer client assertion. */
function buildClientAssertion(): string {
  const privateKeyPem = readFileSync(PRIVATE_KEY_PATH, 'utf8');
  const now = Math.floor(Date.now() / 1000);

  return jwt.sign(
    {
      iss: OAUTH_CLIENT_ID,
      sub: OAUTH_CLIENT_ID,
      aud: AUDIENCE,
      jti: randomUUID(),
      iat: now,
      exp: now + 120,
    },
    privateKeyPem,
    { algorithm: 'ES256', keyid: KID }
  );
}

/** Exchanges the signed client assertion for a short-lived access token. */
async function getAccessToken(): Promise<string> {
  const clientAssertion = buildClientAssertion();

  const body = new URLSearchParams({
    grant_type: 'client_credentials',
    client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
    client_assertion: clientAssertion,
    OAuthClientId: OAUTH_CLIENT_ID,
  });

  const response = await fetch(TOKEN_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body,
  });

  if (!response.ok) {
    throw new Error(`Token request failed: ${response.status} ${await response.text()}`);
  }

  const data = (await response.json()) as { accessToken: string };
  return data.accessToken;
}

/** Calls a metadata API using the access token. Swap 'endpoint' for any of
 * the other metadata endpoints. */
async function callMetadataEndpoint(accessToken: string, endpoint: string = METADATA_ENDPOINT): Promise<unknown> {
  const response = await fetch(`${GATEWAY_BASE_URL}${endpoint}`, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
  });

  if (!response.ok) {
    throw new Error(`Metadata request failed: ${response.status} ${await response.text()}`);
  }

  return response.json();
}

(async () => {
  const token = await getAccessToken();
  console.log('Access token acquired.');

  const data = await callMetadataEndpoint(token);
  console.log(`Response from ${METADATA_ENDPOINT}:`);
  console.log(data);
})().catch((err) => {
  console.error(err);
  process.exitCode = 1;
});
```

**Python**

Requiere Python 3.8 o posterior.

```bash theme={null}
pip install "requests>=2.31.0" "PyJWT>=2.8.0" "cryptography>=41.0.0"
python sample_request.py
```

```python sample_request.py theme={null}
import time
import uuid

import jwt  # PyJWT
import requests

# ---------------------------------------------------------------------------
# Configuration — fill these in for your environment.
# ---------------------------------------------------------------------------

OAUTH_CLIENT_ID = "<OAuthClientId>"  # Your OAuth Client Id (from your onboarding pack)
KID = "<KID>"  # The Kid whose PRIVATE key you're using to sign below
PRIVATE_KEY_PATH = "private_key.pem"  # Path to the PRIVATE key matching that Kid's public key

GATEWAY_BASE_URL = "https://gateway.creditbenchmark.com"
TOKEN_URL = "https://gateway.creditbenchmark.com/api/security/token"
AUDIENCE = "cb-gateway-m2m-blue"

# Any of the metadata endpoints below — change as needed.
METADATA_ENDPOINT = "/beta/metadata/columns"


def build_client_assertion() -> str:
    """Builds and signs the RFC 7523 JWT bearer client assertion."""
    with open(PRIVATE_KEY_PATH, "r", encoding="utf-8") as f:
        private_key_pem = f.read()

    now = int(time.time())
    payload = {
        "iss": OAUTH_CLIENT_ID,
        "sub": OAUTH_CLIENT_ID,
        "aud": AUDIENCE,
        "jti": str(uuid.uuid4()),
        "iat": now,
        "exp": now + 120,
    }
    headers = {"kid": KID}

    return jwt.encode(payload, private_key_pem, algorithm="ES256", headers=headers)


def get_access_token() -> str:
    """Exchanges the signed client assertion for a short-lived access token."""
    client_assertion = build_client_assertion()

    response = requests.post(
        TOKEN_URL,
        data={
            "grant_type": "client_credentials",
            "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
            "client_assertion": client_assertion,
            "OAuthClientId": OAUTH_CLIENT_ID,
        },
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        timeout=30,
    )
    response.raise_for_status()
    return response.json()["accessToken"]


def call_metadata_endpoint(access_token: str, endpoint: str = METADATA_ENDPOINT) -> dict:
    """Calls a metadata API using the access token. Swap 'endpoint' for any
    of the other metadata endpoints."""
    response = requests.get(
        f"{GATEWAY_BASE_URL}{endpoint}",
        headers={
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json",
            "Accept": "application/json",
        },
        timeout=30,
    )
    response.raise_for_status()
    return response.json()


if __name__ == "__main__":
    token = get_access_token()
    print("Access token acquired.")

    data = call_metadata_endpoint(token)
    print(f"Response from {METADATA_ENDPOINT}:")
    print(data)
```

## Puntos finales de metadatos

Establezca `METADATA_ENDPOINT` cualquiera de estas opciones. Todas son `GET` solicitudes.

| Punto de conexión | Devuelve |
| - | - |
| `/beta/metadata/columns` | Columnas de entrada disponibles con tipo, «scopeable», «facetable» y «entitlement» |
| `/beta/metadata/available-dates` | Fecha de entrada en vigor más reciente y fecha de entrada en vigor finalizada más reciente |
| `/beta/metadata/geography-schema` | Jerarquía de grupos de regiones, regiones y países |
| `/beta/metadata/rating-scales` | Escalas de calificación compatibles y sus correspondencias de grados |

> [!WARNING]
>
> Nunca comparta su clave privada con nadie, ni siquiera con Credit Benchmark. Genere una nueva aserción de cliente para cada solicitud de token y, si en algún momento se ve comprometida una clave privada, siga el procedimiento que se indica en [Rotación de claves](/api-reference/authentication/key-pair-setup#key-rotation).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.