api/public_api_v1.yaml
swagger: '2.0'
info:
version: 1.0.0
title: Digital Citizenship API
contact:
name: Digital Transformation Team and AgID
url: https://forum.italia.it/c/progetto-io
x-logo:
url: https://io.italia.it/assets/img/io-logo-blue.svg
description: >
# Warning / Avvertenza
**Questa è una API sperimentale che (probabilmente)
subirà dei cambiamenti mano a mano che il servizio di
messaggistica IO si evolverà.**
**This is an experimental API that is (most probably)
going to change as we evolve the IO Messaging service.**
# Introduction
This is the documentation of the Digital Citizenship API.
This API enables Public Administration services to integrate with the
Digital Citizenship platform of the Italian Government.
The platform enables services to communicate with Italian Citizens via
the [IO app](https://io.italia.it/).
# How to get an API key
To get access to this API, you'll need to register on the
[Digital Citizenship Developer Portal](https://developer.cd.italia.it/).
After the registration step, you have to click on the button that says
`subscribe to the digital citizenship api` to receive the API key
that you will use to authenticate the API calls.
You will also receive an email with further instructions, including a fake
Fiscal Code that you will be able to use to send test messages. Messages
sent to the fake Fiscal Code will be notified to the email address used
during the registration process on the developer portal.
# Messages
## What is a message
Messages are the primary form of communication enabled by the Digital
Citizenship APIs. Messages are **personal** communications directed to a
**specific citizen**. You will not be able to use this API to broadcast a
message to a group of citizens, you will have to compose e specific,
personalized message to each citizen you want to communicate to.
The recipient of the message (i.e. a citizen) is identified trough his
[Fiscal Code](https://it.wikipedia.org/wiki/Codice_fiscale).
## Message format
A message is conceptually very similar to an email and, in its simplest form,
is composed of the following attributes:
* A required `subject`: a short description of the topic.
* A required `markdown` body: a Markdown representation of the body (see
below on what Markdown tags are allowed).
* An optional `payment_data`: in case the message is a payment request,
the _payment data_ will enable the recipient to pay the requested amount
via [PagoPA](https://www.agid.gov.it/it/piattaforme/pagopa).
* An optional `due_date`: a _due date_ that let the recipient
add a reminder when receiving the message. The format for all
dates is [ISO8601](https://it.wikipedia.org/wiki/ISO_8601) with time
information and UTC timezone (ie. "2018-10-13T00:00:00.000Z").
## Allowed Markdown formatting
Not all Markdown formatting is currently available. Currently you can use
the following formatting:
* Headings
* Text stylings (bold, italic, etc...)
* Lists (bullet and numbered)
## Process for sending a message to a citizen
Not every citizen will be interested in what you have to say and not every
citizen you want to communicate to will be registered on the Digital
Citizenship platform. For this reason, before sending a message you will
have to check whether the recipient is registered on the platform and
that he has not yet opted out from receiving messages from you.
The process for sending a message is made of 3 steps:
1. Call [getProfile](#operation/getProfile): if the profile does not exist
or the recipient has opted-out from your service, you cannot send the
message and you must stop here.
1. Call [submitMessageforUser](#operation/submitMessageforUser) to submit
a new message.
1. (optional) Call [getMessage](#operation/getMessage) to check whether
the message has been notified to the recipient.
host: api.cd.italia.it
tags:
- name: public
description: Public APIs
- name: restricted
description: Restricted APIs
x-tagGroups:
- name: For Public Administrations and services
tags:
- public
- name: For the IO app
tags:
- restricted
basePath: "/api/v1"
schemes:
- https
security:
- SubscriptionKey: []
paths:
"/services/{service_id}":
parameters:
- name: service_id
in: path
type: string
required: true
description: The ID of an existing Service.
get:
tags:
- restricted
operationId: getService
summary: Get Service
description: A previously created service with the provided service ID is returned.
responses:
'200':
description: Service found.
schema:
"$ref": "#/definitions/ServicePublic"
examples:
application/json:
department_name: dept
organization_name: org
service_id: 2b3e728c1a5d1efa035c
service_name: service
version: 1
'401':
description: Unauthorized
'404':
description: No service found for the provided ID.
'429':
description: Too many requests
parameters: []
"/profiles/{recipient}/sender-services":
get:
tags:
- restricted
operationId: getServicesByRecipient
summary: Get Services by recipient
description: |-
Returns the service IDs of all the services that have contacted the recipient,
identified by the provided fiscal code, at least once.
responses:
'200':
description: Found.
schema:
$ref: "#/definitions/PaginatedServiceTupleCollection"
'401':
description: Unauthorized
'429':
description: Too many requests
parameters:
- name: recipient
in: path
type: string
required: true
description: The recipient's fiscal code.
minLength: 16
maxLength: 16
pattern: "[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]"
"/services":
get:
tags:
- restricted
operationId: getVisibleServices
summary: Get all visibile services.
description: |-
Returns all the services that have the 'is_visibile' field value set to true.
responses:
'200':
description: Found.
schema:
$ref: "#/definitions/PaginatedServiceTupleCollection"
'401':
description: Unauthorized
'429':
description: Too many requests
"/messages/{fiscal_code}/{id}":
get:
tags:
- public
- restricted
operationId: getMessage
summary: Get Message
description: |-
The previously created message with the provided message ID is
returned.
parameters:
- $ref: "#/parameters/FiscalCode"
- name: id
in: path
type: string
required: true
description: The ID of the message.
responses:
'200':
description: Message found.
schema:
$ref: "#/definitions/MessageResponseWithContent"
examples:
application/json:
message:
id: 01BX9NSMKAAAS5PSP2FATZM6BQ
fiscal_code: QXJNTX9RCRVD6V4O
time_to_live: 3600
content:
subject: message subject, aliquip sint nulla in estinut
markdown: |-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas et mollis felis.
Vivamus orci nisl, commodo ut sodales ut, eleifend a libero. Donec dapibus, turpis in mattis tempor,
risus nunc malesuada ex, non aliquet metus nunc a lacus. Aenean in arcu vitae nisl porta
fermentum nec non nibh. Phasellus tortor tellus, semper in metus eget, eleifend
laoreet nibh. Aenean feugiat lectus ut nisl eleifend gravida.
sender_service_id: 01BX9NSMKVXXS5PSP2FATZM6QX
notification:
email: QUEUED
'401':
description: Unauthorized
'404':
description: No message found for the provided ID.
schema:
$ref: "#/definitions/ProblemJson"
'429':
description: Too many requests
"/messages/{fiscal_code}":
get:
tags:
- restricted
operationId: getMessagesByUser
summary: Get messages by user
description: |-
Returns the messages for the user identified by the provided fiscal code.
Messages will be returned in inverse acceptance order (from last to first).
The "next" field, when present, contains an URL pointing to the next page of results.
responses:
'200':
description: Found.
schema:
$ref: "#/definitions/PaginatedCreatedMessageWithoutContentCollection"
examples:
application/json:
items:
- id: 01BX9NSMKVXXS5PSP2FATZMYYY
fiscal_code: PUPFHK4TD3MWL20W
time_to_live: 3600
content:
subject: amet sunt dolor nulla esseesseanim
markdown: |-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas et mollis felis.
Vivamus orci nisl, commodo ut sodales ut, eleifend a libero. Donec dapibus, turpis in mattis tempor,
risus nunc malesuada ex, non aliquet metus nunc a lacus. Aenean in arcu vitae nisl porta
fermentum nec non nibh. Phasellus tortor tellus, semper in metus eget, eleifend
laoreet nibh. Aenean feugiat lectus ut nisl eleifend gravida.
sender_service_id: 01BX9NSMKVXXS5PSP2FATZMZZZ
- id: 01BX9NSMKVXXS5PSP2FATZM123
fiscal_code: PKTINH4QDQUV696L
time_to_live: 3600
content:
subject: idUt quis tempor esseesseanim
markdown: |-
Nullam dapibus metus sed elementum efficitur. Curabitur facilisis sagittis risus nec sodales.
Vestibulum in eros sapien. Donec ac odio sit amet dui semper ornare eget nec odio. Pellentesque habitant
morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent nibh ex, mattis sit amet
felis id, sodales euismod velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
sender_service_id: 01BX9NSMKVXXS5PSP2FATZMWWW
page_size: 2
next: https://example.com/next
'401':
description: Unauthorized
'404':
description: No message found.
schema:
$ref: "#/definitions/ProblemJson"
'429':
description: Too many requests
parameters:
- $ref: "#/parameters/FiscalCode"
- $ref: "#/parameters/PaginationRequest"
post:
tags:
- public
operationId: submitMessageforUser
summary: Submit a message
description: |-
Submits a message to a user.
On error, the reason is returned in the response payload.
In order to call `submitMessageforUser`, before sending any message,
the sender MUST call `getProfile` and check that the profile exists
(for the specified fiscal code) and that the `sender_allowed` field
of the user's profile it set to `true`.
parameters:
- $ref: "#/parameters/FiscalCode"
- name: message
in: body
schema:
$ref: "#/definitions/NewMessage"
x-examples:
application/json:
time_to_live: 3600
content:
subject: ipsum labore deserunt fugiat
markdown: |-
Nullam dapibus metus sed elementum efficitur. Curabitur facilisis sagittis risus nec sodales.
Vestibulum in eros sapien. Donec ac odio sit amet dui semper ornare eget nec odio. Pellentesque habitant
morbi tristique senectus et netus et malesuada fames ac turpis egestas. Praesent nibh ex, mattis sit amet
felis id, sodales euismod velit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
responses:
'201':
description: Message created.
schema:
type: object
properties:
id:
type: string
description: The identifier of the created message.
headers:
Location:
type: string
description: |-
Location (URL) of created message resource.
A GET request to this URL returns the message status and details.
examples:
application/json:
id: 01BX9NSMKVXXS5PSP2FATZMYYY
'400':
description: Invalid payload.
schema:
$ref: "#/definitions/ProblemJson"
examples: {}
'401':
description: Unauthorized
'429':
description: Too many requests
'500':
description: The message cannot be delivered.
schema:
$ref: "#/definitions/ProblemJson"
"/profiles/{fiscal_code}":
get:
tags:
- public
operationId: getProfile
summary: Get a User Profile
description: |-
Returns the preferences for the user identified by the provided
fiscal code. The field `sender_allowed` is set fo `false` in case
the service which is calling the API is blacklisted by the user.
responses:
'200':
description: Found.
schema:
$ref: "#/definitions/Profile"
examples:
application/json:
email: foobar@example.com
version: 1
'401':
description: Unauthorized
'404':
description: No user found for the provided fiscal code.
schema:
$ref: "#/definitions/ProblemJson"
'429':
description: Too many requests
parameters:
- $ref: "#/parameters/FiscalCode"
post:
tags:
- restricted
responses:
'200':
description: Profile updated.
schema:
$ref: "#/definitions/ExtendedProfile"
examples:
application/json:
email: foobar@example.com
version: 0
'400':
description: Invalid payload.
schema:
$ref: "#/definitions/ProblemJson"
'401':
description: Unauthorized
'404':
description: Not found
'429':
description: Too many requests
'500':
description: Profile cannot be updated.
schema:
$ref: "#/definitions/ProblemJson"
description: |-
Create or update the preferences for the user identified by the
provided fiscal code.
operationId: upsertProfile
summary: Updates a User Profile
parameters:
- $ref: "#/parameters/FiscalCode"
- in: body
name: body
schema:
$ref: "#/definitions/ExtendedProfile"
x-examples:
application/json:
email: foobar@example.com
"/info":
get:
tags:
- restricted
operationId: getInfo
responses:
'200':
description: Returns success if the API-Key is right.
schema:
type: object
properties: {}
'401':
description: Unauthorized
'429':
description: Too many requests
description: An endpoint to test authenticated access to the API backend.
summary: API test endpoint
definitions:
ProblemJson:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ProblemJson"
NotificationChannel:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/NotificationChannel"
BlockedInboxOrChannel:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/BlockedInboxOrChannel"
NotificationChannelStatusValue:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/NotificationChannelStatusValue"
NotificationChannelStatus:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/NotificationChannelStatus"
PaymentData:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PaymentData"
PaymentNoticeNumber:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PaymentNoticeNumber"
PaymentAmount:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PaymentAmount"
MaxAllowedPaymentAmount:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MaxAllowedPaymentAmount"
CreatedMessageWithContent:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/CreatedMessageWithContent"
CreatedMessageWithoutContent:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/CreatedMessageWithoutContent"
MessageResponseNotificationStatus:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageResponseNotificationStatus"
MessageResponseWithContent:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageResponseWithContent"
MessageResponseWithoutContent:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageResponseWithoutContent"
FiscalCode:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/FiscalCode"
OrganizationFiscalCode:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/OrganizationFiscalCode"
MessageSubject:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageSubject"
MessageBodyMarkdown:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageBodyMarkdown"
PaginationResponse:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PaginationResponse"
CreatedMessageWithoutContentCollection:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/CreatedMessageWithoutContentCollection"
PaginatedCreatedMessageWithoutContentCollection:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PaginatedCreatedMessageWithoutContentCollection"
BlockedInboxOrChannels:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/BlockedInboxOrChannels"
Profile:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/Profile"
LimitedProfile:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/LimitedProfile"
ExtendedProfile:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ExtendedProfile"
IsInboxEnabled:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/IsInboxEnabled"
AcceptedTosVersion:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/AcceptedTosVersion"
IsWebhookEnabled:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/IsWebhookEnabled"
HttpStatusCode:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/HttpStatusCode"
NewMessageDefaultAddresses:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/NewMessageDefaultAddresses"
EmailAddress:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/EmailAddress"
PreferredLanguages:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PreferredLanguages"
SenderMetadata:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/SenderMetadata"
Service:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/Service"
ServiceTupleCollection:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ServiceTupleCollection"
PaginatedServiceTupleCollection:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PaginatedServiceTupleCollection"
ServicePublic:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ServicePublic"
ServiceId:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ServiceId"
ServiceTuple:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ServiceTuple"
ServiceName:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/ServiceName"
OrganizationName:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/OrganizationName"
DepartmentName:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/DepartmentName"
CIDR:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/CIDR"
Timestamp:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/Timestamp"
HttpsUrl:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/HttpsUrl"
TimeToLiveSeconds:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/TimeToLiveSeconds"
NewMessage:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/NewMessage"
MessageContent:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageContent"
MessageStatusValue:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageStatusValue"
MessageStatus:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/MessageStatus"
PreferredLanguage:
$ref: "https://raw.githubusercontent.com/teamdigitale/io-functions-commons/master/openapi/definitions.yaml#/PreferredLanguage"
responses: {}
parameters:
PaginationRequest:
name: cursor
in: query
type: string
minimum: 1
description: An opaque identifier that points to the next item in the collection.
x-example: 01BX9NSMKVXXS5PSP2FATZM123
FiscalCode:
name: fiscal_code
in: path
type: string
maxLength: 16
minLength: 16
required: true
description: The fiscal code of the user, all upper case.
pattern: "[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]"
x-example: SPNDNL80R13C555X
consumes:
- application/json
produces:
- application/json
securityDefinitions:
SubscriptionKey:
type: apiKey
name: Ocp-Apim-Subscription-Key
in: header
description: The API key obtained through the developer portal.