openapi: 3.0.3 info: title: Meet External API version: 1.0.0 description: | External API for room management with application-delegated authentication. #### Authentication Flow 1. Exchange application credentials for a JWT token via `/external-api/v1.0/application/token/`. 2. Use the JWT token in the `Authorization: Bearer ` header for all subsequent requests. 3. Tokens are scoped and allow applications to act on behalf of specific users. #### Scopes * `rooms:list` – List rooms accessible to the delegated user. * `rooms:retrieve` – Retrieve details of a specific room. * `rooms:create` – Create new rooms. * `rooms:update` – **Coming soon** Update existing rooms, e.g., add attendees to a room. * `rooms:delete` – **Coming soon** Delete rooms generated by the application. #### Upcoming Features * **Add attendees to a room:** You will be able to update a room to include a list of attendees, allowing them to bypass the lobby system automatically. * **Delete application-generated rooms:** Rooms created via the application can be deleted when no longer needed. contact: name: API Support email: antoine.lebaud@mail.numerique.gouv.fr servers: - url: https://visio-sandbox.beta.numerique.gouv.fr/external-api/v1.0 description: Sandbox server tags: - name: Authentication description: Application authentication and token generation - name: Rooms description: Room management operations paths: /application/token/: post: tags: - Authentication summary: Generate JWT token description: | Exchange application credentials for a scoped JWT token that allows the application to act on behalf of a specific user. The application must be authorized for the user's email domain. The returned token expires after a configured duration and must be refreshed by calling this endpoint again. operationId: generateToken requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TokenRequest' examples: tokenRequest: summary: Request token for user delegation value: client_id: "550e8400-e29b-41d4-a716-446655440000" client_secret: "1234567890abcdefghijklmnopqrstuvwxyz" grant_type: "client_credentials" scope: "user@example.com" responses: '200': description: Token generated successfully content: application/json: schema: $ref: '#/components/schemas/TokenResponse' examples: tokenResponse: summary: Successful token generation value: access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." token_type: "Bearer" expires_in: 3600 scope: "rooms:list rooms:retrieve rooms:create" '401': description: Authentication failed content: application/json: schema: $ref: '#/components/schemas/OAuthError' examples: invalidCredentials: summary: Invalid credentials value: error: "Invalid credentials" inactiveApplication: summary: Application is inactive value: error: "Application is inactive" '400': description: Invalid request content: application/json: schema: $ref: '#/components/schemas/OAuthError' examples: userNotFound: summary: User not found value: error: "User not found." '403': description: Access denied - cannot delegate user content: application/json: schema: $ref: '#/components/schemas/OAuthError' examples: delegationDenied: summary: Domain not authorized value: error: "This application is not authorized for this email domain." /rooms: get: tags: - Rooms summary: List rooms description: | Returns a list of rooms accessible to the authenticated user. Only rooms where the delegated user has access will be returned. operationId: listRooms security: - BearerAuth: [rooms:list] parameters: - name: page in: query description: Page number for pagination schema: type: integer minimum: 1 default: 1 - name: page_size in: query description: Number of items per page schema: type: integer minimum: 1 maximum: 100 default: 20 responses: '200': description: List of accessible rooms content: application/json: schema: type: object properties: count: type: integer description: Total number of rooms next: type: string nullable: true description: URL to next page previous: type: string nullable: true description: URL to previous page results: type: array items: $ref: '#/components/schemas/Room' examples: roomList: summary: Paginated room list value: count: 2 next: "https://visio-sandbox.beta.numerique.gouv.fr/external-api/v1.0/rooms?page=2" previous: null results: - id: "7c9e6679-7425-40de-944b-e07fc1f90ae7" slug: "aae-erez-aaz" access_level: "trusted" url: "https://visio-sandbox.beta.numerique.gouv.fr/aae-erez-aaz" telephony: enabled: true pin_code: "123456" phone_number: "+1-555-0100" default_country: "US" '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/ForbiddenError' post: tags: - Rooms summary: Create a room description: | Creates a new room with secure defaults for external API usage. **Restrictions:** - Rooms are always created with `trusted` access (no public rooms via API) - Room access_level can be updated from the webapp interface. **Defaults:** - Delegated user is set as owner - Room slug auto-generated for uniqueness - Telephony PIN auto-generated when enabled - Creation tracked with application client_id for auditing operationId: createRoom security: - BearerAuth: [rooms:create] requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/RoomCreate' examples: emptyBody: summary: No parameters (default) value: {} responses: '201': description: Room created successfully content: application/json: schema: $ref: '#/components/schemas/Room' '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/ForbiddenError' /rooms/{id}: get: tags: - Rooms summary: Retrieve a room description: Get detailed information about a specific room by its ID operationId: retrieveRoom security: - BearerAuth: [rooms:retrieve] parameters: - name: id in: path required: true description: Room UUID schema: type: string format: uuid responses: '200': description: Room details content: application/json: schema: $ref: '#/components/schemas/Room' examples: room: summary: Room details value: id: "7c9e6679-7425-40de-944b-e07fc1f90ae7" slug: "aae-erez-aaz" access_level: "trusted" url: "https://visio-sandbox.beta.numerique.gouv.fr/aae-erez-aaz" telephony: enabled: true pin_code: "123456" phone_number: "+1-555-0100" default_country: "US" '401': $ref: '#/components/responses/UnauthorizedError' '403': $ref: '#/components/responses/ForbiddenError' '404': $ref: '#/components/responses/RoomNotFoundError' components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: | JWT token obtained from the `/application/token/` endpoint. Include in requests as: `Authorization: Bearer ` schemas: TokenRequest: type: object required: - client_id - client_secret - grant_type - scope properties: client_id: type: string description: Application client identifier example: "550e8400-e29b-41d4-a716-446655440000" client_secret: type: string format: password writeOnly: true description: Application secret key example: "1234567890abcdefghijklmnopqrstuvwxyz" grant_type: type: string enum: - client_credentials description: OAuth2 grant type (must be 'client_credentials') example: "client_credentials" scope: type: string format: email description: | Email address of the user to delegate. The application will act on behalf of this user. Note: This parameter is named 'scope' to align with OAuth2 conventions, but accepts an email address to identify the user. This design allows for future extensibility. example: "user@example.com" TokenResponse: type: object properties: access_token: type: string description: JWT access token example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtZWV0LWFwaSIsImF1ZCI6Im1lZXQtY2xpZW50cyIsImlhdCI6MTcwOTQ5MTIwMCwiZXhwIjoxNzA5NDk0ODAwLCJjbGllbnRfaWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJzY29wZSI6InJvb21zOmxpc3Qgcm9vbXM6cmV0cmlldmUgcm9vbXM6Y3JlYXRlIiwidXNlcl9pZCI6IjdiOGQ5YzQwLTNhMmItNGVkZi04NzFjLTJmM2Q0ZTVmNmE3YiIsImRlbGVnYXRlZCI6dHJ1ZX0.signature" token_type: type: string description: Token type (always 'Bearer') example: "Bearer" expires_in: type: integer description: Token lifetime in seconds example: 3600 scope: type: string description: Space-separated list of granted permission scopes example: "rooms:list rooms:retrieve rooms:create" RoomCreate: type: object description: Empty object - all room properties are auto-generated properties: {} Room: type: object properties: id: type: string format: uuid readOnly: true description: Unique room identifier example: "7c9e6679-7425-40de-944b-e07fc1f90ae7" slug: type: string readOnly: true description: URL-friendly room identifier (auto-generated) example: "aze-eere-zer" access_level: type: string readOnly: true description: Room access level (always 'trusted' for API-created rooms) example: "trusted" url: type: string format: uri readOnly: true description: Full URL to access the room example: "https://visio-sandbox.beta.numerique.gouv.fr/aze-eere-zer" telephony: type: object readOnly: true description: Telephony dial-in information (if enabled) properties: enabled: type: boolean description: Whether telephony is available example: true pin_code: type: string description: PIN code for dial-in access example: "123456" phone_number: type: string description: Phone number to dial example: "+1-555-0100" default_country: type: string description: Default country code example: "US" OAuthError: type: object description: OAuth2-compliant error response properties: error: type: string description: Human-readable error description example: "Invalid credentials" Error: type: object properties: detail: type: string description: Error message example: "Invalid token." ValidationError: type: object properties: field_name: type: array items: type: string description: List of validation errors for this field example: ["This field is required."] responses: UnauthorizedError: description: Authentication required or token invalid/expired content: application/json: schema: $ref: '#/components/schemas/Error' examples: invalidToken: summary: Invalid or expired token value: error: "Invalid token." tokenExpired: summary: Token has expired value: error: "Token expired." ForbiddenError: description: Insufficient permissions for this operation content: application/json: schema: $ref: '#/components/schemas/Error' examples: insufficientScope: summary: Missing required scope value: detail: "Insufficient permissions. Required scope: 'rooms:xxxx'" RoomNotFoundError: description: Room not found content: application/json: schema: $ref: '#/components/schemas/Error' examples: roomNotFound: summary: Room does not exist value: detail: "Not found." BadRequestError: description: Invalid request data content: application/json: schema: $ref: '#/components/schemas/ValidationError' examples: validationError: summary: Field validation failed value: scope: ["Invalid email address."]