API v1

Introduction

L’API vous permet de piloter votre compte par programme ou avec un assistant IA : portfolios (sections, entrées, thème, publication), CV (création, copie depuis un portfolio, export PDF), entreprises, offres d’emploi et candidatures reçues. Elle applique les mêmes règles et les mêmes quotas de formule que l’application.

Base URL : https://middlefolio.online/api/v1

Démarrage rapide

  1. Dans le tableau de bord, ouvrez API > Gérer et créez une clé de test.
  2. Faites votre premier appel : lisez votre profil (exemple ci-dessous, dans votre langage).
  3. Créez un portfolio avec la même clé de test : la réponse est réelle, mais rien n’est enregistré.
  4. Passez à une clé réelle (et activez le module API) une fois votre intégration validée.
curl 'https://middlefolio.online/api/v1/me' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'
curl -X POST 'https://middlefolio.online/api/v1/portfolios' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Awa Diallo",
  "locale": "fr",
  "headline": "Développeuse Laravel & React",
  "summary": "J’accompagne les PME dans la création de leurs outils web.",
  "years_of_experience": 6
}'

Le choix du langage est mémorisé et appliqué à tous les exemples de la page.

Authentification et droits

Créez une clé dans le tableau de bord (API > Gérer) et envoyez-la dans l’en-tête Authorization. La clé n’est affichée qu’une fois à la création ; seule son empreinte est conservée. Créer ou révoquer une clé n’est possible que depuis l’interface.

  • Permissions par zone : à la création, vous choisissez pour chaque zone (compte, fichiers, portfolios, CV, entreprises, offres, candidatures) « aucun accès », « lecture » (GET) ou « lecture et écriture ». Une zone fermée répond 403 insufficient_permission.
  • Entreprises : une clé peut être limitée à certaines entreprises que vous gérez (les autres répondent 403 company_not_allowed). Le site d’une entreprise suit les droits de l’entreprise, pas ceux des portfolios : vous pouvez ouvrir une entreprise à une IA sans lui donner vos portfolios. GET /me/key liste les permissions de la clé.
  • L’accès dépend de votre formule (capacité api_access) ; une clé réelle exige aussi que le module API soit activé. Les clés de test fonctionnent toujours.
  • Hors API : création/révocation de clés, suppression du compte, mot de passe et double authentification, e-mail principal, abonnement et paiement, versement de parrainage.

Conventions

  • Succès : { "data": … }. Listes paginées : data, links, meta (?page=, ?per_page=, 100 maximum). Création : 201. Suppression : 204.
  • Les modifications (PATCH) sont partielles : envoyez seulement les champs à changer, les autres restent inchangés. Un objet est fusionné clé par clé, une liste est remplacée en entier. PUT reste accepté et remplace toute la ressource.
  • Identifiants : ULID (portfolios, CV, sections, entrées, candidatures) ou slug (entreprises, offres), comme dans les URL de l’application.
  • Images : téléversez d’abord le fichier (POST /files, multipart ou JSON base64) pour obtenir un identifiant, puis rattachez-le (image_media_ids d’une entrée, media_id d’un logo ou d’une image principale, photo_media_ids d’un CV). JPG, PNG, WebP, GIF et PDF, 5 Mo maximum, dans le quota de stockage de la formule ; indisponible avec une clé de test.
  • URL absolues : public_url pointe vers le sous-domaine du portfolio quand il en a réservé un, sinon vers /p/{slug}. Le nom affiché publiquement est le nom de marque s’il est renseigné.
  • Chaque opération montre une requête et une réponse réelles, capturées sur l’API elle-même (identifiants et dates d’exemple) ; les mêmes exemples figurent dans le document OpenAPI.

Mode test et bac à sable

Une clé mf_test_… exécute les vraies routes (validation, quotas, identifiants générés) puis annule tout : rien n’est enregistré et aucun e-mail n’est envoyé. Les lectures renvoient vos vraies données. Le téléchargement de fichiers et les opérations IA ne sont pas disponibles en mode test (409).

Le bac à sable du tableau de bord permet d’essayer chaque opération depuis l’interface, avec l’équivalent dans votre langage. Ouvrir le bac à sable

Assistants IA : MCP et skill

Serveur MCP HTTP (une clé API en Bearer), un outil par opération de l’API :

https://middlefolio.online/api/v1/mcp

Sans clé, via OAuth : dans Claude (Paramètres > Connecteurs > Ajouter un connecteur personnalisé) ou tout client MCP compatible OAuth, collez seulement cette adresse. Vous vous connectez à Middle Folio, choisissez le mode et les accès, et l’application apparaît dans API > Gérer, section « Applications connectées », d’où vous pouvez la déconnecter. La connexion se renouvelle seule (jeton de 30 jours, rafraîchi automatiquement).

Pour les clients stdio (Claude Desktop, Cursor…), un pont Node sans dépendance est fourni dans le dépôt (mcp/middle-folio-mcp.mjs) :

{
  "mcpServers": {
    "middle-folio": {
      "command": "node",
      "args": ["/chemin/vers/mcp/middle-folio-mcp.mjs"],
      "env": {
        "MIDDLE_FOLIO_API_KEY": "mf_test_…",
        "MIDDLE_FOLIO_URL": "https://middlefolio.online"
      }
    }
  }
}

Compte

Profil du titulaire de la clé.

GET/meread
curl 'https://middlefolio.online/api/v1/me' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000004",
    "first_name": "Awa",
    "last_name": "Diallo",
    "username": "awa-diallo",
    "email": "[email protected]",
    "email_verified": true,
    "secondary_email": null,
    "phone_number": null,
    "secondary_phone_number": null,
    "locale": null,
    "avatar": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Modifie le profil (l’e-mail principal et la photo restent réservés à l’interface web).

PATCH/mewrite

Corps de la requête

first_namestringPrénom
last_namestringNom
usernamestringNom d’utilisateur unique
secondary_emailstringE-mail secondaire
phone_numberstringTéléphone
secondary_phone_numberstringSecond téléphone
curl -X PATCH 'https://middlefolio.online/api/v1/me' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "first_name": "Awa",
  "last_name": "Diallo",
  "phone_number": "+221 77 123 45 67"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000004",
    "first_name": "Awa",
    "last_name": "Diallo",
    "username": "awa-diallo",
    "email": "[email protected]",
    "email_verified": true,
    "secondary_email": null,
    "phone_number": "+221 77 123 45 67",
    "secondary_phone_number": null,
    "locale": null,
    "avatar": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Change la langue du compte (interface et e-mails).

PATCH/me/localewrite

Corps de la requête

locale *fr | enLangue
curl -X PATCH 'https://middlefolio.online/api/v1/me/locale' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "locale": "en"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000004",
    "first_name": "Awa",
    "last_name": "Diallo",
    "username": "awa-diallo",
    "email": "[email protected]",
    "email_verified": true,
    "secondary_email": null,
    "phone_number": "+221 77 123 45 67",
    "secondary_phone_number": null,
    "locale": "en",
    "avatar": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Définit la photo de profil (image de la bibliothèque, copiée vers la photo du compte).

PUT/me/photowrite

Indisponible avec une clé de test (409) : écrit un fichier.

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/me/photo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000021"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000004",
    "first_name": "Awa",
    "last_name": "Diallo",
    "username": "awa-diallo",
    "email": "[email protected]",
    "email_verified": true,
    "secondary_email": null,
    "phone_number": "+221 77 123 45 67",
    "secondary_phone_number": null,
    "locale": null,
    "avatar": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000022.png",
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Retire la photo de profil.

DELETE/me/photowrite

Indisponible avec une clé de test (409) : supprime un fichier.

curl -X DELETE 'https://middlefolio.online/api/v1/me/photo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Formule courante, capacités (quotas, droits) et usage du compte.

GET/me/planread
curl 'https://middlefolio.online/api/v1/me/plan' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "plan": {
      "key": "premium",
      "name": "Premium"
    },
    "capabilities": {
      "max_portfolios": 10,
      "max_cvs": 20,
      "max_cv_downloads_per_month": null,
      "max_letter_downloads_per_month": null,
      "max_companies": 5,
      "max_sections_per_portfolio": null,
      "max_entries_per_section": null,
      "max_cv_sections": null,
      "max_cv_entries_per_section": null,
      "custom_branding": true,
      "custom_document_branding": true,
      "custom_theme": true,
      "premium_themes": true,
      "contact_form": true,
      "location_info": true,
      "portfolio_site": true,
      "company_site": true,
      "analytics_tier": "advanced",
      "company_analytics_tier": "advanced",
      "job_matching": true,
      "job_matching_ai": true,
      "company_ats": true,
      "company_ats_ai": true,
      "api_access": true
    },
    "usage": {
      "portfolios_count": 0,
      "cvs_count": 0,
      "companies_count": 0,
      "storage_used_bytes": 0
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Permissions de la clé utilisée : niveau par zone et entreprises autorisées.

GET/me/keyread

Utile à un assistant IA pour savoir ce qu’il peut faire avant d’agir. Ne demande aucune permission particulière.

curl 'https://middlefolio.online/api/v1/me/key' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "name": "Test",
    "mode": "live",
    "permissions": {
      "account": "write",
      "files": "write",
      "portfolios": "write",
      "cvs": "write",
      "companies": "write",
      "offers": "write",
      "applications": "write"
    },
    "companies": "all",
    "expires_at": null
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Code et lien de parrainage, nombre de filleuls (lecture seule).

GET/me/referralread
curl 'https://middlefolio.online/api/v1/me/referral' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "code": "UPHWF6FC",
    "link": "https://middlefolio.online/register?ref=UPHWF6FC",
    "is_eligible": false,
    "referrals_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Fichiers

Bibliothèque de fichiers : fournit les identifiants pour les champs *_media_ids et media_id.

GET/filesread

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
curl 'https://middlefolio.online/api/v1/files' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000017",
      "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000018.png",
      "position": null,
      "alt_text": null,
      "original_filename": "logo.png",
      "mime_type": "image/png",
      "size": 106,
      "collection": null,
      "is_attached": false,
      "created_at": "2026-09-15T09:30:00+00:00"
    },
    {
      "id": "01j9z000000000000000000019",
      "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000020.png",
      "position": null,
      "alt_text": null,
      "original_filename": "couverture.png",
      "mime_type": "image/png",
      "size": 106,
      "collection": null,
      "is_attached": false,
      "created_at": "2026-09-15T09:30:00+00:00"
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/files?page=1",
    "last": "https://middlefolio.online/api/v1/files?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/files?page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/files",
    "per_page": 25,
    "to": 9,
    "total": 9
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Téléverse une image (jpg, png, webp, gif) ou un PDF dans la bibliothèque et renvoie son identifiant.

POST/fileswrite

Deux formes : multipart/form-data (champ `file`, `name` facultatif) ou JSON (`content_base64` + `filename`, pour les clients sans multipart comme MCP). Taille maximale 5 Mo, quota de stockage de la formule. Rattachez ensuite le fichier avec image_media_ids, media_id, photo_media_ids… Indisponible avec une clé de test (409) : un fichier ne peut pas être annulé.

Corps de la requête

content_base64stringContenu du fichier encodé en base64 (alternative à `file` en multipart)
filenamestringNom du fichier avec son extension (requis avec content_base64)
namestringNom affiché dans la bibliothèque (défaut : le nom du fichier)
curl -X POST 'https://middlefolio.online/api/v1/files' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "content_base64": "iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAIAAAADnC86AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAHElEQVRYhe3BAQ0AAADCoPdPbQ43oAAAAADg3wAS6AABuHYUGQAAAABJRU5ErkJggg==",
  "filename": "logo.png"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000017",
    "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000018.png",
    "position": null,
    "alt_text": null,
    "original_filename": "logo.png",
    "mime_type": "image/png",
    "size": 106,
    "collection": null,
    "is_attached": false,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Supprime définitivement un fichier de la bibliothèque (et tous ses rattachements).

DELETE/files/{media}write

Indisponible avec une clé de test (409).

Chemin

media *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/files/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Référentiels

Catégories de l’annuaire, arbre aplati (parent_id, depth) : identifiants pour categories (portfolio) et category_ids (entreprise, offre).

GET/categoriesread

Permis à toute clé, quelles que soient ses zones.

curl 'https://middlefolio.online/api/v1/categories' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000001",
      "name": "Technologies",
      "slug": "technologies",
      "parent_id": null,
      "depth": 0
    },
    {
      "id": "01j9z000000000000000000002",
      "name": "Développement web",
      "slug": "developpement-web",
      "parent_id": "01j9z000000000000000000001",
      "depth": 1
    }
  ]
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Bibliothèque d’icônes utilisable : icônes globales et les vôtres, identifiants pour icon_id d’une entrée de portfolio.

