Skip to main content

API Docs

API documentation extracted from the code

Starts the login process by token, the backend sends the email with the token

POST {{URL}}/api/v2/login/token/init

lang is optional, it receives the language in which the email will be sent with the code

headers:{
"Content-type":"application/json",
"Accept":"application/json"
}
request:{
"email":"user@email.com",
"lang":"en|es|pt|it",
}
http_code 201
response:{}

Receive login token

POST {{URL}}/api/v2/login/token/validate

headers:{
"Content-type":"application/json",
"Accept":"application/json"
}
request:{
"email":"user@email.com",
"code":"token",
}
http_code 200
response:{
"access_token": "access_token",
"token_type": "bearer",
"expires_in": 3600
}

Social login: google, facebook, apple

The providers must be google, facebook or apple.

For Apple, according to the tests we did, client-side gets id_token and access_token, but unlike the other providers it is the id_token that must be sent as a parameter called access_token to the backend.

POST {{URL}}/api/v2/login/social/{{google||facebook||apple}}

headers:{}
request:{
"access_token":"access_token",
}
http_code 200
response:{
"access_token": "access_token",
"token_type": "bearer",
"expires_in": 3600
}
http_code 401
response:{
"message": "Unauthorized."
}

It brings the data of the user and the tenants to which it belongs

GET {{URL}}/api/v2/user

headers:{
"Authorization": "Bearer {{access_token}}",
}
request:{}
http_code 200
response:{
"id": 12345678,
"admin": false,
"email": "usertest@test.publica.la",
"picture": "https://www.xxxxxxx.com/avatar/xxxxx9f?s=160&d=mm&r=g",
"tenants": [
{
"id": 1,
"logo": "https://xxxxxxxxx.test/publicala/logo/logo_12345675.png",
"name": "Publica",
"colors": {
"primary": "#D5D5D5",
"secondary": "#0080FF"
}
},
{
"id": 2,
"logo": "https://xxxxxxxxxxx.test/publicala/logo/logo.png",
"name": "Barcelona Digital",
"colors": {
"primary": "#FFFFFF",
"secondary": "#ea5b0c"
}
}
]
}
http_code 401
response:{
"message": "The given data was invalid.",
}

Get the user's general continue-reading of all tenants to which it belongs

GET {{URL}}/api/v2/user/continue-reading

params:{
"page":"1",
"count":"10"
}
headers:{
"Authorization": "Bearer {{access_token}}"
}
request:{
}
http_code 200
response:{
"filter_name": "continue_reading",
"filter_value": "continue_reading",
"title": "Seguir Leyendo",
"data": [
{
"id": 153598,
"tenant_id": 1,
"name": "The Governor and the Rebel",
"slug": "the-governor-and-the-rebel",
"cover_url": "https://xcxcxcxc.publica.la/coresourceplus/issues/2020/11/xcxcxcxcxc_cover.jpg",
"published_at": "2020-11-20 03:00:00",
"type": "epub",
"description": "XXXXXXXXXXXXXX",
"external_id": "12345678999",
"number_of_pages": 30,
"lang": "pt",
"author": "Azevedo, Israel Belo De",
"publisher": "Editora Prazer Da Palavra",
"bisac": "Autoayuda > General"
},
{
"...":"..."
},
],
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"per_page": 6,
"to": 2,
"total": 2
}
}

It brings the list of available sliders (today continue_reading and latest_issues). Each slider contains 10 publications

GET {{URL}}/api/v2/library

