{
  "openapi": "3.1.0",
  "info": {
    "title": "API publique MANA",
    "version": "1.0.0",
    "summary": "Missions d'entraide et annuaire des associations déclarées, en JSON-LD.",
    "description": "Lecture seule, sans authentification. Aucune donnée personnelle n'est servie : la granularité géographique maximale est la commune (code INSEE), et aucun compteur de contribution par personne n'existe.\n\nDébit : 60 requêtes par minute et par adresse IP. Taille de page maximale : 100.",
    "license": {
      "name": "Licence Ouverte 2.0 (Etalab)",
      "url": "https://www.etalab.gouv.fr/licence-ouverte-open-licence/"
    },
    "contact": {
      "name": "MANA",
      "url": "https://mana.bzh"
    }
  },
  "servers": [
    {
      "url": "https://mana.bzh/api/public/v1"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "summary": "Catalogue des jeux de données",
        "responses": {
          "200": {
            "description": "Un DataCatalog schema.org.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/chercher": {
      "get": {
        "summary": "Chercher un lieu, un commerce, un professionnel ou une association",
        "description": "LA ROUTE À APPELER pour répondre à « trouve-moi X près de Y ». Elle interroge 3 764 277 fiches actives en France, rangées en 11 catégories dérivées de 169 codes NAF de l'INSEE — donc par code officiel, jamais par ressemblance de mots. Accepte aussi un numéro SIRET (14 chiffres) ou SIREN (9) dans « q » et rend l'établissement correspondant. La granularité géographique s'arrête à la COMMUNE : ni adresse, ni coordonnées, ni contact ne sont rendus, y compris pour un établissement dont l'adresse est publique dans SIRENE.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Texte libre, ou un numéro SIRET / SIREN",
            "schema": {
              "type": "string",
              "pattern": "^.{1,80}$"
            }
          },
          {
            "name": "categorie",
            "in": "query",
            "required": false,
            "description": "Une des 11 catégories : repas, soin, beaute, artisan, habitat, boutique, transport, sortie, hotel, demarche, entraide",
            "schema": {
              "type": "string",
              "pattern": "^[a-z-]{1,24}$"
            }
          },
          {
            "name": "sous_categorie",
            "in": "query",
            "required": false,
            "description": "Une sous-catégorie (ex. « boulange », « kiné », « plombier »). ⚠️ Ne se combine pas avec « q » : le rangement l'emporte sur le texte.",
            "schema": {
              "type": "string",
              "pattern": "^[a-zà-ÿ' -]{1,40}$"
            }
          },
          {
            "name": "commune",
            "in": "query",
            "required": false,
            "description": "Code INSEE de la commune",
            "schema": {
              "type": "string",
              "pattern": "^[0-9AB]{5}$"
            }
          },
          {
            "name": "departement",
            "in": "query",
            "required": false,
            "description": "Code de département",
            "schema": {
              "type": "string",
              "pattern": "^[0-9AB]{2,3}$"
            }
          }
        ]
      }
    },
    "/missions": {
      "get": {
        "summary": "Missions ouvertes",
        "description": "Chaque mission porte l'URL de sa source : la candidature se fait chez l'organisateur.",
        "parameters": [
          {
            "name": "commune",
            "in": "query",
            "required": false,
            "description": "Code INSEE de la commune (résolu en nom de commune)",
            "schema": {
              "type": "string",
              "pattern": "^[0-9AB]{5}$"
            }
          },
          {
            "name": "code_postal",
            "in": "query",
            "required": false,
            "description": "Code postal",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{5}$"
            }
          },
          {
            "name": "departement",
            "in": "query",
            "required": false,
            "description": "Code de département",
            "schema": {
              "type": "string",
              "pattern": "^(0[1-9]|[1-8][0-9]|9[0-5]|2[AB]|97[1-6])$"
            }
          },
          {
            "name": "date_min",
            "in": "query",
            "required": false,
            "description": "Début au plus tôt (AAAA-MM-JJ)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "date_max",
            "in": "query",
            "required": false,
            "description": "Début au plus tard (AAAA-MM-JJ)",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
            }
          },
          {
            "name": "duree_max_heures",
            "in": "query",
            "required": false,
            "description": "Durée d'engagement maximale, en heures",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "nature",
            "in": "query",
            "required": false,
            "description": "Nature de l'engagement (benevolat, volontariat_service_civique…)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "domaine",
            "in": "query",
            "required": false,
            "description": "Domaine (sante, environnement, sport…)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Recherche dans le titre",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "description": "1 à 100",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "curseur",
            "in": "query",
            "required": false,
            "description": "Curseur de pagination, rendu par « mana:pageSuivante »",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Un ItemList d’Event.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "Débit dépassé.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/mission/{id}": {
      "get": {
        "summary": "Détail d'une mission",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Un Event.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Aucune mission à cet identifiant.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "410": {
            "description": "La mission a été retirée ; la date de retrait accompagne la réponse.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/communes": {
      "get": {
        "summary": "Résoudre un nom de commune en code INSEE",
        "description": "À appeler EN PREMIER : les routes /missions et /associations attendent un code INSEE, pas un nom.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Début du nom de la commune (« croz » trouve Crozon)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "commune",
            "in": "query",
            "required": false,
            "description": "Code INSEE, pour la recherche inverse",
            "schema": {
              "type": "string",
              "pattern": "^[0-9AB]{5}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Un ItemList de Place.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Aucun filtre fourni.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/associations": {
      "get": {
        "summary": "Associations déclarées",
        "description": "Au moins un filtre est exigé : le répertoire ne se parcourt pas de bout en bout.",
        "parameters": [
          {
            "name": "commune",
            "in": "query",
            "required": false,
            "description": "Code INSEE",
            "schema": {
              "type": "string",
              "pattern": "^[0-9AB]{5}$"
            }
          },
          {
            "name": "departement",
            "in": "query",
            "required": false,
            "description": "Code de département",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Recherche dans le nom",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "curseur",
            "in": "query",
            "required": false,
            "description": "Curseur de pagination",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Un ItemList d’Organization.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Aucun filtre fourni.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/association/{rna}": {
      "get": {
        "summary": "Fiche d'une association par numéro RNA",
        "parameters": [
          {
            "name": "rna",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^W[0-9A-Z]{8,9}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Une Organization.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Numéro inconnu.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "summary": "Cette spécification",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1.",
            "content": {
              "application/ld+json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  }
}