GET/portfolio-iconsread

Permis à toute clé, quelles que soient ses zones.

curl 'https://middlefolio.online/api/v1/portfolio-icons' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000028",
      "name": "Laravel",
      "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000029.png",
      "is_global": false
    }
  ]
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Ajoute une icône personnalisée à votre bibliothèque (50 max par compte).

POST/portfolio-iconswrite

Corps de la requête

name *stringNom de l’icône (100 car. max)
icon_media_ids *string[]Un identifiant d’image de la bibliothèque (POST /files)
curl -X POST 'https://middlefolio.online/api/v1/portfolio-icons' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Laravel",
  "icon_media_ids": [
    "01j9z000000000000000000030"
  ]
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000028",
    "name": "Laravel",
    "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000029.png",
    "is_global": false
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Supprime une de vos icônes personnalisées (les entrées qui l’utilisent la perdent).

DELETE/portfolio-icons/{icon}write

Chemin

icon *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolio-icons/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Portfolios

Liste vos portfolios personnels.

GET/portfoliosread

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
curl 'https://middlefolio.online/api/v1/portfolios' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000037",
      "name": "Awa Diallo",
      "slug": "awa-diallo",
      "public_url": "https://middlefolio.online/p/awa-diallo",
      "brand_name": null,
      "headline": "Développeuse Laravel & React",
      "summary": "J’accompagne les PME dans la création de leurs outils web.",
      "years_of_experience": 6,
      "clients_count": null,
      "projects_count": null,
      "cv_url": null,
      "logo_url": null,
      "favicon_url": null,
      "hero_image": null,
      "is_activated": true,
      "is_published": false
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/portfolios?page=1",
    "last": "https://middlefolio.online/api/v1/portfolios?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/portfolios?page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/portfolios",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Crée un portfolio avec ses sections par défaut (quota du plan appliqué).

POST/portfolioswrite

Corps de la requête