params:{
"page":"1",
"count":"6",
}
headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request:{
}
http_code 200
response:{
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"per_page": 6,
"to": 2,
"total": 2
},
"data": [
{
"filter_name": "section",
"filter_value": "continue_reading",
"title": "Seguir Leyendo",
"data": [
{
"id": 153598,,
"tenant_id": 1,
"name": "The Governor and the Rebel",
"slug": "the-governor-and-the-rebel",
"cover_url": "https://xcxcxcxc.publica.la/coresourceplus/issues/2020/11/xcxcxcxcxc_cover.jpg",
"published_at": "2020-11-20 03:00:00",
"type": "epub",
"description": "XXXXXXXXXXXXXX",
"external_id": "12345678999",
"number_of_pages": 30,
"lang": "pt",
"author": "Azevedo, Israel Belo De",
"publisher": "Editora Prazer Da Palavra",
"bisac": "Autoayuda > General"
},
{
"...":"..."
},
],
},
{
"filter_name": "section",
"filter_value": "latest_issues",
"title": "Ultimas publicaciones",
"data": [
{
"id": 153598,,
"tenant_id": 1,
"name": "The Governor and the Rebel",
"slug": "the-governor-and-the-rebel",
"cover_url": "https://xcxcxcxc.publica.la/coresourceplus/issues/2020/11/xcxcxcxcxc_cover.jpg",
"published_at": "2020-11-20 03:00:00",
"type": "epub",
"description": "XXXXXXXXXXXXXX",
"external_id": "12345678999",
"number_of_pages": 30,
"lang": "pt",
"author": "Azevedo, Israel Belo De",
"publisher": "Editora Prazer Da Palavra",
"bisac": "Autoayuda > General"
},
{
"...":"..."
},
],
},
],
}

Bring the detail of a section

For now continue-reading or latest-publications. 
The filter should be composed as /api/v2/library?{{filter_name}}={{filter_value}}

GET {{URL}}/api/v2/library/filter?section=continue-reading
params:{
"page":"1",
"count":"6",
}
headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request:{
}
http_code 200
response:{
"filter_name": "section",
"filter_value": "continue_reading",
"title": "Seguir Leyendo",
"data": [
{
"id": 153598,
"tenant_id": 1,
"name": "The Governor and the Rebel",
"slug": "the-governor-and-the-rebel",
"cover_url": "https://xcxcxcxc.publica.la/coresourceplus/issues/2020/11/xcxcxcxcxc_cover.jpg",
"published_at": "2020-11-20 03:00:00",
"type": "epub",
"description": "XXXXXXXXXXXXXX",
"external_id": "12345678999",
"number_of_pages": 30,
"lang": "pt",
"author": "Azevedo, Israel Belo De",
"publisher": "Editora Prazer Da Palavra",
"bisac": "Autoayuda > General"
},
{
"...":"..."
},
],
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"per_page": 10,
"to": 10,
"total": 94
}
}

Reader settings

GET {{URL}}/api/v2/reader/settings/{{issue_id}}
headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request:{
}
http_code 200
response:{
"token": "xxx",
"coniglio_track_token": "xxx",
"features": {
"tts": false,
"search": false,
"concurrency_limit": false,
"chinese_voice": false
},
"settings": {
"tenant": {
"lang": "es",
"reader_token_session_url": "https://tenant.publica.la/api/v1/reader/session",
"exit_url": "https://tenant.publica.la/library",
"reader": {
"pdf": {
"layout": "single"
},
"tts": false,
"theme": "light",
"elefante": [],
"customStyles": null
},
"preview": true
},
"user": {
"pdf": {
"layout": null
},
"epub": {
"zoom": null,
"layout": null
},
"theme": "light"
}
},
"issue": {
"name": "Celebração dos hábitos bons",
"description": "Celebração dos hábitos bons....",
"file_type": "epub",
"tags": {
"author": [
"Azevedo, Israel Belo De"
],
"keyword": [
"Hábitos",
"Autodisciplina",
"Rotinas"
],
"edition": [
"Edición Alguna"
]
},
"issue_url": "https://tenant.publica.la/reader/celebracao-dos-habitos-bons",
"issue_full_url": "https://tenant.publica.la/api/v2/reader/settings/440317",
"issue_tenant_id": 1,
"publication_date": "2020",
"user": {
"issue_is_favorite": false,
"last_location": {
"page": 4
}
},
"twitter_user": "tenant"
},
"volpe_url": "https://volpe.test",
"volpe_url_proxied": "https://volpe.test"
}

Publication download

Gets the publication data to be sent to the reader, with the links to download files. These file paths must be replaced by the local ones in the device filesystem before sending to the reader.

GET {{URL}}/api/v2/content/{{issue_id}}/download

