# Création d’appels avec GraphQL

Découvrez comment s’authentifier auprès de l’API GraphQL, puis comment créer et exécuter des requêtes et des mutations.

## Authentification avec GraphQL

Vous pouvez vous authentifier auprès de l’API GraphQL à l’aide d’un personal access token, GitHub Appou OAuth app.

### Authentification avec un personal access token

Pour vous authentifier auprès d’un personal access token, suivez les étapes décrites dans [Gestion de vos jetons d’accès personnels](/fr/enterprise-server@3.22/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). Les étendues ou les autorisations dont vous aurez besoin dépendent des données que vous demandez.

Par exemple, sélectionnez l’autorisation « issues:read » pour lire toutes les issues dans les référentiels auxquels votre jeton a accès.

Tous les fine-grained personal access token incluent l’accès en lecture aux référentiels publics. Pour accéder aux référentiels publics avec un personal access token (classic), sélectionnez l’étendue « public\_repo ».

Si votre jeton n’a pas les étendues ou autorisations requises pour access une ressource, l’API retourne un message d’erreur qui indique les étendues ou les autorisations dont votre jeton a besoin.

### Authentification avec un GitHub App

Si vous souhaitez utiliser l’API pour le compte d’une organisation ou d’un autre utilisateur, GitHub vous recommande d’utiliser un GitHub App. Pour attribuer l’activité à votre application, vous pouvez faire en sorte que votre application s’authentifie en tant qu’installation d’application. Pour attribuer l’activité de l’application à un utilisateur, vous pouvez faire en sorte que votre application s’authentifie au nom d’un utilisateur. Dans les deux cas, vous allez générer un jeton que vous pouvez utiliser pour vous authentifier auprès de l’API GraphQL. Pour plus d’informations, consultez [Inscription d’une application GitHub](/fr/enterprise-server@3.22/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) et [À propos de l’authentification avec une application GitHub](/fr/enterprise-server@3.22/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app).

### Authentification avec un OAuth app

Pour vous authentifier à l’aide d’un jeton OAuth provenant d’un OAuth app, vous devez d’abord autoriser votre OAuth app en utilisant soit un flux d’application web, soit un flux d’appareil. Ensuite, vous pouvez utiliser le jeton d'accès que vous avez reçu pour accéder à l’API. Pour plus d’informations, consultez [Création d’une application OAuth](/fr/enterprise-server@3.22/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) et [Autorisation des applications OAuth](/fr/enterprise-server@3.22/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps).

## Point de terminaison GraphQL

L'API REST comporte de nombreux points d'extrémité. Avec l'API GraphQL, le point de terminaison reste constant, quelle que soit l'opération effectuée. Pour GitHub Enterprise Server, ce point de terminaison est :

<pre>http(s)://HOSTNAME/api/graphql</pre>

## Communication avec GraphQL

Étant donné que les opérations GraphQL se composent de JSON multiligne, GitHub recommande d’utiliser les clients [GraphQL](/fr/enterprise-server@3.22/graphql/guides/using-graphql-clients) pour effectuer des appels GraphQL. Vous pouvez également utiliser `curl` ou n’importe quelle autre bibliothèque HTTP.

