# Scripting con la API de REST y JavaScript

Escribe un script mediante el SDK de Octokit.js para interactuar con la API de REST.

## Acerca de Octokit.js

Si desea escribir un script mediante JavaScript para interactuar con GitHubla API REST de , GitHub recomienda usar el SDK de Octokit.js. Octokit.js es mantenido por GitHub. El SDK implementa los procedimientos recomendados y facilita la interacción con la API de REST a través de JavaScript. Octokit.js funciona con todos los exploradores modernos, Node.js y Deno. Para más información, consulta el archivo [README de Octokit.js](https://github.com/octokit/octokit.js/#readme).

## Prerrequisitos

En esta guía se da por supuesto que está familiarizado con JavaScript y la GitHub API REST. Para obtener más información sobre la API REST, consulta [Introducción a la API REST](/es/enterprise-cloud@latest/rest/using-the-rest-api/getting-started-with-the-rest-api).

Debes instalar e importar `octokit` para usar la biblioteca de Octokit.js. En esta guía se usan instrucciones de importación de acuerdo con ES6. Para obtener más información sobre los diferentes métodos de instalación e importación, consulta [la sección Uso del archivo README de Octokit.js](https://github.com/octokit/octokit.js/#usage).

## Instanciación y autenticación

> \[!WARNING]
> Considera tus credenciales de autenticación una contraseña.
>
> Para mantener seguras sus credenciales, puede almacenarlas como secreto y ejecutar su script a través de GitHub Actions. Para más información, consulta [Uso de secretos en Acciones de GitHub](/es/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).

> También puede almacenar sus credenciales como un Codespaces secreto y ejecutar el script en Codespaces. Para más información, consulta [Administración de secretos específicos de la cuenta para GitHub Codespaces](/es/enterprise-cloud@latest/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces).

> Si estas opciones no son posibles, considere la posibilidad de usar otro servicio de la CLI para almacenar sus credenciales de forma segura.

### Autenticación con personal access token

Si desea usar la GitHub API REST para su uso personal, puede crear un personal access token. Para obtener más información sobre cómo crear un personal access token, vea [Administración de tokens de acceso personal](/es/enterprise-cloud@latest/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).

En primer lugar, importa `Octokit` desde `octokit`. A continuación, introduce tu personal access token al crear una instancia de `Octokit`. En el ejemplo siguiente, sustituya `YOUR-TOKEN` por una referencia a su personal access token.

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  auth: 'YOUR-TOKEN',
});
```

### Autenticación con GitHub App

Si desea usar la API en nombre de una organización u otro usuario, GitHub recomienda usar .GitHub App Si un punto de conexión está disponible para GitHub Apps, la documentación de referencia de REST para ese punto de conexión indicará qué tipo de GitHub App token es necesario. Para más información, consulta [Registro de una aplicación de GitHub](/es/enterprise-cloud@latest/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) y [Acerca de la autenticación con una aplicación de GitHub](/es/enterprise-cloud@latest/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app).

En lugar de importar `Octokit` desde `octokit`, importa `App`. En el ejemplo siguiente, reemplaza `APP_ID` por una referencia al identificador de la aplicación. Reemplaza `PRIVATE_KEY` por una referencia a la clave privada de la aplicación. Reemplaza `INSTALLATION_ID` por el identificador de la instalación de la aplicación en nombre de la cual quieras autenticarte. Puedes encontrar el identificador de la aplicación y generar una clave privada en la página de configuración de la aplicación. Para más información, consulta [Administración de claves privadas para aplicaciones de GitHub](/es/enterprise-cloud@latest/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps). Puedes obtener un identificador de instalación con `GET /users/{username}/installation`, `GET /repos/{owner}/{repo}/installation` o `GET /orgs/{org}/installation`. Para obtener más información, consulte [Puntos de conexión de la API de REST para GitHub Apps](/es/enterprise-cloud@latest/rest/apps/apps).

```javascript copy
import { App } from "octokit";

const app = new App({
  appId: APP_ID,
  privateKey: PRIVATE_KEY,
});

const octokit = await app.getInstallationOctokit(INSTALLATION_ID);
```

### Autenticación en GitHub Actions

Si desea usar la API en un GitHub Actions flujo de trabajo, GitHub recomienda autenticarse con la función integrada en `GITHUB_TOKEN` en vez de crear un token. Puedes conceder permisos a `GITHUB_TOKEN` con la clave `permissions`. Para obtener más información sobre `GITHUB_TOKEN`, consulta [GITHUB\_TOKEN](/es/enterprise-cloud@latest/actions/concepts/security/github_token).

Si el flujo de trabajo necesita acceder a los recursos fuera del repositorio del flujo de trabajo, no podrás usar `GITHUB_TOKEN`. En ese caso, almacena tus credenciales como secreto y reemplaza `GITHUB_TOKEN` en el ejemplo siguiente por el nombre del secreto. Para obtener más información sobre secretos, consulta [Uso de secretos en Acciones de GitHub](/es/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).

Si usa la palabra clave `run` para ejecutar su script de JavaScript en sus flujos de trabajo GitHub Actions, puede almacenar el valor de `GITHUB_TOKEN` como una variable de entorno. El script puede acceder a la variable de entorno como `process.env.VARIABLE_NAME`.

Por ejemplo, este paso de flujo de trabajo almacena `GITHUB_TOKEN` en una variable de entorno denominada `TOKEN`:

```yaml
- name: Run script
  env:
    TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    node .github/actions-scripts/use-the-api.mjs
