Sociétés, salariés et contrats

Les établissements du client, les personnes qui y travaillent, et les contrats qui les lient. Ces lectures portent des données personnelles : chaque champ est classifié dans la référence de l'API, et certains ne sont rendus que si un scope dédié vous a été accordé.

Lisez d'abord Découverte : les référentiels qu'elle décrit sont ce contre quoi se résolvent les identifiants ci-dessous.

Sociétés

GET /api/v1/client/companies (scopes : companies:read) GET /api/v1/client/companies/{id} (mêmes scopes)

{
  "items": [
    {
      "id": "lPBpV3",
      "name": "Atelier Central",
      "code": "AC-01",
      "siret": "12345678900012",
      "siren": "123456789",
      "isHeadquarter": true,
      "isManagingEstablishment": false,
      "businessSign": "Atelier",
      "address": {
        "street": "12 rue des Fabriques",
        "postalCode": "69001",
        "city": "Lyon",
        "country": "France"
      },
      "phoneNumber": "0400000000",
      "legalCategoryLabel": "SAS",
      "activityCode": "2562B",
      "activityLabel": "Mecanique industrielle",
      "collectiveAgreementName": "Metallurgie",
      "collectiveAgreementIdcc": "3248",
      "weeklyWorkingHours": 35,
      "masterCompanyId": "dV3QPr",
      "masterName": "Groupe Central"
    }
  ],
  "nextCursor": null
}
Champ Ce qu'il vous dit
id Identifiant opaque. Toutes les autres lectures le prennent comme companyId.
siret, siren Identifiants légaux publics, en clair — ils ne sont pas opaques, vous pouvez rapprocher dessus.
isHeadquarter true pour le siège.
collectiveAgreementIdcc Le code IDCC, qui joint le référentiel des conventions collectives.
masterCompanyId L'établissement parent, quand il y en a un.

La liste rend une entrée par établissement de votre périmètre. Un identifiant mandaté sur un groupe parcourt tous les établissements qu'il atteint ; mandaté sur une seule société, il n'en contient toujours qu'une. La forme de la réponse est la même dans les deux cas : parcourez la page plutôt que d'en lire le premier élément.

Salariés

GET /api/v1/client/employees (scopes : employees:read) GET /api/v1/client/employees/{id} (mêmes scopes)

{
  "items": [
    {
      "id": "1VaKPa",
      "fullName": "Camille Dupont",
      "civility": "Mme",
      "employeeNumber": "E-0042",
      "professionalEmail": null,
      "companyId": "dV3QPr",
      "companyName": "Atelier Central",
      "isActive": true,
      "jobFunction": "Chef d\u0027atelier",
      "managerResourceId": "GNnBNO",
      "managerFullName": "Renaud Lambert"
    },
    {
      "id": "DJABPM",
      "fullName": "Camille Dupont",
      "civility": "Mme",
      "employeeNumber": "E-0042",
      "professionalEmail": null,
      "companyId": "dV3QPr",
      "companyName": "Atelier Central",
      "isActive": true,
      "jobFunction": "Chef d\u0027atelier",
      "managerResourceId": "GNnBNO",
      "managerFullName": "Renaud Lambert"
    }
  ],
  "nextCursor": null
}
Champ Ce qu'il vous dit
id Identifiant opaque — le {id} que prennent les lectures de contrat et de congés.
employeeNumber Le matricule tel que l'employeur l'a fixé. Pas garanti unique entre sociétés.
isActive false pour quelqu'un qui est parti. Il reste rendu.
managerResourceId Son responsable, quand la fiche de ce responsable est dans la même société.
managerFullName Le nom du responsable, à la même condition.

Un responsable d'une autre société revient à null, pas sous forme d'identifiant irrésoluble. Les groupes où l'on reporte d'un établissement à l'autre verront donc des trous dans la ligne hiérarchique. C'est délibéré : nommer quelqu'un hors du périmètre qui vous a été accordé reviendrait à le divulguer.

Les fiches confidentielles et archivées ne sont jamais rendues, par aucune lecture. Un salarié marqué confidentiel dans Staff & Go est absent de cette liste et répond 404 par identifiant — la même réponse qu'un identifiant inexistant, de sorte que vous ne pouvez pas distinguer les deux cas. C'est le but.

Contrats de travail

GET /api/v1/client/employees/{id}/employments (scopes : employments:read) GET /api/v1/client/employments/{id} (mêmes scopes)