Dans REST, les [verbes HTTP](/fr/enterprise-server@3.22/rest#http-verbs) déterminent l’opération effectuée. Dans GraphQL vous fournirez un corps encodé JSON, que vous effectuiez une requête ou une mutation ; le verbe HTTP est donc `POST`. L’exception est une [requête d’introspection](/fr/enterprise-server@3.22/graphql/guides/introduction-to-graphql#discovering-the-graphql-api), qui est un simple `GET` au point de terminaison. Pour plus d’informations sur GraphQL et REST, consultez [Migration de REST vers GraphQL](/fr/enterprise-server@3.22/graphql/guides/migrating-from-rest-to-graphql).

Pour interroger GraphQL dans une commande `curl`, effectuez une requête `POST` avec une charge utile JSON. La charge utile doit contenir une chaîne nommée `query` :

```shell
curl -H "Authorization: bearer TOKEN" -X POST -d " \
 { \
   \"query\": \"query { viewer { login }}\" \
 } \
" http(s)://HOSTNAME/api/graphql
```

> \[!NOTE]
> La valeur de chaîne de `"query"` doit échapper les caractères de nouvelle ligne, sinon le schéma ne l’analysera pas correctement. Pour le corps `POST`, utilisez des guillemets doubles externes et des guillemets doubles internes échappés.

### À propos des opérations de requête et de mutation

Les deux types d'opérations autorisées dans l'API GraphQL de GitHub sont *queries* et *mutations*. Si l’on compare GraphQL à REST, les requêtes opèrent comme des requêtes `GET`, tandis que les mutations opèrent comme `POST`/`PATCH`/`DELETE`. Le nom de mutation détermine quelle modification est exécutée.

Pour obtenir des informations sur la limitation du débit, consultez [Limites de débit et limites de requête pour l’API GraphQL](/fr/enterprise-server@3.22/graphql/overview/rate-limits-and-query-limits-for-the-graphql-api).

Les requêtes et les mutations partagent des formes similaires, avec certaines différences importantes.

### À propos des requêtes

Les requêtes GraphQL retournent seulement les données que vous spécifiez. Pour former une requête, vous devez spécifier [des champs au sein des champs](/fr/enterprise-server@3.22/graphql/guides/introduction-to-graphql#field) (également appelés *sous-champs imbriqués*) jusqu’à ce que vous renvoyiez uniquement des scalaires.

Les requêtes sont structurées comme ceci :

<pre>query {
  JSON-OBJECT-TO-RETURN
}</pre>

Pour obtenir un exemple réel, consultez [Exemple de requête](#example-query).

### À propos des mutations

Pour former une mutation, vous devez spécifier trois éléments :

1. *Nom de la mutation*. Type de modification que vous souhaitez effectuer.
2. *Objet d’entrée*. Données que vous souhaitez envoyer au serveur, composées de *champs d’entrée*. Passez-les comme argument au nom de la mutation.
3. *Objet de charge utile*. Données que vous souhaitez retourner à partir du serveur, composées de *champs de retour*. Passez-les comme corps du nom de la mutation.

Les mutations sont structurées comme suit :

<pre>mutation {
  MUTATION-NAME(input: {MUTATION-NAME-INPUT!}) {
    MUTATION-NAME-PAYLOAD
  }
}</pre>

L’objet d’entrée dans cet exemple est `MutationNameInput`, et l’objet de charge utile est `MutationNamePayload`.

Dans la référence sur les mutations, les *champs d'entrée* répertoriés correspondent à ceux que vous transmettez comme objet d'entrée. Les *champs de retour* listés correspondent à ce que vous passez en tant qu’objet de charge utile.

Pour obtenir un exemple réel, consultez [Exemple de mutation](#example-mutation).

## Utilisation de variables

Les [variables](https://graphql.org/learn/queries/#variables) peuvent rendre les requêtes plus dynamiques et plus puissantes, et elles peuvent réduire la complexité lors de la transmission d’objets d’entrée de mutation.

Voici un exemple de requête avec une variable unique :

```graphql
query($number_of_repos:Int!) {
  viewer {
    name
     repositories(last: $number_of_repos) {
       nodes {
         name
       }
     }
   }
}
variables {
   "number_of_repos": 3
}
```

L’utilisation des variables implique trois étapes :

1. Définir la variable en dehors de l’opération dans un objet `variables` :

   ```graphql
   variables {
      "number_of_repos": 3
   }
   ```

   L’objet doit être du JSON valide. Cet exemple montre un type de variable simple `Int`, mais il est possible de définir des types de variables plus complexes, tels que des objets d’entrée. Vous pouvez également définir plusieurs variables ici.

2. Passer la variable à l’opération en tant qu’argument :

   ```graphql
   query($number_of_repos:Int!){
   ```

   L’argument est une paire clé-valeur, où la clé est le *nom* commençant par `$` (par exemple `$number_of_repos`), et la valeur est le *type* (par exemple `Int`). Ajoutez un `!` pour indiquer si le type est obligatoire. Si vous avez défini plusieurs variables, incluez-les ici en tant qu’arguments multiples.

3. Utiliser la variable dans l’opération :

   ```graphql
   repositories(last: $number_of_repos) {
   ```

   Dans cet exemple, nous substituons la variable au nombre de dépôts à récupérer. Nous spécifions un type à l’étape 2, car GraphQL applique un typage fort.

Ce processus rend l’argument de requête dynamique. Nous pouvons maintenant simplement modifier la valeur dans l’objet `variables` et conserver le reste de la requête identique.

L’utilisation de variables comme arguments vous permet de mettre à jour dynamiquement les valeurs dans l’objet `variables` sans modifier la requête.

## Exemple de requête

Examinons une requête plus complexe et mettons ces informations dans le contexte.

La requête suivante recherche le dépôt `octocat/Hello-World`, recherche les 20 derniers problèmes fermés et retourne le titre, l’URL et les cinq premières étiquettes de chaque problème :

```graphql
query {
  repository(owner:"octocat", name:"Hello-World") {
    issues(last:20, states:CLOSED) {
      edges {
        node {
          title
          url
          labels(first:5) {
            edges {
              node {
                name
              }
            }
          }
        }
      }
    }
  }
}
```

Examinons la ligne de composition ligne par ligne :

* `query {`

  Comme nous souhaitons lire des données à partir du serveur, et non les modifier, `query` est l’opération racine. (Si vous ne spécifiez pas d’opération, `query` est également l’opération par défaut.)

* `repository(owner:"octocat", name:"Hello-World") {`

  Pour commencer la requête, nous voulons trouver un objet [`repository`](/fr/enterprise-server@3.22/graphql/reference/repos#object-repository). La validation du schéma indique que cet objet nécessite un `owner` et un argument `name`.

* `issues(last:20, states:CLOSED) {`

  Pour tenir compte de tous les problèmes dans le dépôts, nous appelons l’objet `issues`. (Nous *pourrions* interroger un `issue` unique sur un `repository`, mais cela nous obligerait à connaître le numéro du problème que nous souhaitons retourner et le fournir en tant qu’argument.)

  Quelques détails concernant l’objet `issues` :

  * La [documentation](/fr/enterprise-server@3.22/graphql/reference/repos#object-repository) nous indique que cet objet a le type `IssueConnection`.
  * La validation du schéma indique que cet objet nécessite un `last` ou `first` nombre de résultats comme argument ; nous fournissons donc la valeur `20`.
  * La [documentation](/fr/enterprise-server@3.22/graphql/reference/repos#object-repository) nous indique également que cet objet accepte un argument `states`, qui est une énumération [`IssueState`](/fr/enterprise-server@3.22/graphql/reference/issues#enum-issuestate) qui accepte des valeurs `OPEN` ou `CLOSED`. Pour trouver uniquement les problèmes fermés, nous affectons à la clé `states` la valeur `CLOSED`.

* `edges {`

  Nous savons que `issues` est une connexion car elle a le type `IssueConnection`. Pour récupérer des données sur des problèmes individuels, nous devons accéder au nœud via `edges`.

* `node {`

  Ici, nous récupérons le nœud à la fin de la périphérie. La documentation sur [`IssueConnection`](/fr/enterprise-server@3.22/graphql/reference/issues#object-issueconnection) indique que le nœud à la fin du type `IssueConnection` est un objet `Issue`.

* Maintenant que nous savons que nous récupérons un objet `Issue`, nous pouvons examiner la [documentation](/fr/enterprise-server@3.22/graphql/reference/issues#object-issue) et spécifier les champs que nous voulons retourner :

  ```graphql
  title
  url
  labels(first:5) {
    edges {
      node {
        name
      }
    }
  }
  ```

  Ici, nous spécifions les champs `title`, `url` et `labels` de l’objet `Issue`.

  Le champ `labels` a le type [`LabelConnection`](/fr/enterprise-server@3.22/graphql/reference/issues#object-labelconnection). Comme pour l’objet `issues`, `labels` étant une connexion, nous devons déplacer ses périphéries vers un nœud connecté : l’objet `label`. Au niveau du nœud, nous pouvons spécifier les champs d’objet `label` que nous voulons retourner, en l’occurrence `name`.

Vous remarquerez peut-être que l’exécution de cette requête sur le dépôt public `Hello-World` d’Octocat ne retournera pas beaucoup d’étiquettes. Essayez de l’exécuter sur l’un de vos propres dépôts qui utilisent des étiquettes, et vous verrez probablement une différence.

## Exemple de mutation

Les mutations nécessitent souvent des informations que vous ne pouvez connaître qu’en effectuant d’abord une requête. Cet exemple montre deux opérations :

1. Une requête pour obtenir un ID de problème
2. Une mutation pour ajouter un émoji de réaction à la question

```graphql
query FindIssueID {
  repository(owner:"octocat", name:"Hello-World") {
    issue(number:349) {
      id
    }
  }
}

mutation AddReactionToIssue {
  addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
    reaction {
      content
    }
    subject {
      id
    }
  }
}
```

Examinons un exemple. La tâche semble simple : ajouter un émoji de réaction à un problème.

Comment savons-nous qu’il faut commencer par une requête ? En fait, nous ne le savons pas encore.

Étant donné que nous voulons modifier des données sur le serveur (attacher un émoji à un problème), nous commençons par rechercher une mutation utile dans le schéma. La documentation de référence montre la mutation [`addReaction`](/fr/enterprise-server@3.22/graphql/reference/reactions#mutation-addreaction), avec cette description : `Adds a reaction to a subject.` Parfait !

La documentation des mutations liste trois champs d’entrée :

* `clientMutationId` (`String`)
* `subjectId` (`ID!`)
* `content` (`ReactionContent!`)

Les `!` indiquent que `subjectId` et `content` sont des champs obligatoires. Le caractère obligatoire de `content` est logique : nous voulons ajouter une réaction, nous devons donc spécifier l’émoji à utiliser.

Mais pourquoi `subjectId` est-il nécessaire ? Parce que le `subjectId` est le seul moyen d’identifier à *quel* problème dans *quel* dépôt il faut réagir.

C’est pourquoi nous commençons cet exemple par une requête : obtenir l’`ID`.

Examinons la requête ligne par ligne :

* `query FindIssueID {`

  Ici, nous exécutons une requête et nous la nommons `FindIssueID`. Notez que le nommage d’une requête est facultatif ; nous lui donnons un nom ici afin que nous puissions l’inclure dans la même fenêtre cliente gui que la mutation.

* `repository(owner:"octocat", name:"Hello-World") {`

  Nous spécifions le dépôt en interrogeant l’objet `repository` et en passant des arguments `owner` et `name`.

* `issue(number:349) {`

  Nous spécifions le problème auquel réagir en interrogeant l’objet `issue` et en transmettant un argument `number`.

* `id`

  C’est là que nous récupérons le `id` de `https://github.com/octocat/Hello-World/issues/349` pour le passer en tant que `subjectId`.

Lorsque nous exécutons la requête, nous obtenons l’`id` : `MDU6SXNzdWUyMzEzOTE1NTE=`

> \[!NOTE]
> La valeur `id` retournée dans la requête est la valeur que nous transmettrons en tant que `subjectID` dans la mutation. Ni la documentation ni l’introspection de schéma n’indiquera cette relation ; vous devrez comprendre les concepts qui sous-tendent les noms pour la déduire.

L’ID étant connu, nous pouvons poursuivre la mutation :

* `mutation AddReactionToIssue {`

  Ici, nous effectuons une mutation, et nous la nommons `AddReactionToIssue`. Comme pour les requêtes, le nommage d’une mutation est facultatif ; Nous lui donnons un nom ici pour pouvoir l’inclure dans la même fenêtre cliente d’interface graphique utilisateur que la requête.

* `addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {`

  Examinons cette ligne :

  * `addReaction` est le nom de la mutation
  * `input` est la clé d’argument requise. Ce sera toujours `input` pour une mutation.
  * `{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}` est la valeur d’argument requise. Il s’agit toujours d’un objet d’entrée (d’où les accolades) composé de champs d’entrée (`subjectId` et `content` dans ce cas) utilisés pour une mutation.

  Comment savons-nous quelle valeur utiliser pour le contenu ? La [`addReaction` documentation](/fr/enterprise-server@3.22/graphql/reference/reactions#mutation-addreaction) nous indique que le champ `content` est de type [`ReactionContent`](/fr/enterprise-server@3.22/graphql/reference/reactions#enum-reactioncontent), c’est-à-dire une énumération, car seules certaines réactions emoji sont prises en charge dans les issues GitHub. Voici les valeurs autorisées pour les réactions (notez que certaines valeurs diffèrent de leurs noms d’émojis correspondants) :

  <table style="width:20%">
  <thead>
  <tr>
  <th scope="col" style="text-align:left">Content</th>
  <th scope="col" style="text-align:left">Emoji</th>
  </tr>
  </thead>
  <tbody>
  <tr>
  <td style="text-align:left"><code>+1</code></td>
  <td style="text-align:left">👍</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>-1</code></td>
  <td style="text-align:left">👎</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>laugh</code></td>
  <td style="text-align:left">😄</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>confused</code></td>
  <td style="text-align:left">😕</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>heart</code></td>
  <td style="text-align:left">❤️</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>hooray</code></td>
  <td style="text-align:left">🎉</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>rocket</code></td>
  <td style="text-align:left">🚀</td>
  </tr>
  <tr>
  <td style="text-align:left"><code>eyes</code></td>
  <td style="text-align:left">👀</td>
  </tr>
  </tbody>
  </table>

* Le reste de l’appel est composé de l’objet de charge utile. C’est là que nous spécifions les données que nous voulons que le serveur retourne une fois que nous avons effectué la mutation. Ces lignes proviennent de la documentation sur [`addReaction`](/fr/enterprise-server@3.22/graphql/reference/reactions#mutation-addreaction), avec trois champs de retour possibles :

  * `clientMutationId` (`String`)
  * `reaction` (`Reaction!`)
  * `subject` (`Reactable!`)

  Dans cet exemple, nous retournons les deux champs obligatoires (`reaction` et `subject`), tous deux ayant des sous-champs obligatoires (respectivement `content` et `id`).

Lorsque nous exécutons la mutation, voici la réponse :

```json
{
  "data": {
    "addReaction": {
      "reaction": {
        "content": "HOORAY"
      },
      "subject": {
        "id": "MDU6SXNzdWUyMTc5NTQ0OTc="
      }
    }
  }
}
```

Et voilà ! Consultez votre [réaction au problème](https://github.com/octocat/Hello-World/issues/349) en pointant sur :tada : pour trouver votre nom d’utilisateur.

Une dernière remarque : lorsque vous transmettez plusieurs champs dans un objet d’entrée, la syntaxe peut être un peu encombrée. Déplacer les champs dans une [variable](#working-with-variables) peut aider. Voici comment vous pourriez réécrire la mutation d’origine à l’aide d’une variable :

```graphql
mutation($myVar:AddReactionInput!) {
  addReaction(input:$myVar) {
    reaction {
      content
    }
    subject {
      id
    }
  }
}
variables {
  "myVar": {
    "subjectId":"MDU6SXNzdWUyMTc5NTQ0OTc=",
    "content":"HOORAY"
  }
}
```

> \[!NOTE]
> Vous remarquerez peut-être que la valeur du champ `content` dans l’exemple précédent (où elle est utilisée directement dans la mutation) n’a pas de guillemets autour de `HOORAY`, mais qu’elle en a en cas d’utilisation dans la variable. Il y a une raison à cela :
>
> * Lorsque vous utilisez `content` directement dans la mutation, le schéma s’attend à ce que la valeur soit de type [`ReactionContent`](/fr/enterprise-server@3.22/graphql/reference/reactions#enum-reactioncontent), qui est une *énumération*, et non une chaîne. La validation du schéma génère une erreur si vous ajoutez des guillemets autour de la valeur d’énumération, car les guillemets sont réservés aux chaînes.
> * Lorsque vous utilisez `content` dans une variable, la section des variables doit être du JSON valide ; les guillemets sont donc obligatoires. La validation du schéma interprète correctement le type `ReactionContent` lorsque la variable est transmise dans la mutation pendant l’exécution.
>
> Pour plus d’informations sur la différence entre les enums et les chaînes de caractères, consultez la [spécification GraphQL officielle](https://spec.graphql.org/June2018/#sec-Enums).

## Pour approfondir

Il est possible de faire *beaucoup plus* de choses lors de la formation d’appels GraphQL. Voici quelques pistes à suivre :

* [Utilisation de la pagination dans l’API GraphQL](/fr/enterprise-server@3.22/graphql/guides/using-pagination-in-the-graphql-api)
* [Fragments](https://graphql.org/learn/queries/#fragments)
* [Fragments inline](https://graphql.org/learn/queries/#inline-fragments)
* [Directives](https://graphql.org/learn/queries/#directives)