Guide d'utilisation de l'API PDP

Plateforme de Dématérialisation PartenaireCopied!

Table des matières

  1. Introduction

  2. Premiers pas

  3. Authentification

  4. Gestion des documents

  5. Workflows de validation

  6. Signatures électroniques

  7. Notifications

  8. Audit et traçabilité

  9. Codes d'erreur

  10. Exemples d'intégration

  11. Bonnes pratiques

IntroductionCopied!

L'API PDP (Plateforme de Dématérialisation Partenaire) permet aux organisations de gérer leurs documents numériques, workflows de validation et signatures électroniques de manière sécurisée et conforme aux réglementations françaises.

Caractéristiques principales

  • Sécurité renforcée : Authentification JWT, audit trail complet

  • Conformité réglementaire : Respect des normes françaises de dématérialisation

  • Signatures électroniques : Support des signatures simples, avancées et qualifiées

  • Workflows flexibles : Processus de validation configurables

  • API REST : Interface standardisée et bien documentée

Prérequis

  • Compte partenaire validé sur la plateforme PDP

  • Clés d'API fournies par l'équipe PDP

  • Connaissance des API REST et du format JSON

Premiers pasCopied!

1. Environnements disponibles

Environnement

URL

Usage

Production

https://api.pdp.gouv.fr/v1

Utilisation en production

Test

https://staging-api.pdp.gouv.fr/v1

Tests et développement

2. Authentification initiale

Toutes les requêtes nécessitent une authentification. Utilisez vos identifiants partenaire pour obtenir un token :

j3. Utilisation du token

Incluez le token dans l'en-tête

Authorization

de toutes vos requêtes :

AuthentificationCopied!

Types d'authentification

L'API supporte deux méthodes d'authentification :

  1. JWT Bearer Token (recommandé) : Token temporaire avec refresh automatique

  2. API Key : Clé permanente pour les intégrations serveur-à-serveur

Gestion des tokens JWT

Les tokens JWT ont une durée de vie limitée (1 heure par défaut). Utilisez le refresh token pour renouveler automatiquement :

Sécurité

  • Stockage sécurisé : Ne jamais exposer les tokens côté client

  • HTTPS obligatoire : Toutes les communications doivent utiliser HTTPS

  • Rotation régulière : Les clés d'API doivent être renouvelées périodiquement

Gestion des documentsCopied!

Upload d'un document

L'upload utilise le format

multipart/form-data

pour supporter les fichiers binaires :

Types de documents supportés

Type

Description

Métadonnées spécifiques

facture

Factures et notes de frais

numero_facture, montant_ht, tva

contrat

Contrats et avenants

duree, montant_total, parties

devis

Devis et propositions commerciales

validite, montant_ht, conditions

bon_commande

Bons de commande

numero_commande, fournisseur

autre

Autres types de documents

Métadonnées libres

Recherche et filtrage

Gestion des versions

Chaque modification d'un document crée une nouvelle version. L'historique complet est conservé :

Workflows de validationCopied!

Types de workflows

  1. Validation simple : Un seul validateur

  2. Validation multiple : Plusieurs validateurs en séquence

  3. Signature électronique : Processus de signature multi-parties

Création d'un workflow

Exécution d'un workflow

Suivi de l'exécution

L'API fournit un suivi en temps réel de l'avancement :

Signatures électroniquesCopied!

Types de signatures supportés

Type

Niveau de sécurité

Usage recommandé

simple

Basique

Documents internes, accusés de réception

avancee

Élevé

Contrats commerciaux, documents officiels

qualifiee

Maximum

Documents juridiques, actes notariés

Processus de signature

1. Création de la demande
2. Notification des signataires

Les signataires reçoivent automatiquement :

  • Email avec lien de signature sécurisé

  • Token de signature unique

  • Instructions de signature

3. Processus de signature

Validation des signatures

Toutes les signatures incluent :

  • Certificat numérique : Identité du signataire

  • Horodatage qualifié : Date et heure exactes

  • Empreinte du document : Garantie d'intégrité

  • Adresse IP : Traçabilité géographique