{
  "id": "lPBpV3",
  "employeeId": "GNnBNO",
  "companyId": "dV3QPr",
  "startDate": "2020-01-06",
  "endDate": null,
  "contractType": "CDI",
  "jobTitle": "Chef d atelier",
  "hiringClass": "CADRE",
  "weeklyWorkingHours": 35,
  "managerResourceId": "XJ2rJL",
  "grossSalary": null,
  "netSalary": null,
  "salaryPeriod": null,
  "restricted": [
    {
      "reason": "requires_scope",
      "fields": [
        "grossSalary",
        "netSalary",
        "salaryPeriod"
      ]
    },
    {
      "reason": "requires_company_opt_in",
      "fields": [
        "grossSalary",
        "netSalary",
        "salaryPeriod"
      ]
    }
  ]
}
Champ Ce qu'il vous dit
id Le contrat.
employeeId À qui il appartient — l'identifiant que prennent les lectures salarié.
contractType En toutes lettres (« CDI »), dans votre langue : envoyez Accept-Language.
jobTitle L'intitulé de poste, texte libre tel que l'employeur l'a écrit.
hiringClass Le statut professionnel tel qu'il a été saisi. Voir l'avertissement ci-dessous.
weeklyWorkingHours Les heures hebdomadaires contractuelles.
grossSalary, netSalary, salaryPeriod La rémunération. Derrière un scope dédié — voir plus bas.

hiringClass est du texte libre, sans référentiel derrière. Il est écrit par un champ de synchronisation de connecteur de paie et par un modèle de document, sans clé étrangère, et rien dans Staff & Go ne le relie au référentiel des statuts professionnels. Ne le joignez pas sur hiringCode, quelle que soit leur ressemblance : les deux ne coïncident que si le connecteur emploie le même vocabulaire, et rien ne l'impose.

Attendez-vous à plusieurs contrats là où vous en attendiez un. Un salarié accumule des avenants au fil d'une carrière, et chacun est une ligne ici. Le listing est paginé : parcourez-le jusqu'au bout plutôt que de lire la première entrée.

Un identifiant de salarié qui n'est pas des vôtres répond 404, pas une page vide. Il désigne le sujet de la lecture, et un sujet qui ne se résout pas n'a pas d'ensemble à rendre vide. C'est différent d'un filtre, qui restreint un ensemble et peut légitimement le restreindre à rien.

Champs retirés

Certains champs ne sont rendus qu'à un partenaire à qui un scope dédié a été accordé. La rémunération est le premier : employments:read:compensation, exigé en plus d'employments:read, qui ne l'implique jamais.

Quand un champ est retiré, il revient à null et il est nommé dans restricted :

"grossSalary": null,
"restricted": [
  { "reason": "requires_scope", "fields": ["grossSalary", "netSalary", "salaryPeriod"] },
  { "reason": "requires_company_opt_in", "fields": ["grossSalary", "netSalary", "salaryPeriod"] }
]

Un null seul ne veut jamais dire « retiré ». Un champ null et absent de restricted n'a réellement aucune valeur enregistrée. Ce sont deux faits différents et ce contrat les tient séparés — ne présentez pas l'un pour l'autre à vos utilisateurs.

Motif Ce qui le lève
requires_scope Demandez à l'administrateur du client d'accorder le sous-scope sur vos identifiants.
requires_company_opt_in La société elle-même n'a pas ouvert le champ. Elle seule le peut.
requires_plan Votre plan partenaire ne couvre pas ce champ.

Plusieurs motifs peuvent apparaître ensemble, et ils comptent tous. Ils sont tranchés par des parties différentes — l'administrateur qui a créé vos accès, la société lue, et votre propre plan — donc en lever un laisse les autres debout. Un partenaire à qui l'on n'annoncerait que le « premier » obstacle l'obtiendrait puis se heurterait au même champ retiré.

restricted voyage dans chaque entrée, y compris dans une page, jamais une seule fois au-dessus de la liste. Sur un listing couvrant plusieurs sociétés, certaines auront ouvert un champ et d'autres non : aucune enveloppe unique ne pourrait décrire la page avec justesse. Quand rien n'a été retiré, le tableau est vide — une seule forme, toujours.

Trois lectures portent cette enveloppe : les contrats de travail, les lignes de congé et les éléments variables de paie. Ce sont les seules dont un champ peut être retiré, et chacune a son propre sous-scope — employments:read:compensation, leaves:read:reason, payroll:read:amounts — ainsi que sa propre décision d'ouverture par la société. Aucun des trois n'en implique un autre : la rémunération contractuelle et ce qu'un mois de paie a enregistré sont deux décisions distinctes, prises séparément par chaque société. Les autres — sociétés, salariés, soldes, référentiels, notes de frais, titres restaurant, bulletins de paie — n'ont pas de clé restricted du tout, et cette absence dit qu'il n'y a rien à y retirer, jamais que rien ne l'a été. Un null y est donc toujours une valeur non enregistrée : c'est le cas du responsable d'une autre société décrit plus haut, qui n'est pas un champ caviardé.