```

El script que el flujo de trabajo ejecuta usa `process.env.TOKEN` para autenticarse:

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  auth: process.env.TOKEN,
});
```

### Instanciación sin autenticación

Puedes usar la API de REST sin autenticación, aunque tendrás un límite de velocidad inferior y no podrás usar algunos puntos de conexión. Para crear una instancia de `Octokit` sin autenticar, no pase el `auth` argumento .

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ );
```

## Realización de solicitudes

Octokit admite varias formas de realizar solicitudes. Puedes usar el método `request` para realizar solicitudes si conoces el verbo HTTP y la ruta de acceso del punto de conexión. Puedes usar el método `rest` si quieres aprovechar la función de autocompletar en el IDE y escribir. En el caso de los puntos de conexión paginados, puedes usar el método `paginate` para solicitar varias páginas de datos.

### Uso del método `request` para realizar solicitudes

Para usar el método `request` para realizar solicitudes, pasa el método HTTP y la ruta de acceso como primer argumento. Pasa cualquier parámetro de cuerpo, consulta o ruta en un objeto como segundo argumento. Por ejemplo, para realizar una solicitud `GET` a `/repos/{owner}/{repo}/issues` y pasar los parámetros `owner`, `repo` y `per_page`:

```javascript copy
await octokit.request("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 2
});
```

El método `request` pasa automáticamente el encabezado `Accept: application/vnd.github+json`. Para pasar encabezados adicionales o un encabezado `Accept` diferente, agrega una propiedad `headers` al objeto que se pasa como segundo argumento. El valor de la propiedad `headers` es un objeto con los nombres de encabezado como claves y valores de encabezado como valores. Por ejemplo, para enviar un encabezado `content-type` con un valor de `text/plain` y un encabezado `x-github-api-version` con un valor de `2026-03-10`:

```javascript copy
await octokit.request("POST /markdown/raw", {
  text: "Hello **world**",
  headers: {
    "content-type": "text/plain",
    "x-github-api-version": "2026-03-10",
  },
});
```

### Uso de métodos de punto de conexión `rest` para realizar solicitudes

Cada punto de conexión de la API de REST tiene un método de punto de conexión asociado `rest` en Octokit. Por lo general, estos métodos se autocompletan en el IDE para mayor comodidad. Puedes pasar cualquier parámetro como un objeto al método.

```javascript copy
await octokit.rest.issues.listForRepo({
  owner: "github",
  repo: "docs",
  per_page: 2
});
```

Además, si usas un lenguaje con tipo como TypeScript, puedes importar tipos para usarlos con estos métodos. Para obtener más información, consulta [la sección TypeScript en el archivo README de plugin-rest-endpoint-methods.js](https://github.com/octokit/plugin-rest-endpoint-methods.js/#typescript).

### Realización de solicitudes paginadas

Si el punto de conexión está paginado y quieres capturar más de una página de resultados, puedes usar el método `paginate`.
`paginate` capturará la siguiente página de resultados hasta llegar a la última página y, a continuación, devolverá todos los resultados como una sola matriz. Algunos puntos de conexión devuelven resultados paginados como matriz en un objeto, en lugar de devolverlos como una matriz.
`paginate` siempre devuelve una matriz de elementos, aun cuando el resultado sin procesar sea un objeto.

Por ejemplo, el siguiente ejemplo obtiene todas las incidencias del repositorio `github/docs`. Aunque se solicitan 100 problemas a la vez, la función no devolverá resultados hasta que se alcance la última página de datos.

```javascript copy
const issueData = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});
```

El método `paginate` acepta una función de mapeo opcional, que puedes utilizar para extraer solo los datos que desees de la respuesta. Esto reduce la cantidad de memoria que usa el script. La función de mapa puede tomar un segundo argumento, `done`, que se puede invocar para terminar la paginación antes de alcanzar la última página. Esto te permite capturar un subconjunto de páginas. Por ejemplo, el siguiente ejemplo sigue obteniendo resultados hasta que se devuelve un problema que incluye "test" en el título. Para las páginas de datos que se han devuelto, solo se almacenan el título de la incidencia y el autor.

```javascript copy
const issueData = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
},
    (response, done) => response.data.map((issue) => {
    if (issue.title.includes("test")) {
      done()
    }
    return ({title: issue.title, author: issue.user.login})
  })
);
```

En lugar de capturar todos los resultados a la vez, puedes usar `octokit.paginate.iterator()` para recorrer en iteración una sola página a la vez. Por ejemplo, en el ejemplo siguiente se captura una página de resultados a la vez y se procesa cada objeto de la página antes de capturar la página siguiente. Una vez que se alcanza un problema que incluye "prueba" en el título, el script detiene la iteración y devuelve el título del problema y el autor del problema de cada objeto que se procesó. El iterador es el método más eficiente en memoria para obtener datos paginados.

```javascript copy
const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