NotificationsCopied!

Types de notifications

Type

Description

Déclencheur

document_recu

Nouveau document reçu

Upload de document

signature_requise

Signature demandée

Création demande de signature

workflow_termine

Workflow terminé

Fin de processus

erreur

Erreur système

Échec d'opération

Consultation des notifications

Webhooks (optionnel)

Pour un traitement en temps réel, configurez des webhooks :

Audit et traçabilitéCopied!

Consultation des logs

L'API fournit un accès complet aux logs d'audit :

Informations tracées

Chaque action inclut :

  • Qui : Utilisateur ayant effectué l'action

  • Quoi : Type d'action et ressource concernée

  • Quand : Horodatage précis

  • : Adresse IP et user agent

  • Détails : Informations contextuelles

Conformité RGPD

  • Pseudonymisation des données personnelles

  • Droit à l'effacement respecté

  • Durée de conservation configurable

  • Export des données sur demande

Codes d'erreurCopied!

Codes HTTP standards

Code

Signification

Action recommandée

200

Succès

Continuer

201

Créé avec succès

Continuer

400

Requête invalide

Vérifier les paramètres

401

Non autorisé

Renouveler le token

403

Accès interdit

Vérifier les permissions

404

Non trouvé

Vérifier l'ID de ressource

422

Erreur de validation

Corriger les données

429

Trop de requêtes

Implementer rate limiting

500

Erreur serveur

Réessayer plus tard

Codes d'erreur métier

{
  "code": "DOCUMENT_SIGNATURE_REQUIRED",
  "message": "Ce document nécessite une signature avant validation",
  "details": ["Le workflow exige une signature électronique"],
  "timestamp": "2025-05-28T10:30:00Z"
}

Gestion des erreurs

async function handleApiCall(url, options) {
  try {
    const response = await fetch(url, options);
    
    if (!response.ok) {
      const error = await response.json();
      
      switch (response.status) {
        case 401:
          // Renouveler le token
          await refreshToken();
          return handleApiCall(url, options);
          
        case 422:
          // Erreur de validation
          console.error('Données invalides:', error.details);
          break;
          
        case 429:
          // Rate limiting
          await delay(error.retry_after * 1000);
          return handleApiCall(url, options);
          
        default:
          console.error('Erreur API:', error.message);
      }
      
      throw new Error(error.message);
    }
    
    return await response.json();
    
  } catch (error) {
    console.error('Erreur réseau:', error);
    throw error;
  }
}

Exemples d'intégrationCopied!

Ruby on Rails

# Gemfile
gem 'faraday'
gem 'jwt'

# app/services/pdp_service.rb
class PdpService
  BASE_URL = 'https://api.pdp.gouv.fr/v1'
  
  def initialize(token = nil)
    @token = token || authenticate
    @client = Faraday.new(url: BASE_URL) do |conn|
      conn.request :json
      conn.response :json
      conn.headers['Authorization'] = "Bearer #{@token}"
    end
  end
  
  def upload_document(file_path, metadata)
    payload = {
      fichier: Faraday::UploadIO.new(file_path, 'application/pdf'),
      type_document: metadata[:type],
      titre: metadata[:titre],
      description: metadata[:description]
    }
    
    response = @client.post('/documents', payload)
    handle_response(response)
  end
  
  def create_signature_request(document_id, signataires)
    payload = {
      document_id: document_id,
      type_signature: 'avancee',
      signataires: signataires
    }
    
    response = @client.post('/signatures', payload)
    handle_response(response)
  end
  
  private
  
  def authenticate
    response = Faraday.post("#{BASE_URL}/auth/login", {
      email: ENV['PDP_EMAIL'],
      mot_de_passe: ENV['PDP_PASSWORD'],
      code_partenaire: ENV['PDP_PARTNER_CODE']
    }.to_json, { 'Content-Type' => 'application/json' })
    
    JSON.parse(response.body)['access_token']
  end
  
  def handle_response(response)
    case response.status
    when 200..299
      response.body
    when 401
      @token = authenticate
      raise 'Token expired, please retry'
    else
      raise "API Error: #{response.body['message']}"
    end
  end