headers:{
"Authorization": "Bearer {{access_token}}",
}
request:{
}
http_code 200
response:{
"id": 440317,
"name": "Celebração dos hábitos bons",
"description": "Celebração dos hábitos bons\r\n\r\nO desenvolvimento de hábitos bons permite uma vida com qualidade.\r\nNo entanto, por heranças familiares e por comodismo, muitas pessoas permanecem com uma vida sem hábitos bons, logo sem vida boa.\r\nO livro oferece sugestões práticas para aqueles que, reconhecendo seus hábitos ruins, desejam adquirir novos e bons.\r\nNele, o autor discorre sobre a tragédia dos maus hábitos e ensina como fazer um inventário, que permite a corrida para a mudança e a celebração da vitória.\r\nIsrael Belo de Azevedo usa a Bíblia guia, mas sem esquecer o que vem da filosofia e da psicologia.",
"slug": "celebracao-dos-habitos-bons",
"published_at": {
"timestamp": 1606186800,
"date": "2020-11-24 03:00:00",
"timezone": "+00:00"
},
"table_of_contents": [],
"user_can_read": true,
"file_type": "epub",
"reader_url": "https://revisbarcelona.test/reader/celebracao-dos-habitos-bons",
"cover": "https://minio.test/storage-dev-local.farfalla.test/publicala/issues/2021/11/yeuRsyiXAs92gPnE/a73323a1-dee2-40ba-8066-842826c552d4_cover.jpg",
"thumbnail": "https://minio.test/storage-dev-local.farfalla.test/publicala/issues/2021/11/yeuRsyiXAs92gPnE/a73323a1-dee2-40ba-8066-842826c552d4_cover.jpg",
"url": "https://minio.test/storage-dev-local.farfalla.test/publicala/issues/2021/11/yeuRsyiXAs92gPnE/v1/",
"file_url": "http://localhost:6718/epub/xxx",
"tracks": null,
"files_urls": null,
"packed_file_url": "http://localhost:6718/epub/xxx",
"articles": [],
"payment_links": null,
"prices": {
"BRL": 9.9
},
"author": "",
"pages": null,
"number_of_pages": null,
"external_id": "9786599001772",
"private_material": null,
"access_expires_at": null,
"require_login": 0,
"free": false
}
http_code 401
response:{
"message": "The given data was invalid.",
}

In the response the properties with the path to the file may vary depending on the file type. The following are used:

EPUB:

  • packed_file_url
  • file_url

PDF:

  • files_urls

Audiobook:

  • tracks

The use of these properties can be seen in the old application, in the file issue-file-manager.ts > performDownload() method

The access_expires_at property indicates the expiration of the download, and should be removed from the device (or at least denied access) when the date arrives. Format: YYYYY-MM-DD hh:mm:ss

Send last-location (reader)

The last-location payload varies according to the type of issue, here are some examples of requests according to type

PUT {{URL}}/api/v2/reader/{{issue_id}}/last-location

   headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request for: audiobook
request:{
"lastLocation":
{
"currentSeek":0,
"currentTrack":1
}
}


request for: epub
request:{
"lastLocation":
{
"chapterHref":"titlepage",
"cfi":"/4/2[cover-image]/2"
}
}


request for: pdf
request:{
"lastLocation":
{
"page": 3
}
}

http_code 200
response:{
"last_location": {...same as request...}
}

Send a user's reader settings

The reader settings payload does not vary according to the type of issue and always contains the keys: theme, epub and pdf.

In case the issue is a PDF, the key_epub_ is sent anyway.

PUT {{URL}}/api/v2/reader/settings

headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request:{
"userReaderSettings": {
"pdf": {
"layout": "single"
},
"epub": {
"zoom": 140,
"layout": "scroll"
},
"theme": "dark"
}
}


http_code 200
response:{
"user_reader_settings": {...same as request...}
}

Set favorite (reader)

POST {{URL}}/api/v2/library/{{issue}}/favorite-issues

headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request:{}

http_code 200
response:{
"is_favorite": true
}

Search single store

The structure of the response is the same as the /library listings

GET {{URL}}/api/v2/search/store?query={{SEARCH_TEXT}}

   headers:{
"Authorization": "Bearer {{access_token}}",
"X-Farfalla-Tenant-Id": "{{tenant_id}}"
}
request:{}