name *stringNom (source du lien public)
locale *fr | enLangue du site
headlinestringAccroche
summarystringPrésentation
years_of_experienceintegerAnnées d’expérience
clients_countintegerNombre de clients
projects_countintegerNombre de projets
cv_media_idsstring[]Un PDF de la bibliothèque
cv_idstringCV à copier en portfolio (sections, couleur, liens, photo) ; name et locale sont alors repris du CV si absents
curl -X POST 'https://middlefolio.online/api/v1/portfolios' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Awa Diallo",
  "locale": "fr",
  "headline": "Développeuse Laravel & React",
  "summary": "J’accompagne les PME dans la création de leurs outils web.",
  "years_of_experience": 6
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000037",
    "name": "Awa Diallo",
    "slug": "awa-diallo",
    "public_url": "https://middlefolio.online/p/awa-diallo",
    "brand_name": null,
    "headline": "Développeuse Laravel & React",
    "summary": "J’accompagne les PME dans la création de leurs outils web.",
    "years_of_experience": 6,
    "clients_count": null,
    "projects_count": null,
    "cv_url": null,
    "logo_url": null,
    "favicon_url": null,
    "hero_image": null,
    "is_activated": true,
    "is_published": false,
    "sections": [
      {
        "id": "01j9z000000000000000000039",
        "type": "description",
        "title": "Description",
        "position": 1,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000040",
        "type": "journey",
        "title": "Parcours",
        "position": 2,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Portfolio complet : sections et entrées.

GET/portfolios/{portfolio}read

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000037",
    "name": "Awa Diallo",
    "slug": "awa-diallo",
    "public_url": "https://middlefolio.online/p/awa-diallo",
    "brand_name": null,
    "headline": "Développeuse Laravel & React",
    "summary": "J’accompagne les PME dans la création de leurs outils web.",
    "years_of_experience": 6,
    "clients_count": 25,
    "projects_count": 40,
    "cv_url": null,
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000018.png",
    "favicon_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000006.png",
    "hero_image": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000020.png",
    "is_activated": true,
    "is_published": false,
    "sections": [
      {
        "id": "01j9z000000000000000000039",
        "type": "description",
        "title": "Description",
        "position": 1,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000040",
        "type": "journey",
        "title": "Parcours",
        "position": 2,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie les informations générales du portfolio.

PATCH/portfolios/{portfolio}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

namestringNom
headlinestringAccroche
summarystringPrésentation
years_of_experienceintegerAnnées d’expérience
clients_countintegerNombre de clients
projects_countintegerNombre de projets
cv_media_idsstring[]Un PDF de la bibliothèque
curl -X PATCH 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Awa Diallo",
  "headline": "Développeuse Laravel & React",
  "summary": "J’accompagne les PME dans la création de leurs outils web.",
  "years_of_experience": 6,
  "clients_count": 25,
  "projects_count": 40
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000037",
    "name": "Awa Diallo",
    "slug": "awa-diallo",
    "public_url": "https://middlefolio.online/p/awa-diallo",
    "brand_name": null,
    "headline": "Développeuse Laravel & React",
    "summary": "J’accompagne les PME dans la création de leurs outils web.",
    "years_of_experience": 6,
    "clients_count": 25,
    "projects_count": 40,
    "cv_url": null,
    "logo_url": null,
    "favicon_url": null,
    "hero_image": null,
    "is_activated": true,
    "is_published": false,
    "sections": [
      {
        "id": "01j9z000000000000000000039",
        "type": "description",
        "title": "Description",
        "position": 1,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000040",
        "type": "journey",
        "title": "Parcours",
        "position": 2,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Duplique un portfolio personnel : contenu, thème, fichiers et réglages (quota du plan appliqué).

POST/portfolios/{portfolio}/duplicatewrite

La copie reçoit un nouvel identifiant et un nouveau slug, naît non publiée et sans sous-domaine. Un site d’entreprise se duplique avec son entreprise (POST /companies/{company}/duplicate).

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

namestringNom de la copie (défaut : « <nom> (copie) »)
curl -X POST 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/duplicate' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Awa Diallo — version anglaise"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000034",
    "name": "Awa Diallo — version anglaise",
    "slug": "awa-diallo-version-anglaise",
    "public_url": "https://middlefolio.online/p/awa-diallo-version-anglaise",
    "brand_name": null,
    "headline": "Développeuse Laravel & React",
    "summary": "J’accompagne les PME dans la création de leurs outils web.",
    "years_of_experience": 6,
    "clients_count": 25,
    "projects_count": 40,
    "cv_url": null,
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000018.png",
    "favicon_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000006.png",
    "hero_image": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000020.png",
    "is_activated": true,
    "is_published": false,
    "sections": [
      {
        "id": "01j9z000000000000000000035",
        "type": "description",
        "title": "Description",
        "position": 1,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000036",
        "type": "journey",
        "title": "Parcours",
        "position": 2,
        "is_visible": true,
        "show_on_home": true,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Supprime le portfolio (suppression logique, non restaurable depuis l’API).

DELETE/portfolios/{portfolio}write

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Définit le logo (image de la bibliothèque).

PUT/portfolios/{portfolio}/logowrite

Indisponible sur un site d’entreprise (403, code company_site) : il reprend le logo de l’entreprise, à changer avec companies_logo_update.

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/logo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000017"
}'

Réponses

200Succès
{
  "data": {
    "media_id": "01j9z000000000000000000017",
    "collection": "logo"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire le logo.

DELETE/portfolios/{portfolio}/logowrite

Indisponible sur un site d’entreprise (403, code company_site).

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/logo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Définit la favicon (image de la bibliothèque), recompressée si elle dépasse le poids maximal.

PUT/portfolios/{portfolio}/faviconwrite

Une image trop lourde est réduite : une copie compressée est ajoutée à la bibliothèque, et la réponse donne l’identifiant réellement rattaché. Indisponible sur un site d’entreprise (403, code company_site) : il reprend la favicon de l’entreprise, à changer avec companies_favicon_update.

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/favicon' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000007"
}'

Réponses

200Succès
{
  "data": {
    "media_id": "01j9z000000000000000000007",
    "collection": "favicon"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire la favicon (le site reprend celle de la plateforme).

DELETE/portfolios/{portfolio}/faviconwrite

Indisponible sur un site d’entreprise (403, code company_site).

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/favicon' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Définit l’image principale (image de la bibliothèque).

PUT/portfolios/{portfolio}/hero-imagewrite

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/hero-image' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000019"
}'

Réponses

200Succès
{
  "data": {
    "media_id": "01j9z000000000000000000019",
    "collection": "hero_image"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire l’image principale.

DELETE/portfolios/{portfolio}/hero-imagewrite

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/hero-image' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Contenu du portfolio

Ajoute une section en fin de liste.

POST/portfolios/{portfolio}/sectionswrite

Types : description (un texte), journey (parcours, formation), skills (compétences avec niveau), projects (projets, galerie et contenu riche), list (liste simple), services, testimonials, clients (logos), blog, keyvalues (clé/valeur), faq (question/réponse), gallery (une entrée = une image + légende facultative), video (une entrée = lien YouTube ou Vimeo + miniature facultative). show_on_home: false détache la section sur sa page dédiée ; une section de liste très longue obtient aussi sa page dédiée.

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

type *description | journey | skills | projects | list | services | testimonials | clients | blog | keyvalues | faq | gallery | videoType de section
titlestringTitre (défaut selon le type)
show_on_homebooleanAfficher sur l’accueil (défaut vrai ; faux = la section a sa propre page publique)
curl -X POST 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/sections' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "faq",
  "title": "Questions fréquentes"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000041",
    "type": "faq",
    "title": "Questions fréquentes",
    "position": 5,
    "is_visible": true,
    "show_on_home": true,
    "entries": []
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Réordonne les sections.

PUT/portfolios/{portfolio}/sections/reorderwrite

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

section_ids *string[]Tous les identifiants de sections, dans le nouvel ordre
curl -X PUT 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/sections/reorder' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "section_ids": [
    "01j9z000000000000000000039",
    "01j9z000000000000000000040"
  ]
}'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000039",
      "type": "description",
      "title": "Description",
      "position": 1,
      "is_visible": true,
      "show_on_home": true,
      "entries": []
    },
    {
      "id": "01j9z000000000000000000040",
      "type": "journey",
      "title": "Parcours",
      "position": 2,
      "is_visible": true,
      "show_on_home": true,
      "entries": []
    }
  ]
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Insère une section juste après {section}.

POST/portfolio-sections/{section}/insert-afterwrite

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

type *description | journey | skills | projects | list | services | testimonials | clients | blog | keyvalues | faq | gallery | videoType
titlestringTitre
show_on_homebooleanAfficher sur l’accueil
curl -X POST 'https://middlefolio.online/api/v1/portfolio-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/insert-after' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "services",
  "title": "Services"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000032",
    "type": "services",
    "title": "Prestations",
    "position": 5,
    "is_visible": true,
    "show_on_home": true,
    "entries": []
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Modifie titre, visibilité et mode d’affichage d’une section.

PATCH/portfolio-sections/{section}write

show_on_home: false = page dédiée (la section quitte l’accueil) ; true = intégrée à l’accueil. Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringTitre
is_visiblebooleanVisible
show_on_homebooleanAfficher sur l’accueil
curl -X PATCH 'https://middlefolio.online/api/v1/portfolio-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Réalisations",
  "is_visible": true,
  "show_on_home": true
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000033",
    "type": "projects",
    "title": "Réalisations",
    "position": 4,
    "is_visible": true,
    "show_on_home": true,
    "entries": [
      {
        "id": "01j9z000000000000000000031",
        "title": "Application de réservation",
        "subtitle": null,
        "description": "Prise de rendez-vous en ligne pour un réseau de cliniques.",
        "content": null,
        "start_date": null,
        "end_date": null,
        "data": [],
        "position": 1,
        "icon_id": null,
        "icon": null,
        "image": null,
        "gallery": []
      },
      {
        "id": "01j9z000000000000000000023",
        "title": "Boutique en ligne Sahel Craft",
        "subtitle": "E-commerce",
        "description": "Catalogue, paiement mobile et suivi des commandes.",
        "content": null,
        "start_date": "2025-03-01",
        "end_date": "2025-09-30",
        "data": {
          "year": 2025,
          "tags": [
            "Laravel",
            "Stripe"
          ]
        },
        "position": 2,
        "icon_id": null,
        "icon": null,
        "image": {
          "id": "01j9z000000000000000000024",
          "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000025.png",
          "position": 1,
          "alt_text": null,
          "original_filename": "projet-boutique.png",
          "mime_type": "image/png",
          "size": 106,
          "collection": "image",
          "is_attached": true,
          "created_at": "2026-09-15T09:30:00+00:00"
        },
        "gallery": [
          {
            "id": "01j9z000000000000000000026",
            "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000027.png",
            "position": 1,
            "alt_text": null,
            "original_filename": "galerie-1.png",
            "mime_type": "image/png",
            "size": 106,
            "collection": "gallery",
            "is_attached": true,
            "created_at": "2026-09-15T09:30:00+00:00"
          }
        ]
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Supprime une section et ses entrées.

DELETE/portfolio-sections/{section}write

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolio-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Ajoute une entrée à une section (limite du plan appliquée).

POST/portfolio-sections/{section}/entrieswrite

Champs requis selon le type de section : titre (sauf description, gallery, video), subtitle pour keyvalues, description pour faq, data.url pour video. Une entrée de galerie porte son image dans image_media_ids.

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringTitre (requis sauf pour description, galerie et vidéo)
subtitlestringSous-titre (valeur pour une section clés-valeurs)
descriptionstringTexte (réponse pour une FAQ)
contentstringContenu long en HTML (assaini côté serveur, 50 000 car. max ; sections « projets » uniquement)
start_datestringDate de début (AAAA-MM-JJ)
end_datestringDate de fin (AAAA-MM-JJ, ≥ début)
dataobjectChamps propres au type : rating (0-100 pour les compétences, 0-5 pour les témoignages), year, project_types[], tags[], url (liens ; obligatoire et limité à YouTube/Vimeo pour une vidéo)
icon_idstringIdentifiant d’icône de la bibliothèque (GET /portfolio-icons)
image_media_idsstring[]Un identifiant de fichier de la bibliothèque (voir POST /files) : image de l’entrée, image d’une galerie, miniature d’une vidéo
gallery_media_idsstring[]Identifiants de fichiers qui s’ajoutent à la galerie (sections « projets » uniquement ; retrait : DELETE …/media/{media})
curl -X POST 'https://middlefolio.online/api/v1/portfolio-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/entries' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Boutique en ligne Sahel Craft",
  "subtitle": "E-commerce",
  "description": "Catalogue, paiement mobile et suivi des commandes.",
  "start_date": "2025-03-01",
  "end_date": "2025-09-30",
  "data": {
    "year": 2025,
    "tags": [
      "Laravel",
      "Stripe"
    ]
  },
  "image_media_ids": [
    "01j9z000000000000000000024"
  ],
  "gallery_media_ids": [
    "01j9z000000000000000000026"
  ]
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000023",
    "title": "Boutique en ligne Sahel Craft",
    "subtitle": "E-commerce",
    "description": "Catalogue, paiement mobile et suivi des commandes.",
    "content": null,
    "start_date": "2025-03-01",
    "end_date": "2025-09-30",
    "data": {
      "year": 2025,
      "tags": [
        "Laravel",
        "Stripe"
      ]
    },
    "position": 1,
    "icon_id": null,
    "icon": null,
    "image": {
      "id": "01j9z000000000000000000024",
      "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000025.png",
      "position": 1,
      "alt_text": null,
      "original_filename": "projet-boutique.png",
      "mime_type": "image/png",
      "size": 106,
      "collection": "image",
      "is_attached": true,
      "created_at": "2026-09-15T09:30:00+00:00"
    },
    "gallery": [
      {
        "id": "01j9z000000000000000000026",
        "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000027.png",
        "position": 1,
        "alt_text": null,
        "original_filename": "galerie-1.png",
        "mime_type": "image/png",
        "size": 106,
        "collection": "gallery",
        "is_attached": true,
        "created_at": "2026-09-15T09:30:00+00:00"
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Réordonne les entrées d’une section.

PUT/portfolio-sections/{section}/entries/reorderwrite

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

entry_ids *string[]Identifiants d’entrées dans le nouvel ordre
curl -X PUT 'https://middlefolio.online/api/v1/portfolio-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/entries/reorder' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "entry_ids": [
    "01j9z000000000000000000031",
    "01j9z000000000000000000023"
  ]
}'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000031",
      "title": "Application de réservation",
      "subtitle": null,
      "description": "Prise de rendez-vous en ligne pour un réseau de cliniques.",
      "content": null,
      "start_date": null,
      "end_date": null,
      "data": [],
      "position": 1,
      "icon_id": null,
      "icon": null,
      "image": null,
      "gallery": []
    },
    {
      "id": "01j9z000000000000000000023",
      "title": "Boutique en ligne Sahel Craft",
      "subtitle": "E-commerce",
      "description": "Catalogue, paiement mobile et suivi des commandes.",
      "content": null,
      "start_date": "2025-03-01",
      "end_date": "2025-09-30",
      "data": {
        "year": 2025,
        "tags": [
          "Laravel",
          "Stripe"
        ]
      },
      "position": 2,
      "icon_id": null,
      "icon": null,
      "image": {
        "id": "01j9z000000000000000000024",
        "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000025.png",
        "position": 1,
        "alt_text": null,
        "original_filename": "projet-boutique.png",
        "mime_type": "image/png",
        "size": 106,
        "collection": "image",
        "is_attached": true,
        "created_at": "2026-09-15T09:30:00+00:00"
      },
      "gallery": [
        {
          "id": "01j9z000000000000000000026",
          "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000027.png",
          "position": 1,
          "alt_text": null,
          "original_filename": "galerie-1.png",
          "mime_type": "image/png",
          "size": 106,
          "collection": "gallery",
          "is_attached": true,
          "created_at": "2026-09-15T09:30:00+00:00"
        }
      ]
    }
  ]
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Modifie une entrée.

PATCH/portfolio-entries/{entry}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

entry *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringTitre (requis sauf pour description, galerie et vidéo)
subtitlestringSous-titre (valeur pour une section clés-valeurs)
descriptionstringTexte (réponse pour une FAQ)
contentstringContenu long en HTML (assaini côté serveur, 50 000 car. max ; sections « projets » uniquement)
start_datestringDate de début (AAAA-MM-JJ)
end_datestringDate de fin (AAAA-MM-JJ, ≥ début)
dataobjectChamps propres au type : rating (0-100 pour les compétences, 0-5 pour les témoignages), year, project_types[], tags[], url (liens ; obligatoire et limité à YouTube/Vimeo pour une vidéo)
icon_idstringIdentifiant d’icône de la bibliothèque (GET /portfolio-icons)
image_media_idsstring[]Un identifiant de fichier de la bibliothèque (voir POST /files) : image de l’entrée, image d’une galerie, miniature d’une vidéo
gallery_media_idsstring[]Identifiants de fichiers qui s’ajoutent à la galerie (sections « projets » uniquement ; retrait : DELETE …/media/{media})
curl -X PATCH 'https://middlefolio.online/api/v1/portfolio-entries/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Boutique en ligne Sahel Craft",
  "subtitle": "E-commerce",
  "description": "Catalogue, paiement mobile et suivi des commandes.",
  "data": {
    "year": 2025,
    "tags": [
      "Laravel",
      "Stripe"
    ]
  }
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000023",
    "title": "Boutique en ligne Sahel Craft",
    "subtitle": "E-commerce",
    "description": "Catalogue, paiement mobile et suivi des commandes.",
    "content": null,
    "start_date": "2025-03-01",
    "end_date": "2025-09-30",
    "data": {
      "year": 2025,
      "tags": [
        "Laravel",
        "Stripe"
      ]
    },
    "position": 1,
    "icon_id": null,
    "icon": null,
    "image": {
      "id": "01j9z000000000000000000024",
      "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000025.png",
      "position": 1,
      "alt_text": null,
      "original_filename": "projet-boutique.png",
      "mime_type": "image/png",
      "size": 106,
      "collection": "image",
      "is_attached": true,
      "created_at": "2026-09-15T09:30:00+00:00"
    },
    "gallery": [
      {
        "id": "01j9z000000000000000000026",
        "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000027.png",
        "position": 1,
        "alt_text": null,
        "original_filename": "galerie-1.png",
        "mime_type": "image/png",
        "size": 106,
        "collection": "gallery",
        "is_attached": true,
        "created_at": "2026-09-15T09:30:00+00:00"
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Supprime une entrée.

DELETE/portfolio-entries/{entry}write

Chemin

entry *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolio-entries/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Retire un média d’une entrée (le fichier reste dans la bibliothèque).

DELETE/portfolio-entries/{entry}/media/{media}write

Chemin

entry *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
media *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/portfolio-entries/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/media/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Thème et publication

Thème du portfolio (couleurs, polices, gabarit).

GET/portfolios/{portfolio}/themeread

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/theme' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000042",
    "color_primary": "#4f39f6",
    "color_secondary": "#432dd7",
    "color_text": "#0a0a0a",
    "color_background": "#ffffff",
    "use_gradients": 1,
    "invert_colors": null,
    "heading_font": "Inter",
    "body_font": "Inter",
    "badge_font": "Inter",
    "icon_style": "outline",
    "icon_set": "lucide",
    "radius_scale": "slight",
    "spacing_scale": "comfortable",
    "typography": {
      "heading_1": {
        "size": "xl",
        "weight": "bold"
      },
      "heading_2": {
        "size": "lg",
        "weight": "bold"
      },
      "heading_3": {
        "size": "md",
        "weight": "medium"
      },
      "body": {
        "size": "md",
        "weight": "regular"
      },
      "badge": {
        "size": "sm",
        "weight": "medium"
      }
    },
    "theme_template_id": "01j9z000000000000000000043",
    "theme_template": {
      "id": "01j9z000000000000000000043",
      "name": "Essentiel",
      "slug": "essentiel",
      "tier": "free",
      "description": "Une page épurée, portrait et projets en grille.",
      "preview_url": null
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie le thème (couleurs, polices, échelles, gabarit).

PATCH/portfolios/{portfolio}/themewrite

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

color_primarystringCouleur principale (#RRGGBB)
color_secondarystringCouleur secondaire
color_textstringCouleur du texte
color_backgroundstringCouleur de fond
use_gradientsbooleanDégradés
invert_colorsbooleanInverser l’usage des couleurs par le gabarit
heading_fontstringPolice des titres
body_fontstringPolice du texte
badge_fontstringPolice des badges
icon_stylestringStyle d’icônes
icon_setstringJeu d’icônes
radius_scalestringÉchelle des arrondis
spacing_scalestringÉchelle des espacements
typographyobjectTailles et graisses par niveau : { niveau: { size, weight } }
theme_template_idstringIdentifiant du gabarit (voir …/theme/templates)
curl -X PATCH 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/theme' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "color_primary": "#bf6b15",
  "color_secondary": "#432dd7",
  "color_text": "#0a0a0a",
  "color_background": "#ffffff",
  "use_gradients": 1,
  "invert_colors": null,
  "heading_font": "Inter",
  "body_font": "Inter",
  "badge_font": "Inter",
  "icon_style": "outline",
  "icon_set": "lucide",
  "radius_scale": "slight",
  "spacing_scale": "comfortable",
  "typography": {
    "heading_1": {
      "size": "xl",
      "weight": "bold"
    },
    "heading_2": {
      "size": "lg",
      "weight": "bold"
    },
    "heading_3": {
      "size": "md",
      "weight": "medium"
    },
    "body": {
      "size": "md",
      "weight": "regular"
    },
    "badge": {
      "size": "sm",
      "weight": "medium"
    }
  },
  "theme_template_id": "01j9z000000000000000000043"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000042",
    "color_primary": "#bf6b15",
    "color_secondary": "#432dd7",
    "color_text": "#0a0a0a",
    "color_background": "#ffffff",
    "use_gradients": 1,
    "invert_colors": null,
    "heading_font": "Inter",
    "body_font": "Inter",
    "badge_font": "Inter",
    "icon_style": "outline",
    "icon_set": "lucide",
    "radius_scale": "slight",
    "spacing_scale": "comfortable",
    "typography": {
      "heading_1": {
        "size": "xl",
        "weight": "bold"
      },
      "heading_2": {
        "size": "lg",
        "weight": "bold"
      },
      "heading_3": {
        "size": "md",
        "weight": "medium"
      },
      "body": {
        "size": "md",
        "weight": "regular"
      },
      "badge": {
        "size": "sm",
        "weight": "medium"
      }
    },
    "theme_template_id": "01j9z000000000000000000043",
    "theme_template": {
      "id": "01j9z000000000000000000043",
      "name": "Essentiel",
      "slug": "essentiel",
      "tier": "free",
      "description": "Une page épurée, portrait et projets en grille.",
      "preview_url": null
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Gabarits proposés, avec leur verrouillage selon la formule (allowed).

GET/portfolios/{portfolio}/theme/templatesread

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/theme/templates' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000043",
      "name": "Essentiel",
      "slug": "essentiel",
      "description": "Une page épurée, portrait et projets en grille.",
      "preview_url": null,
      "tier": "free",
      "image_specs": {
        "hero": {
          "ratio": "1:1",
          "min_width": 1000
        },
        "description": {
          "ratio": "4:3",
          "min_width": 1000
        },
        "journey": {
          "ratio": "1:1",
          "min_width": 400
        },
        "projects": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "projects_gallery": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "testimonials": {
          "ratio": "1:1",
          "min_width": 400
        },
        "blog": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "gallery": {
          "ratio": "16:10",
          "min_width": 1200
        },
        "video": {
          "ratio": "16:9",
          "min_width": 1200
        }
      },
      "allowed": true,
      "exclusive": false
    },
    {
      "id": "01j9z000000000000000000044",
      "name": "Vitrine",
      "slug": "vitrine",
      "description": "Un profil complet : chiffres clés, services, projets, avis et blog.",
      "preview_url": null,
      "tier": "pro",
      "image_specs": {
        "hero": {
          "ratio": "1:1",
          "min_width": 1000
        },
        "description": {
          "ratio": "4:3",
          "min_width": 1000
        },
        "journey": {
          "ratio": "1:1",
          "min_width": 400
        },
        "projects": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "projects_gallery": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "testimonials": {
          "ratio": "1:1",
          "min_width": 400
        },
        "blog": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "gallery": {
          "ratio": "16:9",
          "min_width": 1200
        },
        "video": {
          "ratio": "16:9",
          "min_width": 1200
        }
      },
      "allowed": true,
      "exclusive": false
    }
  ],
  "meta": {
    "selected_template_id": "01j9z000000000000000000043"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Change uniquement le gabarit.

PUT/portfolios/{portfolio}/theme/templateswrite

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

theme_template_id *stringIdentifiant du gabarit
curl -X PUT 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/theme/templates' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "theme_template_id": "01j9z000000000000000000043"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000042",
    "color_primary": "#bf6b15",
    "color_secondary": "#432dd7",
    "color_text": "#0a0a0a",
    "color_background": "#ffffff",
    "use_gradients": 1,
    "invert_colors": null,
    "heading_font": "Inter",
    "body_font": "Inter",
    "badge_font": "Inter",
    "icon_style": "outline",
    "icon_set": "lucide",
    "radius_scale": "slight",
    "spacing_scale": "comfortable",
    "typography": {
      "heading_1": {
        "size": "xl",
        "weight": "bold"
      },
      "heading_2": {
        "size": "lg",
        "weight": "bold"
      },
      "heading_3": {
        "size": "md",
        "weight": "medium"
      },
      "body": {
        "size": "md",
        "weight": "regular"
      },
      "badge": {
        "size": "sm",
        "weight": "medium"
      }
    },
    "theme_template_id": "01j9z000000000000000000043",
    "theme_template": {
      "id": "01j9z000000000000000000043",
      "name": "Essentiel",
      "slug": "essentiel",
      "tier": "free",
      "description": "Une page épurée, portrait et projets en grille.",
      "preview_url": null
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Réglages de publication et état (publié ou non).

GET/portfolios/{portfolio}/publishingread

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/publishing' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000038",
    "locale": "fr",
    "is_published": false,
    "is_marketplace_listed": true,
    "published_at": null,
    "has_contact_form": false,
    "contact_info": null,
    "location_info": null,
    "opening_hours": null,
    "subdomain": null,
    "cta_label": null,
    "cta_url": null,
    "social_links": []
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie les réglages de publication.

PATCH/portfolios/{portfolio}/publishingwrite

Horaires d’ouverture en texte libre, une ligne par plage de jours, affichés tels quels : "Lundi – vendredi : 9 h – 18 h\nSamedi : 9 h – 13 h". Réseaux : un objet { plateforme: url } (plateformes : facebook, instagram, tiktok, whatsapp, x, youtube, linkedin) ; une URL vide retire le réseau, un réseau absent reste inchangé. Site d’entreprise : is_marketplace_listed, categories, contact_info et location_info (sauf map_url) sont ignorés, car repris de la fiche de l’entreprise (companies_update). Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

localefr | enLangue du site
has_contact_formbooleanFormulaire de contact (selon la formule)
is_marketplace_listedbooleanVisible dans l’annuaire : préférence acceptée même avant publication, effective une fois le portfolio publié (ignoré pour un site d’entreprise)
categoriesstring[]Identifiants de catégories de l’annuaire (6 max, GET /categories ; ignoré pour un site d’entreprise)
contact_infoobjectCoordonnées (ignoré pour un site d’entreprise)
location_infoobjectLocalisation, formule Pro et plus (seul map_url compte pour un site d’entreprise)
opening_hoursstringHoraires d’ouverture en texte libre (1000 car. max ; vide = bloc masqué)
subdomainstringSous-domaine réservé
cta_labelstringLibellé du bouton d’action
cta_urlstringURL du bouton d’action
social_linksobjectRéseaux : { plateforme: url }
curl -X PATCH 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/publishing' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "locale": "fr",
  "has_contact_form": true,
  "is_marketplace_listed": false,
  "contact_info": {
    "email": "[email protected]",
    "phone": "+221 77 123 45 67"
  },
  "location_info": {
    "country": "Sénégal",
    "city": "Dakar"
  },
  "opening_hours": "Lundi – vendredi : 9 h – 18 h\nSamedi : 9 h – 13 h, sur rendez-vous\nFermé le dimanche",
  "cta_label": "Demander un devis",
  "cta_url": "https://awadiallo.dev/devis",
  "social_links": {
    "linkedin": "https://www.linkedin.com/in/awadiallo",
    "instagram": "https://www.instagram.com/awadiallo.dev"
  }
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000038",
    "locale": "fr",
    "is_published": false,
    "is_marketplace_listed": false,
    "published_at": null,
    "has_contact_form": true,
    "contact_info": {
      "email": "[email protected]",
      "phone": "+221 77 123 45 67"
    },
    "location_info": {
      "city": "Dakar",
      "country_code": "SN",
      "country": "Sénégal"
    },
    "opening_hours": "Lundi – vendredi : 9 h – 18 h\nSamedi : 9 h – 13 h, sur rendez-vous\nFermé le dimanche",
    "subdomain": null,
    "cta_label": "Demander un devis",
    "cta_url": "https://awadiallo.dev/devis",
    "social_links": {
      "instagram": "https://www.instagram.com/awadiallo.dev",
      "linkedin": "https://www.linkedin.com/in/awadiallo"
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Publie le portfolio (le plan doit inclure un site public).

POST/portfolios/{portfolio}/publishing/publishwrite

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X POST 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/publishing/publish' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000038",
    "locale": "fr",
    "is_published": true,
    "is_marketplace_listed": false,
    "published_at": "2026-09-15T09:30:00+00:00",
    "has_contact_form": true,
    "contact_info": {
      "email": "[email protected]",
      "phone": "+221 77 123 45 67"
    },
    "location_info": {
      "city": "Dakar",
      "country_code": "SN",
      "country": "Sénégal"
    },
    "opening_hours": "Lundi – vendredi : 9 h – 18 h\nSamedi : 9 h – 13 h, sur rendez-vous\nFermé le dimanche",
    "subdomain": null,
    "cta_label": "Demander un devis",
    "cta_url": "https://awadiallo.dev/devis",
    "social_links": {
      "instagram": "https://www.instagram.com/awadiallo.dev",
      "linkedin": "https://www.linkedin.com/in/awadiallo"
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Dépublie le portfolio.

POST/portfolios/{portfolio}/publishing/unpublishwrite

Chemin

portfolio *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X POST 'https://middlefolio.online/api/v1/portfolios/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/publishing/unpublish' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000038",
    "locale": "fr",
    "is_published": false,
    "is_marketplace_listed": false,
    "published_at": "2026-09-15T09:30:00+00:00",
    "has_contact_form": true,
    "contact_info": {
      "email": "[email protected]",
      "phone": "+221 77 123 45 67"
    },
    "location_info": {
      "city": "Dakar",
      "country_code": "SN",
      "country": "Sénégal"
    },
    "opening_hours": "Lundi – vendredi : 9 h – 18 h\nSamedi : 9 h – 13 h, sur rendez-vous\nFermé le dimanche",
    "subdomain": null,
    "cta_label": "Demander un devis",
    "cta_url": "https://awadiallo.dev/devis",
    "social_links": {
      "instagram": "https://www.instagram.com/awadiallo.dev",
      "linkedin": "https://www.linkedin.com/in/awadiallo"
    }
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

CV

Liste vos CV.

GET/cvsread

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
curl 'https://middlefolio.online/api/v1/cvs' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000011",
      "name": "CV développeuse",
      "template": "design",
      "locale": "fr",
      "full_name": "Awa Diallo",
      "headline": null,
      "email": "[email protected]",
      "phone": "+221 77 123 45 67",
      "location": null,
      "website": null,
      "portfolio_url": null,
      "extra_info": [
        {
          "kind": "birth_date",
          "label": "Date de naissance",
          "value": "",
          "icon": "cake"
        },
        {
          "kind": "birth_place",
          "label": "Lieu de naissance",
          "value": "",
          "icon": "map-pin"
        }
      ],
      "summary": null,
      "accent_color": null,
      "panel_color": null,
      "font": "sans",
      "heading_font": null,
      "font_size": "md",
      "heading_size": "md",
      "spacing": "comfortable",
      "use_icons": null,
      "show_photo": true,
      "photo_shape": "round",
      "photo_url": null,
      "source_portfolio_name": null,
      "updated_at": "2026-09-15T09:30:00+00:00"
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/cvs?page=1",
    "last": "https://middlefolio.online/api/v1/cvs?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/cvs?page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/cvs",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Gabarits de CV proposés à ce compte.

GET/cv-templatesread
curl 'https://middlefolio.online/api/v1/cv-templates' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "slug": "ats",
      "name": "ATS",
      "description": "Une seule colonne, texte seul : lisible par les logiciels de recrutement.",
      "tier": "free",
      "position": 10,
      "preview_url": null,
      "layout": "single",
      "is_ats": true,
      "monochrome": true,
      "has_photo": false,
      "side": null,
      "mirror": null,
      "locked": false
    },
    {
      "slug": "ats-elegant",
      "name": "ATS élégant",
      "description": "Une colonne lisible par les ATS : en-tête centré, titres en empattement et couleur d’accent.",
      "tier": "pro",
      "position": 11,
      "preview_url": null,
      "layout": "single",
      "is_ats": true,
      "monochrome": false,
      "has_photo": false,
      "side": null,
      "mirror": null,
      "locked": false
    }
  ]
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Crée un CV vide ou copié depuis un portfolio (quota max_cvs).

POST/cvswrite

Corps de la requête

template *ats | ats-elegant | design | sidebar-left | sidebar-right | columns | exotic | canada | canada-modern | minimal | ribbon-left | ribbon-right | wave-left | wave-right | arch-left | arch-right | studio-left | studio-right | pastel-left | pastel-right | timeline-left | timeline-rightGabarit
namestringNom (requis hors copie)
localefr | enLangue (requise hors copie)
portfolio_idstringPortfolio à copier en CV
curl -X POST 'https://middlefolio.online/api/v1/cvs' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "CV développeuse",
  "locale": "fr",
  "template": "design"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "design",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": null,
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": null,
    "website": null,
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": null,
    "accent_color": null,
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": null,
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

CV complet : sections et entrées.

GET/cvs/{cv}read

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie identité et coordonnées du CV.

PATCH/cvs/{cv}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

namestringNom du CV
localefr | enLangue
full_namestringNom complet
headlinestringTitre
emailstringE-mail
phonestringTéléphone
locationstringLocalisation
websitestringSite web
portfolio_urlstringLien du portfolio
extra_infoobject[]Autres informations en texte libre (20 max, ordre conservé) : [{ kind, label, value, icon }] ; kind (facultatif) : birth_date|birth_place|nationality|marital_status|driving_license|po_box|linkedin|github|whatsapp|availability|mobility|id_number
summarystringRésumé
curl -X PATCH 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "CV développeuse",
  "locale": "fr",
  "full_name": "Awa Diallo",
  "headline": "Développeuse Laravel & React",
  "email": "[email protected]",
  "phone": "+221 77 123 45 67",
  "location": "Dakar, Sénégal",
  "website": "https://awadiallo.dev",
  "social_links": [
    {
      "label": "GitHub",
      "url": "https://github.com/awadiallo",
      "icon": "github"
    }
  ],
  "summary": "Six ans d’expérience en développement web."
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "design",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": null,
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": null,
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Modifie l’apparence du CV.

PATCH/cvs/{cv}/appearancewrite

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

fontsans | serif | mono | helvetica | times | courier | inter | poppins | space-grotesk | sora | dm-sans | manrope | outfit | plus-jakarta-sans | work-sans | montserrat | raleway | nunito | lato | roboto | open-sans | rubik | playfair-display | merriweather | lora | cormorant-garamond | libre-baskerville | fraunces | bitter | dm-serif-display | syne | unbounded | oswald | bebas-neue | anton | abril-fatface | archivo-black | jetbrains-mono | ibm-plex-mono | space-mono | caveat | pacifico | permanent-markerPolice
heading_fontsans | serif | mono | helvetica | times | courier | inter | poppins | space-grotesk | sora | dm-sans | manrope | outfit | plus-jakarta-sans | work-sans | montserrat | raleway | nunito | lato | roboto | open-sans | rubik | playfair-display | merriweather | lora | cormorant-garamond | libre-baskerville | fraunces | bitter | dm-serif-display | syne | unbounded | oswald | bebas-neue | anton | abril-fatface | archivo-black | jetbrains-mono | ibm-plex-mono | space-mono | caveat | pacifico | permanent-markerPolice des titres
font_sizesm | md | lgTaille du texte
heading_sizesm | md | lgTaille des titres
spacingcompact | comfortable | spaciousEspacement
show_photobooleanAfficher la photo
photo_shaperound | rounded | squareForme de la photo
accent_colorstringCouleur d’accent (#RRGGBB)
panel_colorstringCouleur du panneau
use_iconsbooleanIcônes (vide = selon le gabarit)
curl -X PATCH 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/appearance' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "font": "sans",
  "font_size": "md",
  "heading_size": "md",
  "spacing": "comfortable",
  "show_photo": true,
  "photo_shape": "round",
  "accent_color": "#bf6b15"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "design",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": null,
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Change le gabarit du CV.

PUT/cvs/{cv}/templatewrite

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

template *ats | ats-elegant | design | sidebar-left | sidebar-right | columns | exotic | canada | canada-modern | minimal | ribbon-left | ribbon-right | wave-left | wave-right | arch-left | arch-right | studio-left | studio-right | pastel-left | pastel-right | timeline-left | timeline-rightGabarit
curl -X PUT 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/template' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "template": "sidebar-left"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": null,
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Définit la photo du CV (image de la bibliothèque).

PUT/cvs/{cv}/photowrite

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

photo_media_ids *string[]Un identifiant d’image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/photo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "photo_media_ids": [
    "01j9z000000000000000000016"
  ]
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire la photo du CV.

DELETE/cvs/{cv}/photowrite

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/photo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Supprime le CV (suppression logique).

DELETE/cvs/{cv}write

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Télécharge le CV en PDF (binaire ; indisponible en mode test).

GET/cvs/{cv}/exportread

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/export' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Fichier PDF
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Contenu du CV

Ajoute une section en fin de liste ; renvoie le CV complet.

POST/cvs/{cv}/sectionswrite

Types : description (un seul texte libre : profil, centres d’intérêt ; une seule entrée), journey (parcours : expériences, formations, certifications — titre, sous-titre, dates, lieu), skills (compétences, niveau data.rating 0-100), projects (projets : url, année, tags), list (liste simple de lignes : langues, atouts), keyvalue (paires libellé/valeur : permis, état civil ; le sous-titre est la valeur, obligatoire). Un CV n’a que ces six types (ni témoignages, clients ni blog). Après avoir créé la section, ajoutez ses lignes avec l’opération d’ajout d’entrée. Sans titre, le titre par défaut du type est utilisé.

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

type *description | journey | skills | projects | list | keyvalueType
titlestringTitre
curl -X POST 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/sections' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "journey",
  "title": "Expérience"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Réordonne les sections.

PUT/cvs/{cv}/sections/reorderwrite

Chemin

cv *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

section_ids *string[]Identifiants dans le nouvel ordre
curl -X PUT 'https://middlefolio.online/api/v1/cvs/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/sections/reorder' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "section_ids": [
    "01j9z000000000000000000013",
    "01j9z000000000000000000014"
  ]
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Insère une section après {section}.

POST/cv-sections/{section}/insert-afterwrite

Types : description (un seul texte libre : profil, centres d’intérêt ; une seule entrée), journey (parcours : expériences, formations, certifications — titre, sous-titre, dates, lieu), skills (compétences, niveau data.rating 0-100), projects (projets : url, année, tags), list (liste simple de lignes : langues, atouts), keyvalue (paires libellé/valeur : permis, état civil ; le sous-titre est la valeur, obligatoire). Un CV n’a que ces six types (ni témoignages, clients ni blog). Après avoir créé la section, ajoutez ses lignes avec l’opération d’ajout d’entrée. Sans titre, le titre par défaut du type est utilisé.

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

type *description | journey | skills | projects | list | keyvalueType
titlestringTitre
curl -X POST 'https://middlefolio.online/api/v1/cv-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/insert-after' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "type": "skills",
  "title": "Compétences"
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Modifie titre, visibilité, colonne.

PATCH/cv-sections/{section}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringTitre
is_visiblebooleanVisible
columnleft | rightColonne
curl -X PATCH 'https://middlefolio.online/api/v1/cv-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Expérience professionnelle",
  "is_visible": true
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Supprime une section.

DELETE/cv-sections/{section}write

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/cv-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Ajoute une entrée ; renvoie le CV complet.

POST/cv-sections/{section}/entrieswrite

Champs requis selon le type de la section : titre (sauf description et keyvalue), subtitle pour keyvalue (la valeur). Une section description n’a qu’une entrée. Les icônes viennent du catalogue des CV (clé comme « car » ou « mail »).

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringTitre (clé pour une section clés-valeurs)
subtitlestringSous-titre (valeur pour clés-valeurs, requise)
iconstringClé d’icône (types qui l’acceptent)
descriptionstringTexte
start_datestringDate de début (AAAA-MM-JJ)
end_datestringDate de fin (AAAA-MM-JJ)
dataobjectChamps propres au type : journey → location (texte), current (booléen, poste en cours) ; skills → rating (0-100) ; projects → url, year, tags[] ; les autres types n’en ont pas
curl -X POST 'https://middlefolio.online/api/v1/cv-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/entries' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Développeuse full stack",
  "subtitle": "Sahel Craft",
  "start_date": "2022-01-01",
  "description": "Refonte de la boutique et du back-office."
}'

Réponses

201Créé
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Réordonne les entrées.

PUT/cv-sections/{section}/entries/reorderwrite

Chemin

section *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

entry_ids *string[]Identifiants dans le nouvel ordre
curl -X PUT 'https://middlefolio.online/api/v1/cv-sections/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/entries/reorder' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "entry_ids": [
    "01j9z000000000000000000015"
  ]
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Modifie une entrée ; renvoie le CV complet.

PATCH/cv-entries/{entry}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

entry *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringTitre (clé pour une section clés-valeurs)
subtitlestringSous-titre (valeur pour clés-valeurs, requise)
iconstringClé d’icône (types qui l’acceptent)
descriptionstringTexte
start_datestringDate de début (AAAA-MM-JJ)
end_datestringDate de fin (AAAA-MM-JJ)
dataobjectChamps propres au type : journey → location (texte), current (booléen, poste en cours) ; skills → rating (0-100) ; projects → url, year, tags[] ; les autres types n’en ont pas
curl -X PATCH 'https://middlefolio.online/api/v1/cv-entries/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Développeuse full stack",
  "subtitle": "Sahel Craft",
  "start_date": "2022-01-01",
  "description": "Refonte de la boutique, du back-office et de l’API."
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000011",
    "name": "CV développeuse",
    "template": "sidebar-left",
    "locale": "fr",
    "full_name": "Awa Diallo",
    "headline": "Développeuse Laravel & React",
    "email": "[email protected]",
    "phone": "+221 77 123 45 67",
    "location": "Dakar, Sénégal",
    "website": "https://awadiallo.dev",
    "portfolio_url": null,
    "extra_info": [
      {
        "kind": "birth_date",
        "label": "Date de naissance",
        "value": "",
        "icon": "cake"
      },
      {
        "kind": "birth_place",
        "label": "Lieu de naissance",
        "value": "",
        "icon": "map-pin"
      }
    ],
    "summary": "<p>Six ans d’expérience en développement web.</p>",
    "accent_color": "#bf6b15",
    "panel_color": null,
    "font": "sans",
    "heading_font": null,
    "font_size": "md",
    "heading_size": "md",
    "spacing": "comfortable",
    "use_icons": null,
    "show_photo": true,
    "photo_shape": "round",
    "photo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000012.png",
    "source_portfolio_name": null,
    "updated_at": "2026-09-15T09:30:00+00:00",
    "sections": [
      {
        "id": "01j9z000000000000000000013",
        "type": "journey",
        "title": "Expérience professionnelle",
        "position": 1,
        "is_visible": true,
        "column": null,
        "entries": []
      },
      {
        "id": "01j9z000000000000000000014",
        "type": "journey",
        "title": "Formation",
        "position": 2,
        "is_visible": true,
        "column": null,
        "entries": []
      }
    ]
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Supprime une entrée.

DELETE/cv-entries/{entry}write

Chemin

entry *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/cv-entries/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Entreprises

Entreprises que vous gérez.

GET/companiesread

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
curl 'https://middlefolio.online/api/v1/companies' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "slug": "sahel-craft",
      "name": "Sahel Craft",
      "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
      "contact_email": "[email protected]",
      "contact_phone": null,
      "website_url": "https://sahelcraft.example",
      "address": null,
      "city": "Dakar",
      "country": "Sénégal",
      "country_code": "SN",
      "logo_url": null,
      "favicon_url": null,
      "is_owner": true,
      "job_offers_count": 0
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/companies?page=1",
    "last": "https://middlefolio.online/api/v1/companies?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/companies?page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/companies",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Crée une entreprise (quota max_companies).

POST/companieswrite

Corps de la requête

name *stringNom
contact_email *stringE-mail de contact
contact_phonestringTéléphone
website_urlstringURL du site
descriptionstringPrésentation (5000 car. max)
addressstringAdresse
citystringVille
countrystringPays
country_codestringCode pays ISO 3166-1 alpha-2 (ex. CM, FR) ; prioritaire sur country
category_idsstring[]Identifiants de catégories (6 max, GET /categories)
curl -X POST 'https://middlefolio.online/api/v1/companies' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Sahel Craft",
  "contact_email": "[email protected]",
  "website_url": "https://sahelcraft.example",
  "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
  "city": "Dakar",
  "country": "Sénégal"
}'

Réponses

201Créé
{
  "data": {
    "slug": "sahel-craft",
    "name": "Sahel Craft",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": null,
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": null,
    "favicon_url": null,
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Détail d’une entreprise et de ses gestionnaires.

GET/companies/{company}read

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
curl 'https://middlefolio.online/api/v1/companies/mon-entreprise' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "slug": "sahel-craft",
    "name": "Sahel Craft",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": "Rue 10, Point E",
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "favicon_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000006.png",
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      },
      {
        "user_id": "01j9z000000000000000000009",
        "name": "Moussa Ndiaye",
        "email": "[email protected]",
        "role": "manager"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie les informations de l’entreprise.

PATCH/companies/{company}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

namestringNom
contact_emailstringE-mail de contact
contact_phonestringTéléphone
website_urlstringURL du site
descriptionstringPrésentation (5000 car. max)
addressstringAdresse
citystringVille
countrystringPays
country_codestringCode pays ISO 3166-1 alpha-2 (ex. CM, FR) ; prioritaire sur country
category_idsstring[]Identifiants de catégories (6 max, GET /categories)
curl -X PATCH 'https://middlefolio.online/api/v1/companies/mon-entreprise' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Sahel Craft",
  "contact_email": "[email protected]",
  "website_url": "https://sahelcraft.example",
  "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
  "address": "Rue 10, Point E",
  "city": "Dakar",
  "country": "Sénégal"
}'

Réponses

200Succès
{
  "data": {
    "slug": "sahel-craft",
    "name": "Sahel Craft",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": "Rue 10, Point E",
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": null,
    "favicon_url": null,
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Duplique une entreprise dont vous êtes propriétaire : fiche, catégories, logo, favicon et site dédié (quota max_companies).

POST/companies/{company}/duplicatewrite

Vous êtes le fondateur de la copie ; ni les autres gestionnaires, ni les offres, ni les candidatures ne sont copiés. Le site n’est copié que si votre formule inclut un site d’entreprise ; il naît non publié et sans sous-domaine.

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

namestringNom de la copie (défaut : « <nom> (copie) »)
curl -X POST 'https://middlefolio.online/api/v1/companies/mon-entreprise/duplicate' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Sahel Craft Abidjan"
}'

Réponses

201Créé
{
  "data": {
    "slug": "sahel-craft-abidjan",
    "name": "Sahel Craft Abidjan",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": "Rue 10, Point E",
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "favicon_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000006.png",
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Définit le logo de l’entreprise (image de la bibliothèque).

PUT/companies/{company}/logowrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/companies/mon-entreprise/logo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000008"
}'

Réponses

200Succès
{
  "data": {
    "slug": "sahel-craft",
    "name": "Sahel Craft",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": "Rue 10, Point E",
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "favicon_url": null,
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire le logo de l’entreprise.

DELETE/companies/{company}/logowrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
curl -X DELETE 'https://middlefolio.online/api/v1/companies/mon-entreprise/logo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Définit la favicon de l’entreprise et de son site (image de la bibliothèque), recompressée si elle dépasse le poids maximal.

PUT/companies/{company}/faviconwrite

Une image trop lourde est réduite : une copie compressée est ajoutée à la bibliothèque.

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/companies/mon-entreprise/favicon' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000007"
}'

Réponses

200Succès
{
  "data": {
    "slug": "sahel-craft",
    "name": "Sahel Craft",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": "Rue 10, Point E",
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "favicon_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000006.png",
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire la favicon de l’entreprise (son site reprend alors le logo).

DELETE/companies/{company}/faviconwrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
curl -X DELETE 'https://middlefolio.online/api/v1/companies/mon-entreprise/favicon' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Ajoute un gestionnaire (compte existant).

POST/companies/{company}/memberswrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

email *stringE-mail du compte
role *manager | ownerRôle
curl -X POST 'https://middlefolio.online/api/v1/companies/mon-entreprise/members' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "email": "[email protected]",
  "role": "manager"
}'

Réponses

201Créé
{
  "data": {
    "slug": "sahel-craft",
    "name": "Sahel Craft",
    "description": "Artisanat d’Afrique de l’Ouest vendu en ligne.",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "website_url": "https://sahelcraft.example",
    "address": "Rue 10, Point E",
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "favicon_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000006.png",
    "is_owner": true,
    "category_ids": [],
    "members": [
      {
        "user_id": "01j9z000000000000000000004",
        "name": "Awa Diallo",
        "email": "[email protected]",
        "role": "owner"
      },
      {
        "user_id": "01j9z000000000000000000009",
        "name": "Moussa Ndiaye",
        "email": "[email protected]",
        "role": "manager"
      }
    ],
    "job_offers_count": 0
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire un gestionnaire (pas le fondateur).

DELETE/companies/{company}/members/{user}write

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
user *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/companies/mon-entreprise/members/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Crée le site dédié ; son contenu se gère ensuite via les routes portfolios (portfolio_id).

POST/companies/{company}/sitewrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

locale *fr | enLangue du site
curl -X POST 'https://middlefolio.online/api/v1/companies/mon-entreprise/site' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "locale": "fr"
}'

Réponses

201Créé
{
  "data": {
    "portfolio_id": "01j9z000000000000000000010"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Offres d’emploi

Offres de l’entreprise.

GET/companies/{company}/offersread

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
curl 'https://middlefolio.online/api/v1/companies/mon-entreprise/offers' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "slug": "developpeurse-backend-laravel",
      "title": "Développeur·se backend Laravel",
      "description": "<p>Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce.</p>\n<h3>Vos missions</h3>\n<ul><li>Concevoir des API Laravel</li>\n<li>Relire le code de l’équipe</li>\n</ul>",
      "description_text": "Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce. Vos missions Concevoir des API Laravel Relire le code de l’équipe",
      "requirements": [
        "PHP 8",
        "Laravel"
      ],
      "required_documents": [
        "cv",
        "cover_letter"
      ],
      "positions_count": 2,
      "experience_required_years": 2,
      "experience_recommended_years": null,
      "workplace_type": "hybrid",
      "contract_type": null,
      "location_address": null,
      "region": null,
      "postal_code": null,
      "salary_min": null,
      "salary_max": null,
      "salary_currency": null,
      "salary_period": null,
      "city": "Dakar",
      "country": "Sénégal",
      "country_code": "SN",
      "contact_email": "[email protected]",
      "contact_phone": null,
      "deadline_at": "2026-10-31",
      "is_active": true,
      "closed_at": null,
      "category_ids": [],
      "applications_count": 0,
      "created_at": "2026-09-15T09:30:00+00:00"
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/companies/sahel-craft/offers?page=1",
    "last": "https://middlefolio.online/api/v1/companies/sahel-craft/offers?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/companies/sahel-craft/offers?page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/companies/sahel-craft/offers",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Publie une offre.

POST/companies/{company}/offerswrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

title *stringIntitulé
description *stringDescription détaillée : HTML (p, br, h2-h4, strong, em, u, s, ul, ol, li, blockquote, hr, a ; le reste est retiré) ou texte brut (lignes « - » = puces), converti en HTML. Renvoyée en HTML, avec description_text en texte brut
positions_count *integerNombre de postes (1 à 100)
contact_email *stringE-mail de contact
workplace_type *remote | on_site | hybridLieu de travail
contract_typecdi | cdd | interim | professional_internship | internship | apprenticeship | freelance | partner | volunteerType de contrat
requirementsstring[]Prérequis
category_idsstring[]Identifiants de catégories (GET /categories)
deadline_atstringDate limite (AAAA-MM-JJ)
experience_required_yearsintegerAnnées d’expérience exigées
experience_recommended_yearsintegerAnnées recommandées (≥ exigées)
contact_phonestringTéléphone
location_addressstringAdresse du lieu
regionstringRégion, état ou province
postal_codestringCode postal
salary_minintegerSalaire de base minimum (entier, sans décimales)
salary_maxintegerSalaire de base maximum (≥ minimum)
salary_currencyXAF | XOF | EUR | USD | GBP | CAD | AOA | BIF | BWP | CDF | CVE | DJF | DZD | EGP | ERN | ETB | GHS | GMD | GNF | KES | KMF | LRD | LSL | LYD | MAD | MGA | MRU | MUR | MWK | MZN | NAD | NGN | RWF | SCR | SDG | SLE | SOS | SSP | STN | SZL | TND | TZS | UGX | ZAR | ZMW | ZWGDevise du salaire, code ISO 4217 (défaut : XAF)
salary_periodhour | day | week | month | yearPériode du salaire (défaut : month)
citystringVille
countrystringPays
country_codestringCode pays ISO 3166-1 alpha-2 (ex. CM, FR) ; prioritaire sur country
required_documentsstring[]Pièces demandées : cv, portfolio, cover_letter, diploma, id_card, certificate (défaut : cv)
curl -X POST 'https://middlefolio.online/api/v1/companies/mon-entreprise/offers' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Développeur·se backend Laravel",
  "description": "<p>Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce.</p><h3>Vos missions</h3><ul><li>Concevoir des API Laravel</li><li>Relire le code de l’équipe</li></ul>",
  "positions_count": 2,
  "contact_email": "[email protected]",
  "workplace_type": "hybrid",
  "requirements": [
    "PHP 8",
    "Laravel"
  ],
  "deadline_at": "2026-10-31",
  "experience_required_years": 2,
  "city": "Dakar",
  "country": "Sénégal",
  "required_documents": [
    "cv",
    "cover_letter"
  ]
}'

Réponses

201Créé
{
  "data": {
    "slug": "developpeurse-backend-laravel",
    "title": "Développeur·se backend Laravel",
    "description": "<p>Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce.</p>\n<h3>Vos missions</h3>\n<ul><li>Concevoir des API Laravel</li>\n<li>Relire le code de l’équipe</li>\n</ul>",
    "description_text": "Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce. Vos missions Concevoir des API Laravel Relire le code de l’équipe",
    "requirements": [
      "PHP 8",
      "Laravel"
    ],
    "required_documents": [
      "cv",
      "cover_letter"
    ],
    "positions_count": 2,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "workplace_type": "hybrid",
    "contract_type": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "deadline_at": "2026-10-31",
    "is_active": true,
    "closed_at": null,
    "category_ids": [],
    "applications_count": 0,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Détail d’une offre.

GET/companies/{company}/offers/{jobOffer}read

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
jobOffer *Paramètre de chemin — exemple : mon-entreprise
curl 'https://middlefolio.online/api/v1/companies/mon-entreprise/offers/mon-entreprise' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "slug": "developpeurse-backend-laravel",
    "title": "Développeur·se backend Laravel",
    "description": "<p>Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce.</p>\n<h3>Vos missions</h3>\n<ul><li>Concevoir des API Laravel</li>\n<li>Relire le code de l’équipe</li>\n</ul>",
    "description_text": "Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce. Vos missions Concevoir des API Laravel Relire le code de l’équipe",
    "requirements": [
      "PHP 8",
      "Laravel"
    ],
    "required_documents": [
      "cv",
      "cover_letter"
    ],
    "positions_count": 2,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "workplace_type": "hybrid",
    "contract_type": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "deadline_at": "2026-10-31",
    "is_active": true,
    "closed_at": null,
    "category_ids": [],
    "applications_count": 0,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie une offre (is_active: false la clôture).

PATCH/companies/{company}/offers/{jobOffer}write

Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
jobOffer *Paramètre de chemin — exemple : mon-entreprise

Corps de la requête

titlestringIntitulé
descriptionstringDescription détaillée : HTML (p, br, h2-h4, strong, em, u, s, ul, ol, li, blockquote, hr, a ; le reste est retiré) ou texte brut (lignes « - » = puces), converti en HTML. Renvoyée en HTML, avec description_text en texte brut
positions_countintegerNombre de postes (1 à 100)
contact_emailstringE-mail de contact
workplace_typeremote | on_site | hybridLieu de travail
contract_typecdi | cdd | interim | professional_internship | internship | apprenticeship | freelance | partner | volunteerType de contrat
requirementsstring[]Prérequis
category_idsstring[]Identifiants de catégories (GET /categories)
deadline_atstringDate limite (AAAA-MM-JJ)
experience_required_yearsintegerAnnées d’expérience exigées
experience_recommended_yearsintegerAnnées recommandées (≥ exigées)
contact_phonestringTéléphone
location_addressstringAdresse du lieu
regionstringRégion, état ou province
postal_codestringCode postal
salary_minintegerSalaire de base minimum (entier, sans décimales)
salary_maxintegerSalaire de base maximum (≥ minimum)
salary_currencyXAF | XOF | EUR | USD | GBP | CAD | AOA | BIF | BWP | CDF | CVE | DJF | DZD | EGP | ERN | ETB | GHS | GMD | GNF | KES | KMF | LRD | LSL | LYD | MAD | MGA | MRU | MUR | MWK | MZN | NAD | NGN | RWF | SCR | SDG | SLE | SOS | SSP | STN | SZL | TND | TZS | UGX | ZAR | ZMW | ZWGDevise du salaire, code ISO 4217 (défaut : XAF)
salary_periodhour | day | week | month | yearPériode du salaire (défaut : month)
citystringVille
countrystringPays
country_codestringCode pays ISO 3166-1 alpha-2 (ex. CM, FR) ; prioritaire sur country
required_documentsstring[]Pièces demandées : cv, portfolio, cover_letter, diploma, id_card, certificate (défaut : cv)
is_activebooleanOffre ouverte
curl -X PATCH 'https://middlefolio.online/api/v1/companies/mon-entreprise/offers/mon-entreprise' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Développeur·se backend Laravel",
  "description": "<p>Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce.</p><h3>Vos missions</h3><ul><li>Concevoir des API Laravel</li><li>Relire le code de l’équipe</li></ul>",
  "positions_count": 3,
  "contact_email": "[email protected]",
  "workplace_type": "hybrid",
  "requirements": [
    "PHP 8",
    "Laravel"
  ],
  "deadline_at": "2026-10-31",
  "experience_required_years": 2,
  "city": "Dakar",
  "country": "Sénégal",
  "required_documents": [
    "cv",
    "cover_letter"
  ],
  "is_active": true
}'

Réponses

200Succès
{
  "data": {
    "slug": "developpeurse-backend-laravel",
    "title": "Développeur·se backend Laravel",
    "description": "<p>Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce.</p>\n<h3>Vos missions</h3>\n<ul><li>Concevoir des API Laravel</li>\n<li>Relire le code de l’équipe</li>\n</ul>",
    "description_text": "Vous rejoignez l’équipe produit pour faire évoluer notre plateforme e-commerce. Vos missions Concevoir des API Laravel Relire le code de l’équipe",
    "requirements": [
      "PHP 8",
      "Laravel"
    ],
    "required_documents": [
      "cv",
      "cover_letter"
    ],
    "positions_count": 3,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "workplace_type": "hybrid",
    "contract_type": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "city": "Dakar",
    "country": "Sénégal",
    "country_code": "SN",
    "contact_email": "[email protected]",
    "contact_phone": null,
    "deadline_at": "2026-10-31",
    "is_active": true,
    "closed_at": null,
    "category_ids": [],
    "applications_count": 0,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Archive l’offre.

DELETE/companies/{company}/offers/{jobOffer}write

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
jobOffer *Paramètre de chemin — exemple : mon-entreprise
curl -X DELETE 'https://middlefolio.online/api/v1/companies/mon-entreprise/offers/mon-entreprise' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Offres externes

Offres externes que vous avez soumises (tous statuts).

GET/external-offersread

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
curl 'https://middlefolio.online/api/v1/external-offers' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "slug": "designer-produit",
      "title": "Designer produit",
      "description": "<p>Offre relayée depuis le site de l’entreprise.</p>",
      "description_text": "Offre relayée depuis le site de l’entreprise.",
      "company_name": "Studio Baobab",
      "company_website_url": "https://baobab.example",
      "apply_url": "https://baobab.example/jobs/designer-produit",
      "logo_url": null,
      "requirements": [
        "Figma",
        "Design system"
      ],
      "required_documents": [
        "cv",
        "portfolio"
      ],
      "positions_count": null,
      "experience_required_years": 2,
      "experience_recommended_years": null,
      "contact_email": null,
      "contact_phone": null,
      "location_address": null,
      "region": null,
      "postal_code": null,
      "salary_min": null,
      "salary_max": null,
      "salary_currency": null,
      "salary_period": null,
      "complementary_document": null,
      "category_ids": [],
      "workplace_type": "remote",
      "contract_type": null,
      "city": "Abidjan",
      "country": "Côte d’Ivoire",
      "country_code": "CI",
      "deadline_at": "2026-10-31",
      "status": "pending",
      "rejection_reason": null,
      "reviewed_at": null,
      "created_at": "2026-09-15T09:30:00+00:00"
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/external-offers?page=1",
    "last": "https://middlefolio.online/api/v1/external-offers?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/external-offers?page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/external-offers",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant

Soumet une offre publiée ailleurs (candidature hors plateforme).

POST/external-offerswrite

Sans is_draft, l’offre naît « pending » : elle n’est visible publiquement qu’après validation par un administrateur (status « approved »), ou immédiatement si le titulaire de la clé est administrateur. Avec is_draft, elle reste « draft » (privée) jusqu’à ce que vous la soumettiez (modification avec is_draft: false).

Corps de la requête

title *stringIntitulé
description *stringDescription détaillée : HTML (p, br, h2-h4, strong, em, u, s, ul, ol, li, blockquote, hr, a ; le reste est retiré) ou texte brut (lignes « - » = puces), converti en HTML (50 000 car. max). Renvoyée en HTML, avec description_text en texte brut
company_name *stringNom de l’entreprise qui recrute
apply_url *stringLien de soumission (http ou https)
workplace_typeremote | on_site | hybridLieu de travail (défaut : on_site)
contract_typecdi | cdd | interim | professional_internship | internship | apprenticeship | freelance | partner | volunteerType de contrat
requirementsstring[]Prérequis (servent au matching avec les portfolios)
required_documentsstring[]Pièces à fournir à l’entreprise, à titre de consigne affichée : cv, portfolio, cover_letter, diploma, id_card, certificate
category_idsstring[]Identifiants de catégories (GET /categories), 6 au plus
positions_countintegerNombre de postes (1 à 100)
experience_required_yearsintegerAnnées d’expérience exigées
experience_recommended_yearsintegerAnnées recommandées (≥ exigées)
contact_emailstringE-mail de contact
contact_phonestringTéléphone
location_addressstringAdresse du lieu
regionstringRégion, état ou province
postal_codestringCode postal
salary_minintegerSalaire de base minimum (entier, sans décimales)
salary_maxintegerSalaire de base maximum (≥ minimum)
salary_currencyXAF | XOF | EUR | USD | GBP | CAD | AOA | BIF | BWP | CDF | CVE | DJF | DZD | EGP | ERN | ETB | GHS | GMD | GNF | KES | KMF | LRD | LSL | LYD | MAD | MGA | MRU | MUR | MWK | MZN | NAD | NGN | RWF | SCR | SDG | SLE | SOS | SSP | STN | SZL | TND | TZS | UGX | ZAR | ZMW | ZWGDevise du salaire, code ISO 4217 (défaut : XAF)
salary_periodhour | day | week | month | yearPériode du salaire (défaut : month)
company_website_urlstringSite de l’entreprise (http ou https)
deadline_atstringDate limite (AAAA-MM-JJ)
citystringVille
countrystringPays
country_codestringCode pays ISO 3166-1 alpha-2 (ex. CM, FR) ; prioritaire sur country
is_draftbooleanVrai : enregistre en brouillon, privé et non modéré (défaut : soumise à validation)
curl -X POST 'https://middlefolio.online/api/v1/external-offers' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Designer produit",
  "description": "Offre relayée depuis le site de l’entreprise.",
  "company_name": "Studio Baobab",
  "apply_url": "https://baobab.example/jobs/designer-produit",
  "workplace_type": "remote",
  "company_website_url": "https://baobab.example",
  "deadline_at": "2026-10-31",
  "city": "Abidjan",
  "country": "Côte d’Ivoire",
  "requirements": [
    "Figma",
    "Design system"
  ],
  "required_documents": [
    "cv",
    "portfolio"
  ],
  "experience_required_years": 2
}'

Réponses

201Créé
{
  "data": {
    "slug": "designer-produit",
    "title": "Designer produit",
    "description": "<p>Offre relayée depuis le site de l’entreprise.</p>",
    "description_text": "Offre relayée depuis le site de l’entreprise.",
    "company_name": "Studio Baobab",
    "company_website_url": "https://baobab.example",
    "apply_url": "https://baobab.example/jobs/designer-produit",
    "logo_url": null,
    "requirements": [
      "Figma",
      "Design system"
    ],
    "required_documents": [
      "cv",
      "portfolio"
    ],
    "positions_count": null,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "contact_email": null,
    "contact_phone": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "complementary_document": null,
    "category_ids": [],
    "workplace_type": "remote",
    "contract_type": null,
    "city": "Abidjan",
    "country": "Côte d’Ivoire",
    "country_code": "CI",
    "deadline_at": "2026-10-31",
    "status": "pending",
    "rejection_reason": null,
    "reviewed_at": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
422Validation ou quota de la formule

Détail d’une de vos offres externes (statut et motif de rejet inclus).

GET/external-offers/{externalJobOffer}read

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "slug": "designer-produit",
    "title": "Designer produit",
    "description": "<p>Offre relayée depuis le site de l’entreprise.</p>",
    "description_text": "Offre relayée depuis le site de l’entreprise.",
    "company_name": "Studio Baobab",
    "company_website_url": "https://baobab.example",
    "apply_url": "https://baobab.example/jobs/designer-produit",
    "logo_url": null,
    "requirements": [
      "Figma",
      "Design system"
    ],
    "required_documents": [
      "cv",
      "portfolio"
    ],
    "positions_count": null,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "contact_email": null,
    "contact_phone": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "complementary_document": null,
    "category_ids": [],
    "workplace_type": "remote",
    "contract_type": null,
    "city": "Abidjan",
    "country": "Côte d’Ivoire",
    "country_code": "CI",
    "deadline_at": "2026-10-31",
    "status": "pending",
    "rejection_reason": null,
    "reviewed_at": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Modifie une de vos offres externes.

PATCH/external-offers/{externalJobOffer}write

Une offre validée ou rejetée repasse « pending » et doit être revalidée (sauf pour un administrateur) ; is_draft: true la renvoie en brouillon, is_draft: false soumet un brouillon. Mise à jour partielle : n’envoyez que les champs à changer, les autres restent inchangés (null ou une chaîne vide efface un champ facultatif). Un objet est fusionné clé par clé, une liste est remplacée en entier.

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

titlestringIntitulé
descriptionstringDescription détaillée : HTML (p, br, h2-h4, strong, em, u, s, ul, ol, li, blockquote, hr, a ; le reste est retiré) ou texte brut (lignes « - » = puces), converti en HTML (50 000 car. max). Renvoyée en HTML, avec description_text en texte brut
company_namestringNom de l’entreprise qui recrute
apply_urlstringLien de soumission (http ou https)
workplace_typeremote | on_site | hybridLieu de travail (défaut : on_site)
contract_typecdi | cdd | interim | professional_internship | internship | apprenticeship | freelance | partner | volunteerType de contrat
requirementsstring[]Prérequis (servent au matching avec les portfolios)
required_documentsstring[]Pièces à fournir à l’entreprise, à titre de consigne affichée : cv, portfolio, cover_letter, diploma, id_card, certificate
category_idsstring[]Identifiants de catégories (GET /categories), 6 au plus
positions_countintegerNombre de postes (1 à 100)
experience_required_yearsintegerAnnées d’expérience exigées
experience_recommended_yearsintegerAnnées recommandées (≥ exigées)
contact_emailstringE-mail de contact
contact_phonestringTéléphone
location_addressstringAdresse du lieu
regionstringRégion, état ou province
postal_codestringCode postal
salary_minintegerSalaire de base minimum (entier, sans décimales)
salary_maxintegerSalaire de base maximum (≥ minimum)
salary_currencyXAF | XOF | EUR | USD | GBP | CAD | AOA | BIF | BWP | CDF | CVE | DJF | DZD | EGP | ERN | ETB | GHS | GMD | GNF | KES | KMF | LRD | LSL | LYD | MAD | MGA | MRU | MUR | MWK | MZN | NAD | NGN | RWF | SCR | SDG | SLE | SOS | SSP | STN | SZL | TND | TZS | UGX | ZAR | ZMW | ZWGDevise du salaire, code ISO 4217 (défaut : XAF)
salary_periodhour | day | week | month | yearPériode du salaire (défaut : month)
company_website_urlstringSite de l’entreprise (http ou https)
deadline_atstringDate limite (AAAA-MM-JJ)
citystringVille
countrystringPays
country_codestringCode pays ISO 3166-1 alpha-2 (ex. CM, FR) ; prioritaire sur country
is_draftbooleanVrai : enregistre en brouillon, privé et non modéré (défaut : soumise à validation)
curl -X PATCH 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "title": "Designer produit",
  "description": "Offre mise à jour.",
  "company_name": "Studio Baobab",
  "apply_url": "https://baobab.example/jobs/designer-produit",
  "workplace_type": "remote",
  "company_website_url": "https://baobab.example",
  "deadline_at": "2026-10-31",
  "city": "Abidjan",
  "country": "Côte d’Ivoire",
  "requirements": [
    "Figma",
    "Design system"
  ],
  "required_documents": [
    "cv",
    "portfolio"
  ],
  "experience_required_years": 2
}'

Réponses

200Succès
{
  "data": {
    "slug": "designer-produit",
    "title": "Designer produit",
    "description": "<p>Offre mise à jour.</p>",
    "description_text": "Offre mise à jour.",
    "company_name": "Studio Baobab",
    "company_website_url": "https://baobab.example",
    "apply_url": "https://baobab.example/jobs/designer-produit",
    "logo_url": null,
    "requirements": [
      "Figma",
      "Design system"
    ],
    "required_documents": [
      "cv",
      "portfolio"
    ],
    "positions_count": null,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "contact_email": null,
    "contact_phone": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "complementary_document": null,
    "category_ids": [],
    "workplace_type": "remote",
    "contract_type": null,
    "city": "Abidjan",
    "country": "Côte d’Ivoire",
    "country_code": "CI",
    "deadline_at": "2026-10-31",
    "status": "pending",
    "rejection_reason": null,
    "reviewed_at": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Supprime une de vos offres externes.

DELETE/external-offers/{externalJobOffer}write

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Définit le logo de l’offre (image de la bibliothèque) ; l’offre repasse « pending ».

PUT/external-offers/{externalJobOffer}/logowrite

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

media_id *stringIdentifiant d’une image de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/logo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000008"
}'

Réponses

200Succès
{
  "data": {
    "slug": "designer-produit",
    "title": "Designer produit",
    "description": "<p>Offre mise à jour.</p>",
    "description_text": "Offre mise à jour.",
    "company_name": "Studio Baobab",
    "company_website_url": "https://baobab.example",
    "apply_url": "https://baobab.example/jobs/designer-produit",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "requirements": [
      "Figma",
      "Design system"
    ],
    "required_documents": [
      "cv",
      "portfolio"
    ],
    "positions_count": null,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "contact_email": null,
    "contact_phone": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "complementary_document": null,
    "category_ids": [],
    "workplace_type": "remote",
    "contract_type": null,
    "city": "Abidjan",
    "country": "Côte d’Ivoire",
    "country_code": "CI",
    "deadline_at": "2026-10-31",
    "status": "pending",
    "rejection_reason": null,
    "reviewed_at": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Définit le document complémentaire de l’offre (fichier de la bibliothèque, public) ; l’offre repasse « pending ».

PUT/external-offers/{externalJobOffer}/documentwrite

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

media_id *stringIdentifiant d’un fichier de la bibliothèque (POST /files)
curl -X PUT 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/document' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "media_id": "01j9z000000000000000000008"
}'

Réponses

200Succès
{
  "data": {
    "slug": "designer-produit",
    "title": "Designer produit",
    "description": "<p>Offre mise à jour.</p>",
    "description_text": "Offre mise à jour.",
    "company_name": "Studio Baobab",
    "company_website_url": "https://baobab.example",
    "apply_url": "https://baobab.example/jobs/designer-produit",
    "logo_url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png",
    "requirements": [
      "Figma",
      "Design system"
    ],
    "required_documents": [
      "cv",
      "portfolio"
    ],
    "positions_count": null,
    "experience_required_years": 2,
    "experience_recommended_years": null,
    "contact_email": null,
    "contact_phone": null,
    "location_address": null,
    "region": null,
    "postal_code": null,
    "salary_min": null,
    "salary_max": null,
    "salary_currency": null,
    "salary_period": null,
    "complementary_document": {
      "name": "logo-entreprise.png",
      "url": "/storage/media/library/01j9z000000000000000000004/01j9z000000000000000000005.png"
    },
    "category_ids": [],
    "workplace_type": "remote",
    "contract_type": null,
    "city": "Abidjan",
    "country": "Côte d’Ivoire",
    "country_code": "CI",
    "deadline_at": "2026-10-31",
    "status": "pending",
    "rejection_reason": null,
    "reviewed_at": null,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Retire le document complémentaire de l’offre.

DELETE/external-offers/{externalJobOffer}/documentwrite

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/document' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Retire le logo de l’offre.

DELETE/external-offers/{externalJobOffer}/logowrite

Chemin

externalJobOffer *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl -X DELETE 'https://middlefolio.online/api/v1/external-offers/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/logo' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

204Supprimé (aucun contenu)
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Candidatures reçues

Candidatures reçues par l’entreprise.

GET/companies/{company}/applicationsread

Chemin

company *Paramètre de chemin — exemple : mon-entreprise

Paramètres de requête

pageintegerNuméro de page (défaut 1)
per_pageintegerÉléments par page (1 à 100, défaut 25)
offerstringSlug d’une offre
statussubmitted | reviewed | accepted | rejectedStatut
sortrecent | ats | ats_aiTri
curl 'https://middlefolio.online/api/v1/companies/mon-entreprise/applications' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": [
    {
      "id": "01j9z000000000000000000003",
      "job_offer_slug": "developpeurse-backend-laravel",
      "applicant_name": "Fatou Sow",
      "applicant_email": "[email protected]",
      "applicant_phone": null,
      "portfolio_url": null,
      "additional_info": null,
      "status": "submitted",
      "ats_score": null,
      "ats_ai_score": null,
      "documents_count": 0,
      "created_at": "2026-09-15T09:30:00+00:00"
    }
  ],
  "links": {
    "first": "https://middlefolio.online/api/v1/companies/sahel-craft/applications?status=submitted&page=1",
    "last": "https://middlefolio.online/api/v1/companies/sahel-craft/applications?status=submitted&page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "&laquo; Précédent",
        "page": null,
        "active": false
      },
      {
        "url": "https://middlefolio.online/api/v1/companies/sahel-craft/applications?status=submitted&page=1",
        "label": "1",
        "page": 1,
        "active": true
      }
    ],
    "path": "https://middlefolio.online/api/v1/companies/sahel-craft/applications",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Détail d’une candidature (pièces jointes non exposées).

GET/companies/{company}/applications/{application}read

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
application *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB
curl 'https://middlefolio.online/api/v1/companies/mon-entreprise/applications/01J9ZQ3M8K7Y2E5R6T4W1N0PAB' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000003",
    "job_offer_slug": "developpeurse-backend-laravel",
    "applicant_name": "Fatou Sow",
    "applicant_email": "[email protected]",
    "applicant_phone": null,
    "portfolio_url": null,
    "additional_info": null,
    "status": "submitted",
    "ats_score": null,
    "ats_ai_score": null,
    "documents_count": 0,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable

Change le statut d’une candidature.

PATCH/companies/{company}/applications/{application}/statuswrite

Chemin

company *Paramètre de chemin — exemple : mon-entreprise
application *Paramètre de chemin — exemple : 01J9ZQ3M8K7Y2E5R6T4W1N0PAB

Corps de la requête

status *submitted | reviewed | accepted | rejectedStatut
curl -X PATCH 'https://middlefolio.online/api/v1/companies/mon-entreprise/applications/01J9ZQ3M8K7Y2E5R6T4W1N0PAB/status' \
  -H 'Authorization: Bearer <votre_clé>' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "status": "reviewed"
}'

Réponses

200Succès
{
  "data": {
    "id": "01j9z000000000000000000003",
    "job_offer_slug": "developpeurse-backend-laravel",
    "applicant_name": "Fatou Sow",
    "applicant_email": "[email protected]",
    "applicant_phone": null,
    "portfolio_url": null,
    "additional_info": null,
    "status": "reviewed",
    "ats_score": null,
    "ats_ai_score": null,
    "documents_count": 0,
    "created_at": "2026-09-15T09:30:00+00:00"
  }
}
401Clé absente, invalide, expirée ou révoquée
403Droit, formule ou compte insuffisant
404Ressource introuvable
422Validation ou quota de la formule

Réponses et codes

Succès : 200 (lecture, modification), 201 (création), 204 (suppression). Chaque réponse porte un en-tête X-Request-Id, à citer en cas de support ; les appels sont visibles dans API > Logs.

{
  "message": "The name field is required.",
  "errors": {
    "name": [
      "The name field is required."
    ]
  }
}
HTTPcodemessage
401unauthenticatedClé API absente.
401invalid_api_keyClé API invalide, expirée ou révoquée.
403api_access_requiredLa formule du compte n'inclut pas l'accès à l'API.
403api_disabledLe module API est désactivé pour ce compte (clés réelles uniquement).
403insufficient_scopeLa clé n'a pas le droit requis (lecture pour GET, écriture sinon).
403email_not_verifiedL'adresse e-mail du compte n'est pas vérifiée.
403account_blockedLe compte est bloqué.
403forbiddenRessource d'un autre compte ou action non autorisée.
404not_foundRessource introuvable.
409not_available_in_test_modeOpération indisponible avec une clé de test (téléchargement de fichier, IA).
422validation_failedDonnées invalides ou quota de la formule atteint (détail par champ dans « errors »).
429rate_limitedTrop de requêtes. Réessayez plus tard (en-tête Retry-After).
500server_errorErreur interne du serveur.

Limites et bonnes pratiques

  • Débit : 60 requêtes par minute et par clé (en-têtes X-RateLimit-*, 429 + Retry-After au-delà).
  • 10 clés actives maximum par compte.
  • Ne placez jamais la clé dans du code côté navigateur.
  • Testez d’abord avec une clé de test, puis passez à une clé réelle.
  • Les webhooks (message de contact reçu, etc.) sont prévus mais pas encore disponibles.

Gérer vos clés : API > Gérer