API du simulateur (intégration headless)


Cette documentation s'adresse aux clients qui veulent construire leur propre interface de simulation (avec leur charte graphique) plutôt que d'intégrer le widget Mula tel quel. Vous envoyez les données du formulaire à notre API, vous recevez le résultat du calcul en JSON, éventuellement accompagné d'un lien vers un PDF généré.

Pour l'intégration du widget préconstruit (bouton flottant, formulaire inclus), voir Installation de la widget.

Accès

Aucune clé d'API n'est nécessaire. L'accès se fait via le serial de votre Source, visible dans votre espace Mula.

https://prod003.simulation-portage-salarial.fr/api/v1/sources/{SERIAL}/...

Les appels sont limités à 60 requêtes par minute.

Important : ajoutez toujours l'en-tête suivant à vos requêtes, sinon les erreurs (validation, etc.) vous reviendront en HTML au lieu de JSON :

Accept: application/json

1 - Calculer une simulation

POST /api/v1/sources/{SERIAL}/simulators/salary/compute-public

Retourne uniquement le résultat du calcul, en JSON. Adapté à un simulateur qui recalcule en direct (à chaque changement de champ), car aucun PDF n'est généré ici.

Champs à envoyer

Le champ ope détermine le mode de calcul, et donc quel champ de montant est attendu :

ope Champ de montant requis Mode
1 tjm Taux Journalier Moyen
2 (avec cout_total: 1) cout Coût total
2 (sans cout_total, ou cout_total: 0) ca Chiffre d'affaires

Autres champs :

Champ Obligatoire Description
contract_type oui "CDI" ou "CDD"
notbillable_fees oui Frais professionnels non refacturables
nombre_jours oui Nombre de jours travaillés dans le mois (entier)
email selon config de la Source Peut être rendu obligatoire dans les réglages de votre Source
overtime non Nombre d'heures supplémentaires
sans_mutuelle non 1 pour exclure la mutuelle du calcul
mutuelle_type non 1 (isolé), 2 (famille), 3 (duo)
management_fee_fix non Plafonné selon la config de votre Source

Exemple de requête

fetch("https://prod003.simulation-portage-salarial.fr/api/v1/sources/{SERIAL}/simulators/salary/compute-public", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json"
  },
  body: JSON.stringify({
    ope: 1,
    tjm: 400,
    contract_type: "CDI",
    notbillable_fees: 150,
    nombre_jours: 18,
    sans_mutuelle: 0,
    mutuelle_type: 1
  })
})
  .then(res => res.json())
  .then(data => console.log(data));

Réponse

{
  "salaire_brut": 4404.41,
  "net_a_payer": 3469.64,
  "net_plus_frais": 3619.64,
  "charges_patronales": 1925.59,
  "taux_charges_patronales": 43.72,
  "charges_salariales": 934.77,
  "taux_charges_salariales": 21.22,
  "indemnites_repas": 0,
  "ca_mensuel": 7200,
  "avec_mutuelle": 1,
  "net_imposable": 3595.13
}

2 - Calculer une simulation et générer le PDF

POST /api/v1/sources/{SERIAL}/simulators/salary/compute-pdf

Mêmes champs d'entrée que compute-public ci-dessus. Adapté à un formulaire validé une seule fois (pas de recalcul en direct), puisqu'un PDF est généré à chaque appel.

La réponse contient les mêmes champs que compute-public, plus pdf_url :

{
  "salaire_brut": 4404.41,
  "net_a_payer": 3469.64,
  "net_plus_frais": 3619.64,
  "charges_patronales": 1925.59,
  "taux_charges_patronales": 43.72,
  "charges_salariales": 934.77,
  "taux_charges_salariales": 21.22,
  "indemnites_repas": 0,
  "ca_mensuel": 7200,
  "avec_mutuelle": 1,
  "net_imposable": 3595.13,
  "pdf_url": "https://prod003.simulation-portage-salarial.fr/tmp/Simulation-salaire-VotreSociete_1788184729.pdf"
}

Si une gabarit personnalisée ("Gabarit du pdf de la simulation") est configurée sur votre Source, le PDF est généré avec cette gabarit. Sinon, le modèle standard Mula est utilisé.

Quel endpoint utiliser ?

Votre besoin Endpoint
Simulateur qui affiche le résultat en direct, à chaque champ modifié compute-public
Formulaire validé une fois, avec bouton de téléchargement du PDF compute-pdf uniquement (il donne déjà le résultat ET le PDF en un seul appel — inutile d'appeler compute-public avant)

Erreurs

Une requête invalide renvoie un code 422 avec le détail :

{
  "message": "The given data was invalid.",
  "errors": {
    "contract_type": ["Le champ contract type est obligatoire."]
  }
}