With results
http_code 200
response:{
"filter_name": "search",
"filter_value": {{SEARCH_TEXT}},
"title": "Buscar...",
"data": [
{
"id": 153598,,
"tenant_id": 1,
"name": "The Governor and the Rebel",
"slug": "the-governor-and-the-rebel",
"cover_url": "https://xcxcxcxc.publica.la/coresourceplus/issues/2020/11/xcxcxcxcxc_cover.jpg",
"published_at": "2020-11-20 03:00:00",
"type": "epub",
"description": "XXXXXXXXXXXXXX",
"external_id": "12345678999",
"number_of_pages": 30,
"lang": "pt",
"author": "Azevedo, Israel Belo De",
"publisher": "Editora Prazer Da Palavra",
"bisac": "Autoayuda > General"
},
{
"...":"..."
},
],
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"per_page": 10,
"to": 10,
"total": 94
}
}


Without results
http_code 200
response:{
"filter_name": "search",
"filter_value": {{SEARCH_TEXT}},
"title": "Buscar...",
"data": [],
"meta": {
"current_page": 1,
"from": null,
"last_page": 1,
"per_page": 10,
"to": null,
"total": 0
}
}

Search all stores (no scoped)

The structure of the response is the same as the /library listings.

GET {{URL}}/api/v2/search/global?query={{SEARCH_TEXT}}

   headers:{
"Authorization": "Bearer {{access_token}}",
}
request:{}

With results
http_code 200
response:{
"filter_name": "search",
"filter_value": {{SEARCH_TEXT}},
"title": "Buscar...",
"data": [
{
"id": 153598,
"tenant_id": 1,
"name": "The Governor and the Rebel",
"slug": "the-governor-and-the-rebel",
"cover_url": "https://xcxcxcxc.publica.la/coresourceplus/issues/2020/11/xcxcxcxcxc_cover.jpg",
"published_at": "2020-11-20 03:00:00",
"type": "epub",
"description": "XXXXXXXXXXXXXX",
"external_id": "12345678999",
"number_of_pages": 30,
"lang": "pt",
"author": "Azevedo, Israel Belo De",
"publisher": "Editora Prazer Da Palavra",
"bisac": "Autoayuda > General"
},
{
"...":"..."
},
],
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"per_page": 10,
"to": 10,
"total": 94
}
}


Without results
http_code 200
response:{
"filter_name": "search",
"filter_value": {{SEARCH_TEXT}},
"title": "Buscar...",
"data": [],
"meta": {
"current_page": 1,
"from": null,
"last_page": 1,
"per_page": 10,
"to": null,
"total": 0
}
}

Obtains the reasons for contact/help

GET {{URL}}/api/v2/help

   headers:{
"Authorization": "Bearer {{access_token}}",
}
request:{
"lang":"en|es|pt|it",
}

http_code 200
response:{
"missing-issues": "Faltan publicaciones",
"missing-store": "Faltan tiendas",
"cancel-subscription": "Cancelar suscripción",
"offline-not-working": "No puedo acceder al contenido offline",
"other": "Otro"
}

Send a contact/help request

The subject must be one of the keys obtained in the previous endpoint. The message has a minimum of 10 characters

GET {{URL}}/api/v2/help

   headers:{
"Authorization": "Bearer {{access_token}}",
}
request:{
"subject" : "missing-issues",
"message" : "Mensaje con un minimo de 10 caracteres"
}

http_code 201
response:{}

Validate current session

GET {{URL}}/api/v2/auth/session/validate

This health-check endpoint does not execute any business logic. Its only purpose is to pass through the authentication stack and confirm that:

  1. The current Auth Session is still valid (checked by AuthSessionMiddleware).
  2. The user has not exceeded the concurrent sessions limit (checked by SessionsLimitMiddleware).

If both conditions are met the server replies with 200 OK. Any failure bubbles up from the middlewares as an error status.

GET /api/v2/auth/session/validate HTTP/1.1
Host: {{URL}}
Authorization: Bearer {{access_token}}
Accept: application/json

Response

CodeMeaning
200Session active and within the allowed limits
401Invalid / expired session (unauthenticated)
409Session limit reached for this user
{
"CODE": "success",
"message": "Session is valid"
}

Headers

  • Authorization: Bearer {{access_token}} — token obtained during login.

X

Graph View