Diamond Careers
APIExemples

Exemples PHP

Exemples PHP (8.1+) avec Guzzle : authentification, lecture, écriture, téléversement, retry.

Cette page propose des exemples PHP (8.1+) avec Guzzle, standard de fait dans l'écosystème PHP.

Installation

composer require guzzlehttp/guzzle vlucas/phpdotenv

Avec un fichier .env à la racine :

DIAMOND_BASE=https://api.diamondcareers.fr/diamond/v1
DIAMOND_EMAIL=integration@votre-etablissement.com
DIAMOND_PASSWORD=VotreMotDePasseTechnique

Client minimal

<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Dotenv\Dotenv;

$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();

class DiamondClient
{
    private Client $http;
    private ?string $token = null;
    private string $base;

    public function __construct()
    {
        $this->base = $_ENV['DIAMOND_BASE'];
        $this->http = new Client(['timeout' => 30]);
    }

    public function getToken(): string
    {
        if ($this->token !== null) {
            return $this->token;
        }
        $response = $this->http->post("{$this->base}/auth/login", [
            'json' => [
                'email' => $_ENV['DIAMOND_EMAIL'],
                'password' => $_ENV['DIAMOND_PASSWORD'],
            ],
        ]);
        $data = json_decode((string) $response->getBody(), true);
        $this->token = $data['token'];
        return $this->token;
    }

    public function api(string $path, string $method = 'GET', array $options = []): mixed
    {
        $options['headers'] = array_merge([
            'Authorization' => 'Bearer ' . $this->getToken(),
            'Content-Type' => 'application/json',
        ], $options['headers'] ?? []);

        try {
            $response = $this->http->request($method, "{$this->base}{$path}", $options);
            $body = (string) $response->getBody();
            if ($response->getStatusCode() === 204 || $body === '') {
                return null;
            }
            return json_decode($body, true);
        } catch (ClientException $e) {
            $body = (string) $e->getResponse()->getBody();
            $error = json_decode($body, true) ?? ['message' => $e->getMessage()];
            throw new \RuntimeException(
                $error['message'] ?? 'Unknown error',
                $e->getResponse()->getStatusCode(),
                $e
            );
        }
    }
}

$diamond = new DiamondClient();

Lister vos offres publiées

$offers = $diamond->api('/offres?status=publish&per_page=100');
echo count($offers) . " offres publiées\n";
foreach ($offers as $offer) {
    $meta = $offer['meta'] ?? [];
    echo "- {$offer['title']} ({$meta['city']}) — {$meta['contract_type']}\n";
}

Synchronisation par delta

function syncOffersIncremental(DiamondClient $diamond, DateTimeInterface $since): int
{
    $sinceIso = $since->format(DATE_ATOM);
    $page = 1;
    $processed = 0;

    while (true) {
        $offers = $diamond->api(
            "/offres?filter[modified_after]=" . urlencode($sinceIso) .
            "&per_page=100&page={$page}"
        );
        if (empty($offers)) break;
        foreach ($offers as $offer) {
            processOffer($offer);
            $processed++;
        }
        if (count($offers) < 100) break;
        $page++;
    }
    return $processed;
}

Créer une offre

$newOffer = $diamond->api('/offres', 'POST', [
    'json' => [
        'title' => 'Chef de partie pâtisserie — restaurant gastronomique',
        'meta' => [
            'contract_type' => 'cdi',
            'city' => 'Paris',
            'country' => 'France',
            'salary_min' => 32000,
            'salary_max' => 38000,
            'salary_display' => '32 000 € – 38 000 €',
            'description' => '<p>Au sein d une brigade de 18 personnes...</p>',
            'missions' => '<ul><li>Encadrer 4 commis</li></ul>',
            'profile_required' => '<p>3 ans d expérience minimum.</p>',
            'start_date' => '2026-09-01',
        ],
    ],
]);
echo "Offre créée : {$newOffer['id']}\n";

Faire évoluer le statut d'une candidature

function setApplicationStatus(DiamondClient $diamond, int $id, string $status, ?string $comment = null): array
{
    $payload = ['status' => $status];
    if ($comment !== null) {
        $payload['comment'] = $comment;
    }
    return $diamond->api("/candidatures/{$id}/status", 'PATCH', ['json' => $payload]);
}

setApplicationStatus($diamond, 18472, 'interview', 'Entretien prévu le 18 mai à 14 h.');

Téléverser un visuel public

function uploadImage(DiamondClient $diamond, string $filePath, string $mime = 'image/jpeg'): array
{
    $token = $diamond->getToken();
    $client = new GuzzleHttp\Client();
    $response = $client->post(
        $_ENV['DIAMOND_BASE'] . '/upload',
        [
            'headers' => ['Authorization' => "Bearer {$token}"],
            'multipart' => [
                ['name' => 'file', 'contents' => fopen($filePath, 'r'), 'filename' => basename($filePath), 'headers' => ['Content-Type' => $mime]],
            ],
        ]
    );
    return json_decode((string) $response->getBody(), true);
}

$media = uploadImage($diamond, './visuel-offre.jpg');
echo "URL publique : {$media['file_url']}\n";

Récupérer un fichier privé

function downloadSecureFile(DiamondClient $diamond, string $path, string $dest): void
{
    $token = $diamond->getToken();
    $client = new GuzzleHttp\Client();
    $client->get(
        $_ENV['DIAMOND_BASE'] . '/secure-file?path=' . urlencode($path),
        [
            'headers' => ['Authorization' => "Bearer {$token}"],
            'sink' => $dest,
        ]
    );
}

downloadSecureFile($diamond, 'cv/9281/abcd-1234.pdf', './telecharge.pdf');

Gestion des erreurs et retry

function apiWithRetry(DiamondClient $diamond, string $path, string $method = 'GET', array $options = [], int $maxRetries = 3): mixed
{
    $lastError = null;
    for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
        try {
            return $diamond->api($path, $method, $options);
        } catch (\RuntimeException $e) {
            $lastError = $e;
            $status = $e->getCode();
            if ($status >= 400 && $status < 500 && $status !== 429) {
                throw $e;
            }
            $delay = min(30, pow(2, $attempt));
            error_log("Tentative " . ($attempt + 1) . " échouée ({$status}), retry dans {$delay}s");
            sleep($delay);
        }
    }
    throw $lastError;
}

Itération paresseuse via générateur

function iterateAll(DiamondClient $diamond, string $path, int $perPage = 100): \Generator
{
    $page = 1;
    while (true) {
        $separator = str_contains($path, '?') ? '&' : '?';
        $items = $diamond->api("{$path}{$separator}per_page={$perPage}&page={$page}");
        if (empty($items)) return;
        foreach ($items as $item) {
            yield $item;
        }
        if (count($items) < $perPage) return;
        $page++;
    }
}

foreach (iterateAll($diamond, '/offres?status=publish') as $offer) {
    processOffer($offer);
}

Bonnes pratiques

  • Cachez le jeton dans une session ou un cache mémoire (Redis, APCu) avec un TTL aligné sur sa durée de vie réelle.
  • Loguez via Monolog avec des niveaux et un format structuré.
  • Gérez les exceptions Guzzle distinctement (ClientException, ServerException, ConnectException) pour ajuster votre logique de retry.
  • Pour les gros volumes, envisagez GuzzleHttp\Pool pour paralléliser intelligemment les requêtes.

On this page