end

# Utilisation
pdp = PdpService.new

# Upload d'un document
document = pdp.upload_document(
  '/path/to/facture.pdf',
  {
    type: 'facture',
    titre: 'Facture Mai 2025',
    description: 'Facture de prestations'
  }
)

# Demande de signature
signature = pdp.create_signature_request(
  document['id'],
  [
    {
      email: 'directeur@entreprise.fr',
      nom: 'Dupont',
      prenom: 'Jean',
      ordre_signature: 1
    }
  ]
)

JavaScript/Node.js

// package.json dependencies
// "axios": "^1.0.0",
// "form-data": "^4.0.0"

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');

class PDPClient {
  constructor() {
    this.baseURL = 'https://api.pdp.gouv.fr/v1';
    this.token = null;
    
    this.client = axios.create({
      baseURL: this.baseURL,
      timeout: 30000
    });
    
    // Intercepteur pour l'authentification automatique
    this.client.interceptors.request.use(async (config) => {
      if (!this.token) {
        await this.authenticate();
      }
      config.headers.Authorization = `Bearer ${this.token}`;
      return config;
    });
    
    // Intercepteur pour le renouvellement automatique
    this.client.interceptors.response.use(
      (response) => response,
      async (error) => {
        if (error.response?.status === 401) {
          await this.authenticate();
          return this.client.request(error.config);
        }
        return Promise.reject(error);
      }
    );
  }
  
  async authenticate() {
    try {
      const response = await axios.post(`${this.baseURL}/auth/login`, {
        email: process.env.PDP_EMAIL,
        mot_de_passe: process.env.PDP_PASSWORD,
        code_partenaire: process.env.PDP_PARTNER_CODE
      });
      
      this.token = response.data.access_token;
      return this.token;
    } catch (error) {
      throw new Error(`Authentication failed: ${error.message}`);
    }
  }
  
  async uploadDocument(filePath, metadata) {
    const form = new FormData();
    form.append('fichier', fs.createReadStream(filePath));
    form.append('type_document', metadata.type);
    form.append('titre', metadata.titre);
    
    if (metadata.description) {
      form.append('description', metadata.description);
    }
    
    const response = await this.client.post('/documents', form, {
      headers: form.getHeaders()
    });
    
    return response.data;
  }
  
  async getDocuments(filters = {}) {
    const params = new URLSearchParams(filters);
    const response = await this.client.get(`/documents?${params}`);
    return response.data;
  }
  
  async createWorkflow(workflowData) {
    const response = await this.client.post('/workflows', workflowData);
    return response.data;
  }
  
  async executeWorkflow(workflowId, documentId, params = {}) {
    const response = await this.client.post(`/workflows/${workflowId}/executer`, {
      document_id: documentId,
      parametres: params
    });
    return response.data;
  }
}

// Utilisation
async function example() {
  const pdp = new PDPClient();
  
  try {
    // Upload d'un document
    const document = await pdp.uploadDocument('./facture.pdf', {
      type: 'facture',
      titre: 'Facture Mai 2025',
      description: 'Prestations de développement'
    });
    
    console.log('Document uploadé:', document.id);
    
    // Création d'un workflow
    const workflow = await pdp.createWorkflow({
      nom: 'Validation facture',
      type_workflow: 'validation_simple',
      etapes: [{
        ordre: 1,
        nom: 'Validation comptable',
        type_action: 'validation',
        assignes: ['comptable@entreprise.fr'],
        delai_max: 48
      }]
    });
    
    // Exécution du workflow
    const execution = await pdp.executeWorkflow(
      workflow.id,
      document.id,
      { priorite: 'normale' }
    );
    
    console.log('Workflow lancé:', execution.id);
    
  } catch (error) {
    console.error('Erreur:', error.message);
  }
}