let issueData = []
let breakLoop = false
for await (const {data} of iterator) {
  if (breakLoop) break
  for (const issue of data) {
    if (issue.title.includes("test")) {
      breakLoop = true
      break
    } else {
      issueData = [...issueData, {title: issue.title, author: issue.user.login}];
    }
  }
}
```

También puedes usar el método `paginate` con los métodos de punto de conexión `rest`. Pase el método de punto de conexión `rest` como primer argumento. Pasa cualquier parámetro como segundo argumento.

```javascript copy
const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});
```

Para obtener más información sobre la paginación, consulta [Uso de la paginación en la API de REST](/es/enterprise-cloud@latest/rest/using-the-rest-api/using-pagination-in-the-rest-api).

## Almacenamiento en caché de los errores

### Detección de todos los errores

A veces, la GitHub API REST devolverá un error. Por ejemplo, recibirás un error si el token de acceso ha expirado o si has omitido un parámetro necesario. Octokit.js reintenta automáticamente la solicitud cuando obtiene un error distinto de `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`y `422 Unprocessable Entity`. Si se produce un error de API incluso después de varios reintentos, Octokit.js genera un error que incluye el código de estado HTTP de la respuesta (`response.status`) y los encabezados de respuesta (`response.headers`). Debes controlar estos errores en el código. Por ejemplo, puedes usar un bloque try/catch para detectar errores:

```javascript copy
let filesChanged = []

try {
  const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", {
    owner: "github",
    repo: "docs",
    pull_number: 22809,
    per_page: 100,
    headers: {
      "x-github-api-version": "2026-03-10",
    },
  });

  for await (const {data} of iterator) {
    filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)];
  }
} catch (error) {
  if (error.response) {
    console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
  }
  console.error(error)
}
```

### Control de los códigos de error previstos

A veces, GitHub usa un código de estado 4xx para indicar una respuesta que no es de error. Si el punto de conexión que usa lo hace, puedes agregar control adicional para errores específicos. Por ejemplo, el punto de conexión `GET /user/starred/{owner}/{repo}` devolverá un valor `404` si el repositorio no está marcado con estrella. En el ejemplo siguiente se usa la respuesta `404` para indicar que el repositorio no se ha destacado; todos los demás códigos de error se tratan como errores.

```javascript copy
try {
  await octokit.request("GET /user/starred/{owner}/{repo}", {
    owner: "github",
    repo: "docs",
    headers: {
      "x-github-api-version": "2026-03-10",
    },
  });

  console.log(`The repository is starred by me`);

} catch (error) {
  if (error.status === 404) {
    console.log(`The repository is not starred by me`);
  } else {
    console.error(`An error occurred while checking if the repository is starred: ${error?.response?.data?.message}`);
  }
}
```

### Gestión de errores de límite de tasa

Si recibes un error de límite de frecuencia, es posible que quieras volver a realizar la solicitud después de esperar. Cuando se aplica un límite de velocidad, GitHub responde con un error `403 Forbidden` y el valor del encabezado de respuesta `x-ratelimit-remaining` será `"0"`. Los encabezados de respuesta incluirán un encabezado `x-ratelimit-reset`, que indica la hora a la que se restablece la ventana de límite de velocidad actual, en segundos de época UTC. Puedes volver a intentar realizar tu solicitud después del tiempo especificado por `x-ratelimit-reset`.

```javascript copy
async function requestRetry(route, parameters) {
  try {
    const response = await octokit.request(route, parameters);
    return response
  } catch (error) {
    if (error.response && error.status === 403 && error.response.headers['x-ratelimit-remaining'] === '0') {
      const resetTimeEpochSeconds = error.response.headers['x-ratelimit-reset'];
      const currentTimeEpochSeconds = Math.floor(Date.now() / 1000);
      const secondsToWait = resetTimeEpochSeconds - currentTimeEpochSeconds;
      console.log(`You have exceeded your rate limit. Retrying in ${secondsToWait} seconds.`);
      setTimeout(requestRetry, secondsToWait * 1000, route, parameters);
    } else {
      console.error(error);
    }
  }
}

