
# (c) Secure Identity Alliance

openapi: 3.0.0
info:
  description: |
    The OSIA Data Access Interface.
    
    Change log:

    - 1.3.0:
      - Add errors 400 and return error details
      - Force additionalProperties to false when extension is not allowed
      - Add pagination for query service. limit parameter replaces the max parameter.
    - 1.2.0: addition of security
    - 1.1.0: extended queryPersonUIN/queryPersonList operation to return a list of attributes, and not only a list of UIN
    - 1.0.0: first version proposed in OSIA.

  version: 1.3.0
  title: OSIA Data Access Interface
  license:
    name: SIA
    url: "https://raw.githubusercontent.com/SecureIdentityAlliance/osia/master/LICENSE"
servers:
  - url: https://pr.com/
  - url: https://cr.com/
tags:
  - name: Person
  - name: Document
paths:
  /v1/persons:
    get:
      description: |
        Query for persons using a set of attributes. Retrieve the UIN or the person attributes.
        This service is used when the UIN is unknown.
        Example: http://registry.com/v1/persons?firstName=John&lastName=Do&names=firstName
      operationId: queryPersonList
      security:
        - BearerAuth: [pr.person.read, cr.person.read]
      tags:
      - Person
      parameters: 
        - name: attributes
          in: query
          description: The attributes (names and values) used to query
          required: true
          schema:
            type: object
            additionalProperties: true
          style: form
          explode: true
          example:
            firstName: John
            lastName: Do
        - name: names
          in: query
          description: The names of the attributes to return. If not provided, only the UIN is returned
          required: false
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          example:
            - firstName
            - lastName
        - name: offset
          in: query
          description: The offset of the query (first item of the response)
          required: false
          schema:
            type: integer
            default: 0
        - name: limit
          in: query
          description: The maximum number of items to return
          required: false
          schema:
            type: integer
            default: 100

      responses:
        200:
          description: >
            The requested attributes for all found persons (a list of at least one entry).
            
            If no names are given, a flat list of UIN is returned.
            If at least one name is given, a list of dictionaries (one dictionary per record) is returned.
          content:
            application/json:
              schema:
                oneOf:
                - type: array
                  minimum: 1
                  items:
                    type: string
                  example:
                    - "1235567890"
                - type: array
                  minimum: 1
                  items:
                    type: object
                    additionalProperties:
                      oneOf:
                      - type: string
                      - type: integer
                      - type: number
                      - type: boolean
                      - $ref: '#/components/schemas/Error'
                    example:
                      firstName: John
                      lastName: Doo
                      dob:
                        code: 1023
                        message: Unknown attribute name
                    
        400:
          description: Invalid parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        401:
          description: Client must be authenticated
        403:
          description: Service forbidden
        404:
          description: No record found
        500:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/persons/{uin}:
    get:
      description: "Read attributes for a person. Example: http://registry.com/v1/persons/123456789?attributeNames=firstName&attributeNames=lastName&attributeNames=dob"
      operationId: readPersonAttributes
      security:
        - BearerAuth: [pr.person.read, cr.person.read]
      tags:
        - Person
      parameters: 
        - name: uin
          in: path
          description: Unique Identity Number
          required: true
          schema:
            type: string
        - name: attributeNames
          in: query
          description: The names of the attributes requested for this person
          required: true
          schema:
            type: array
            items:
              type: string
            example:
              - firstName
              - lastName
              - dob
      responses:
        200:
          description: Requested attributes values or error description.
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  oneOf:
                  - type: string
                  - type: integer
                  - type: number
                  - type: boolean
                  - $ref: '#/components/schemas/Error'
              example:
                firstName: John
                lastName: Doo
                dob:
                  code: 1023
                  message: Unknown attribute name
        400:
          description: Invalid parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        401:
          description: Client must be authenticated
        403:
          description: Service forbidden
        404:
          description: Unknown uin
        500:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/persons/{uin}/match:
    post:
      description: |
        Match person attributes.
        This service is used to check the value of attributes without exposing private data.

        The request body should contain a list of attributes and their value, formatted as a json dictionary.
      operationId: matchPersonAttributes
      security:
        - BearerAuth: [pr.person.match, cr.person.match]
      tags:
        - Person
      parameters: 
        - name: uin
          in: path
          description: Unique Identity Number
          required: true
          schema:
            type: string
      requestBody:
        description: A set of attributes for the person
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Attributes'
            example:
              firstName: John
              lastName: Doo
              dateOfBirth: "1984-11-19"
      responses:
        200:
          description: |
            Information about non matching attributes. Returns a list of matching result.
            An empty list indicates all attributes were matching.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MatchingError'
              example:
                - attributeName: firstName
                  errorCode: 1
        400:
          description: Invalid parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        401:
          description: Client must be authenticated
        403:
          description: Service forbidden
        404:
          description: Unknown uin
        500:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/persons/{uin}/verify:
    post:
      description: |
        Evaluate expressions on person attributes.
        This service is used to evaluate simple expressions on
        person's attributes without exposing private data

        The request body should contain a list of expressions.
      operationId: verifyPersonAttributes
      security:
        - BearerAuth: [pr.person.verify, cr.person.verify]
      tags:
        - Person
      parameters: 
        - name: uin
          in: path
          description: Unique Identity Number
          required: true
          schema:
            type: string
      requestBody:
        description: A set of expressions on attributes of the person
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Expressions'
            example:
              - attributeName: firstName
                operator: "="
                value: John
              - attributeName: dateOfBirth
                operator: "<"
                value: "1990-12-31"
      responses:
        200:
          description: The expressions are all true (true is returned) or one is false (false is returned)
          content:
            application/json:
              schema:
                type: boolean
              example:
                true
        400:
          description: Invalid parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        401:
          description: Client must be authenticated
        403:
          description: Forbidden access. The service is forbidden or one of the attributes is forbidden.
        404:
          description: Unknown uin
        500:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /v1/persons/{uin}/document:
    get:
      description: |
        Read in an unstructured format (PDF, image) a document such as a marriage certificate.
        Example: ``http://registry.com/v1/persons/123456789/document?doctype=marriage&secondaryUin=234567890&format=pdf``
      operationId: readDocument
      security:
        - BearerAuth: [pr.document.read, cr.document.read]
      tags:
        - Document
      parameters: 
        - name: uin
          in: path
          description: Unique Identity Number
          required: true
          schema:
            type: string
        - name: secondaryUin
          in: query
          description: |
            Unique Identity Number of a second person linked to the requested document.
            Example: wife, husband
          required: false
          schema:
            type: string
        - name: doctype
          in: query
          description: The type of document
          required: true
          schema:
            type: string
        - name: format
          in: query
          description: |
            The expected format of the document.
            If the document is not available at this format, it must be converted.
            TBD: one format for certificate data.
          required: true
          schema:
            type: string
            enum: ['pdf', 'jpeg', 'png', 'TBD'] 
      responses:
        200:
          description: The document(s) is/are found and returned, as binary data in a MIME multipart structure.
          content:
            multipart/mixed:
              schema:
                type: object
                properties:
                  documents:
                    type: array
                    items:
                      type: string
                      format: binary
                additionalProperties: false
              encoding:
                documents:
                  contentType: application/pdf, image/jpeg, image/png
        400:
          description: Invalid parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        401:
          description: Client must be authenticated
        403:
          description: Service forbidden
        404:
          description: Unknown uin
        415:
          description: Unsupported format
        500:
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
      additionalProperties: false
    Attributes:
      type: object
      additionalProperties:
        oneOf:
        - type: string
        - type: integer
        - type: number
        - type: boolean
      # Or ?:
      #additionalProperties: true
    Expression:
      type: object
      required:
        - attributeName
        - operator
        - value
      properties:
        attributeName:
          type: string
        operator:
          type: string
          enum: ['<', '>', '=', '>=', '<=']
        value:
          oneOf:
          - type: string
          - type: integer
          - type: number
          - type: boolean
      additionalProperties: false
    Expressions:
      type: array
      items:
        $ref: '#/components/schemas/Expression'
    MatchingError:
      type: array
      items:
        type: object
        properties:
          attributeName:
            type: string
          errorCode:
            type: integer
            format: int32
            enum: [0, 1]
            description: 0=attribute does not exist; 1=attribute exists but does not match
        additionalProperties: false
        