const response = await requestRetry("GET /repos/{owner}/{repo}/issues", {
    owner: "github",
    repo: "docs",
    per_page: 2
  })
```

## Análisis de la respuesta

El método `request` devuelve una promesa que se resuelve en un objeto si la solicitud se ha realizado correctamente. Las propiedades del objeto son `data` (el cuerpo de la respuesta devuelto por el punto de conexión), `status` (el código de respuesta HTTP), `url` (la dirección URL de la solicitud) y `headers` (un objeto que contiene los encabezados de respuesta). A menos que se especifique lo contrario, el cuerpo de la respuesta está en formato JSON. Algunos puntos de conexión no devuelven un cuerpo de respuesta; en esos casos, se omite la propiedad `data`.

```javascript copy
const response = await octokit.request("GET /repos/{owner}/{repo}/issues/{issue_number}", {
  owner: "github",
  repo: "docs",
  issue_number: 11901,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

console.log(`The status of the response is: ${response.status}`)
console.log(`The request URL was: ${response.url}`)
console.log(`The x-ratelimit-remaining response header is: ${response.headers["x-ratelimit-remaining"]}`)
console.log(`The issue title is: ${response.data.title}`)
```

Del mismo modo, el método `paginate` devuelve una promesa. Si la solicitud se ha realizado correctamente, la promesa se resuelve en una matriz de datos devueltos por el punto de conexión. A diferencia del método `request`, el método `paginate` no devuelve el código de estado, la dirección URL ni los encabezados.

```javascript copy
const data = await octokit.paginate("GET /repos/{owner}/{repo}/issues", {
  owner: "github",
  repo: "docs",
  per_page: 100,
  headers: {
    "x-github-api-version": "2026-03-10",
  },
});

console.log(`${data.length} issues were returned`)
console.log(`The title of the first issue is: ${data[0].title}`)
```

## Script de ejemplo

Este es un script de ejemplo completo que usa Octokit.js. El script importa `Octokit` y crea una nueva instancia de `Octokit`. Si quisiera autenticarse con GitHub App en lugar de personal access token, importaría e instanciaría `App` en lugar de `Octokit`. Para obtener más información, consulte [Autenticarse con un GitHub App](#authenticating-with-a-github-app).

La función `getChangedFiles` obtiene todos los archivos modificados para una solicitud de incorporación de cambios. La función `commentIfDataFilesChanged` llama a la función `getChangedFiles`. Si alguno de los archivos que cambió la solicitud de incorporación de cambios incluye `/data/` en la ruta de acceso del archivo, la función comentará la solicitud de incorporación de cambios.

```javascript copy
import { Octokit } from "octokit";

const octokit = new Octokit({ 
  auth: 'YOUR-TOKEN',
});

async function getChangedFiles({owner, repo, pullNumber}) {
  let filesChanged = []

  try {
    const iterator = octokit.paginate.iterator("GET /repos/{owner}/{repo}/pulls/{pull_number}/files", {
      owner: owner,
      repo: repo,
      pull_number: pullNumber,
      per_page: 100,
      headers: {
        "x-github-api-version": "2026-03-10",
      },
    });

    for await (const {data} of iterator) {
      filesChanged = [...filesChanged, ...data.map(fileData => fileData.filename)];
    }
  } catch (error) {
    if (error.response) {
      console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
    }
    console.error(error)
  }

  return filesChanged
}

async function commentIfDataFilesChanged({owner, repo, pullNumber}) {
  const changedFiles = await getChangedFiles({owner, repo, pullNumber});

  const filePathRegex = new RegExp(/\/data\//, "i");
  if (!changedFiles.some(fileName => filePathRegex.test(fileName))) {
    return;
  }

  try {
    const {data: comment} = await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", {
      owner: owner,
      repo: repo,
      issue_number: pullNumber,
      body: `It looks like you changed a data file. These files are auto-generated. \n\nYou must revert any changes to data files before your pull request will be reviewed.`,
      headers: {
        "x-github-api-version": "2026-03-10",
      },
    });

    return comment.html_url;
  } catch (error) {
    if (error.response) {
      console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
    }
    console.error(error)
  }
}

await commentIfDataFilesChanged({owner: "github", repo: "docs", pullNumber: 191});
```

## Pasos siguientes

* Para más información sobre Octokit.js, consulta [la documentación de Octokit.js](https://github.com/octokit/octokit.js/#readme).
* Para ver algunos ejemplos de la vida real, consulte cómo GitHub Docs usa Octokit.js [mediante la búsqueda en el GitHub repositorio de Docs](https://github.com/search?q=repo%3Agithub%2Fdocs%20path%3A.github%20octokit\&type=code).