Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.
Comentário: Complementando filtros simples, referente a estruturas aninhadas; Ajustando exemplos, principalmente dos campos expansíveis.

...

Extrair

25/03/2019 - APIs podem conter domínio de negócio na URL; inclusão do atributo _messages nas mensagens de sucesso (retornos simples e coleções). 

03/09/2019 - Exemplo de aplicação de filtro simples em estruturas com entidades aninhadas.

Índice

Índice
maxLevel4
outlinetrue
exclude.*ndice
stylenone

...

  • Entidade apresentada no plural e uso correto do parâmetro na url.
    • https://totvs.com/api/fdn/v1/users/{id}
  • Ações sobre entidades no caminho da url e como parâmetro da url.
    • https://totvs.com/api/bpm/v1/workflows/{id}?action=execute
    • https://totvs.com/api/bpm/v1/workflows/{id}/send
  • Relacionando entidades diretamente no caminho
    • https://totvs.com/api/fdn/v1/users/{alias}/communities
    • https://totvs.com/api/social/v1/communities/{id}/users
  • URL com suporte a campos expansíveis
    • https://totvs.com/api/fdn/v1/users/{alias}?expand=prop1.subprop,prop2
  • Ordenando e paginando coleções
    • https://totvs.com/api/fdn/v1/users?order=name,-age&page=2&pageSize=20
  • URL com Query Param e nome composto:
    • https://totvs.com/api/fdn/v1/users/?firstName=joao


Exemplo de URLS NÃO amigáveis e que deve ser evitadas

  • Redundância na definição da url
    • https://totvs.com/api/communty/listCommunities
  • Ordenação especificada na url
    • https://totvs.com/api/communty/listCommunitiesWithRelevance
  • Verbos definidos na url ao invés de usar o verbo HTTP e falta de pluralização no substantivo
    • https://totvs.com/api/correlationquestion/create
    • https://totvs.com/api/user/create
    • https://totvs.com/api/user/delete

...

Consideramos uma API o agrupamento de endpoints que façam parte da mesma unidade de negócio, criar um novo grupo de endpoints implica em preocupações como versionamento, disponibilidade e documentação. Usamos como base a estrutura "{protocolo}://{host}/{api}/{agrupador}/{dominio}/{versao}/{recurso}". Ex: https://fluig.totvs.com/api/ecm/security/v1/users. A partir deste ponto deve-se considerar como regra básica a complexidade necessária para descobrir estes endpoints, ou seja, o agrupamento deve facilitar e não complicar a descoberta dos serviços.

...

Informações

Importante entender a diferença entre o agrupador e o domínio no nome da API.

O Agrupadoragrupador, é geralmente definido o segmento de atuação da API, é uma maneira de facilitar a localização das API, EX.: Financeiro, Contábil.

Já o domínio é uma subdivisão especifica de determinado módulo, criando assim o escopo de uma determinada API, separando somente seus endpoints, facilitando o uso de ferramentas de gerenciamento de API EX.: Financeiro/ContasPagar, Financeiro/ContasReceber, Contábil/Lançamentos, Contábil/Balanço.

...

Todos os endpoints de coleção devem suportar ordenação. A definição de como a lista deve ser ordenada é definida no parâmetro de urlquery order respeitando as seguintes regras:

  • O parâmetro de query da urlURL deve ter o nome order;
  • O valor do parâmetro order é uma lista de campos, separada por virgula (,) opcionalmente precedida pelo sinal de subtração (-);
  • A lista deve respeitar a ordem dos campos como descrito na url para fazer a ordenação;
  • Campos precedidos por um sinal de subtração (-) devem ser ordenados de forma decrescente;
  • Campos que omitirem o sinal (subtração) devem ser ordenados de forma crescente.

...

As coleções podem suportar filtro e devedevem usar as técnicas abaixo de acordo com a complexidade exigida pela função:

...

Filtros simples devem usar parâmetros de query no formato propriedade=filtrovalor e as propriedades suportadas e , bem como a forma como elas serão interpretadas, devem estar listadas na documentação do endpoint. Ex:

Bloco de código
languagetext
GET https://totvs.com.br/api/fluig/fdn/v1/users?name=john&surname=doe

Filtros complexos

Filtros complexos e que forneçam uma linguagem de filtro devem seguir o padrão definido para os filtros no documento ODATA na versão 4. (opcional)

Opcionalmente, em endpoints que tenham estrutura com entidades aninhadas, a propriedade usada para filtrar os resultados deve usar o formato propriedade_pai.propriedade_filho.

Não há limite para os níveis que se pode referenciar, mas deve-se levar em consideração o quão complexa pode ser a implementação. Quando houver limitação quanto a quantidade de níveis referenciados, importante documentar na API.

Exemplo de uso do filtro com propriedades aninhadas:

Bloco de código
languagetext
GET https://totvs.com.br/api/fluig/fdn/v1/users?communities.name="Vendas"


No exemplo acima, serão retornados todos os usuários (users) cuja propriedade name (que está contida na propriedade communities da entidade users) seja igual a "Vendas".


Filtros complexos

Filtros complexos e que forneçam uma linguagem de filtro devem seguir o padrão definido para os filtros no documento ODATA na versão 4. (opcional)

Exemplo de filtros no Exemplo de filtros no padrão odata:

OperatorDescriptionExample
Logical Operators
eqEqual/Suppliers?$filter=Address/City eq 'Redmond'
neNot equal/Suppliers?$filter=Address/City ne 'London'
gtGreater than/Products?$filter=Price gt 20
geGreater than or equal/Products?$filter=Price ge 10
ltLess than/Products?$filter=Price lt 20
leLess than or equal/Products?$filter=Price le 100
andLogical and/Products?$filter=Price le 200 and Price gt 3.5
orLogical or/Products?$filter=Price le 3.5 or Price gt 200
notLogical negation/Products?$filter=not endswith(Description,'milk')
Grouping Operators
( )grouping/Products?$filter=(Price lt 5)


Filtros de data Modificação (opcional)

Opcionalmente, a api pode disponibilizar o filtro especial "datemodified" para retornar registros alterados a partir de uma determinada data. Ex:

...

Bloco de código
languagetext
GET https://totvs.com.br/api/fluig/fdn/v1/users?$filter=datemodified ge '2018-01-01' and datemodified le '2018-01-31'


Paginação

Todos os endpoints de coleção devem suportar paginação. A definição de como a coleção deve ser paginada é definida pelos parâmetros de url page e pageSize respeitando as seguintes regras:

...

MétodoDescriçãoIdempotente
GETRetorna o valor corrente do objeto.Sim
PUT

Sobrescreve o objeto quando aplicável. Por exemplo: O cliente gostaria de sobrescrever o usuário com novos valores:

Bloco de código
languagetext
PUT http://totvs.com/api/users/10

{
  name: "John",
  age: 2025,
  ...
}
Informações
titleImportante

Caso o cliente não informe alguma propriedade para ser atualizada, está deve ser considerada nula. Está informação deve estar clara na documentação do método para que o cliente não há utilize inadvertidamente, ou pode-se optar por não implementá-la.

Sim
DELETE

Exclui o objeto.

Sim
POSTCria um novo objeto ou submete um comando ao objeto.Não
HEADRetorna os metadados da requisição em casos em que o cliente não precisa do corpo das requisições do tipo GET.Sim
PATCH

Também usado para atualizar uma entidade, mas diferente do PUT, recebe em seu corpo uma série de instruções ou o estado no qual o cliente gostaria que a entidade estivesse no final da operação. Deve ser tratado de forma atômica, ou seja, ou todas as instruções foram completadas com sucesso ou deve retornar erro ao cliente.

PATH pode causar efeitos colaterais e portanto não é considerado seguro ou idempotente.

Bloco de código
languagetext
PATCH http://totvs.com/api/fluig/fdn/v1/users/10

[
  { "op": "replace", "path": "/name", "value": "Bob" }
]

O servidor deverá implementar o serviço de modo que apenas o nome do usuário seja atualizado e todas as outras propriedades sejam mantidas.

Não
OPTIONSDeve retornar pelo menos o campo Allow no cabeçalho da resposta listando os verbos suportados pelo endpoint.Sim

...

JSON deve ser o formato padrão para mensagens mensagens. 

Tipos de dados JSON

Os tipos de dados e a notação para os campos da mensagem JSON deve seguir os padrões descritos no documento ECMA-404.

...

Bloco de código
languagejs
GET http://totvs.com.br/api/fluig/fdn/v1/users/1

{
  name: "John10

{
    _expandables: ["permissions","communities","detailedInformation"],
    id: 10,
    name: "John",
    surname: "Doe",
  surname  age: 25,
    country: "DoeUS"
}

Opcionalmente, o atributo _messages pode ser incluído no objeto retornado para fornecer alguma informação complementar ao processamento realizado (mensagens de aviso, de negócio, etc.). O formato do objeto de mensagem segue o padrão anteriormente descrito, para mensagens de erro.

Bloco de código
languagejs
GET http://totvs.com.br/api/fluig/fdn/v1/users/110

{
    _expandables: ["permissions","communities","detailedInformation"],
    id: 10,
    name: "John",
    surname: "Doe",
    age: 25,
    country: "US"
    _messages: [{
	    code: "INFO",
        message: "ThisEsta isé anuma informativemensagem messageinformativa",
        detailedMessage: "SomeMais detailsdetalhes aboutsobre thisesta informativemensagem messagepodem canser be found here!vistos aqui."
    }]
}


Âncora
ApiSuccessMsgColl
ApiSuccessMsgColl
Mensagens de sucesso para coleções

...

Bloco de código
languagejs
{
  hasNext: true,
  items: [
    {},
    {},
    ...
  ],
  _messages: [{
    code: "INFO",
    message: "someUma infomensagem messageinformativa.",
    detailedMessage: "detailsDetalhes aboutrelativos thea info messagemensagem."
  }]
}

A estrutura acima é a mínima esperada para respostas de coleção. Entretanto, pode-se retornar mais campos se for necessário desde que a estrutura básica se mantenha. Por exemplo:

...

Bloco de código
languagejs
GET http://totvs.com.br/api/fluig/fdn/v1/users/10

{
    _expandables: ["Permissions"permissions","communities","detailedInformation"],
  name    id: 10,
    name: "John",
    surname: "Doe",
    age: 1825,
    country: "US"
}


Caso os únicos campos interessantes para o cliente sejam o "name" e "age" ele pode reduzir a quantidade de dados usando o parâmetro fields. Ex:

Bloco de código
languagejs
GET http://totvs.com.br/api/fluig/fdn/v1/users/10?fields=name,age

{
    name name: "John",
    age: 1825
}
Informações

O parâmetro fields deve ter precedência sobre o parâmetro expand. Isso que dizer que o campo não será retornado a menos que esteja na lista de campos do parâmetro fields mesmo que ele esteja presente na lista de campos a serem expandidos do parâmetro expand.

...

Bloco de código
languagejs
GET https://totvs.com/api/fluig/fdn/v1/users/10


{
        _expandables: ["permissions", "communities", "detailedInformation"],
        id: 10,
    name: "John",
   name surname: "UsuárioDoe",
    age: 25,
    agecountry: 25"US"
}

Caso o cliente queira expandir as propriedades, ele deve então fazer uma requisição informando o parâmetro expand na url e passando como valor uma lista separada por virgula (,) dos campos exatamente como descritos no campo _expandables.

...

Bloco de código
languagejs
GET https://totvs.com/api/fluig/fdn/v1/users/10?expand=communities

{
        _expandables: ["permissions", "communities","detailedInformation"]  # refere-se aos atributos do objeto pai (1o nível)
   ,
     id: 10
        name: "Usuário"
        age: 25
   ,
     communitiesname: ["John",
    surname: "Doe",
    age: 25,
  {
  country: "US",
    communities: [{
        _expandables: ["Permissionspermissions"],   # refere-se ao atributo permissions destede objeto-filhocommunities (2o nivel)
                name: "Vendas",
                photoUrl: "https://totvs.com/communities/1/photo"
            },
            {
                _expandables: ["permissions"],  # refere-se ao atributo permissions destede objeto-filho
        communities
        name: "Outra comunidade",
                photoUrl: "https://totvs.com/communities/2/photo"
            }
        ]
      
}

Note que as propriedades do objeto expandido não são retornadas por padrão. O cliente pode solicitar que as propriedades dos objetos sejam expandidas separando as sub-propriedades com ponto (.). Usando o exemplo acima, o usuário gostaria de expandir as permissões das comunidades da entidade usuário:

...

Bloco de código
languagejs
GET https://totvs.com/api/fluig/fdn/v1/users/10?expand=communities.permissions

{
        _expandables: ["permissions", "communities","detailedInformation"],
        id: 10,
        name: "UsuárioJohn",
    surname: "Doe",
    age: 25,
       country: "US",
    communities: [{
            name: "Vendas",
            photoUrl: "https://totvs.com/communities/1/photo",
            permissions: {
                isAdmin: true,
                canView: true
            }
        }, {
            name: "Outra comunidade",
            photoUrl: "https://totvs.com/communities/2/photo",
            permissions: {
                isAdmin: true,
                canView: true
            }
        }]
      
}


Informações
titlelimites

A API deve suportar a expansão de até dois níveis de propriedade de retorno, ex: prop1.prop2.prop3.

Nos casos em que o objeto tenha uma sub coleção é recomendável que o número máximo de registros dessa coleção não ultrapasse 20 registros. Se houver a necessidade de retornar mais itens, considerar criar um endpoint especifico para retornar a coleção com suporte a filtro, ordenação, etc.

Requisições Assíncronas

...

Ao realizar um POST, PUT ou DELETE em um recurso que executa seu processamento de maneira assíncrona, o mesmo DEVE retornar o código 202 Accepted, com cabeçalho location apontando para um recurso temporário que permita o acompanhamento do status da requisição.

Informações
titleAtenção

A implementação do modelo assíncrono não é obrigatório. A opção por este modelo deve basear no tempo e recurso necessário para o processamento de uma requisição.

Processando

Ao realizar o GET no recurso temporário, enquanto ainda estiver sendo processado, o mesmo DEVE retornar o código 200 e um JSON com a propriedade status definida como “pending”. Esse retorno PODE, e é uma boa prática, retornar a propriedade progress, informando o percentual de conclusão da operação solicitada.

...


Para cancelar a execução do processamento, quando permitido, o client deve executar DELETE no recurso temporário.

Finalizada – Erro

Ao acessar o recurso temporário que finalizou seu processamento com erros, retorna o erro adequado, conforme definido em Mensagens de Erro  e Código 4xx versus 5xx

Finalizada – Sucesso

Ao acessar o recurso temporário que finalizou seu processamento com sucesso, o mesmo DEVE retornar o código 303 (See Other) com o cabeçalho Location, apontando para endereço do real recurso criado.

A deleção do recurso temporário não é obrigatória e PODE ser feita através de DELETE do client, ou através do próprio server, após um tempo determinado para expirá-lo. Nesse segundo caso, ao tentar acessá-lo DEVE retornar 410 (Gone).

Padrão HATEOAS

...

Esse estilo de arquitetura permite usar links no conteúdo da resposta para que o cliente possa navegar dinamicamente para o recurso apropriado. Isso é conceitualmente o mesmo que um usuário da Web navegando pelas páginas e clicando nos hiperlinks apropriados para atingir uma meta final.

O padrão HATEOAS deve ser utilizado no retorno de entidades relacionadas a principal e que não são parte do recurso principal. Ex.

Bloco de código
languagejs
GET https://totvs.com/api/fluig/fdn/v1/users/10
{
	_expandables: ["permissions","communities","detailedInformation"],
       "id" : 10,
    name: "John",
   "name" surname: "UsuárioDoe",
    age: 25,
   "age" country: 25"US",
		    "links": [
        { "rel": "communities",  "href": "/fdn/v1/communities/5" },
        { "rel": "permissions",  "href": "/fdn/v1/permissions/30" }
          ]             
}

Versionamento


As APIs devem ser versionadas sempre que alguma alteração quebrar o contrato entre o usuário e a plataforma, a versão deve estar presente na URI e deve estar no forma v{major.minor}.
A versão major indica uma grande versão da API, ou seja, a API mudou significativamente em seu formato e comportamento.
A versão minor indica uma alteração que pode quebrar o código do cliente.
Por exemplo:

...

O numero da versão indica para o cliente quando alguma alteração pode "quebrar" o código escrito por ele. Deve-se tomar um cuidado especial no processo de versionamento para que o cliente esteja ciente dessas alterações e a frequência com que elas acontecem usando algum tipo de release notes ou documentação.

Alterações que devem gerar uma nova versão "major"

...

  • URIs foram removidas ou renomeadas;
  • Foram removidos campos do retorno de um endpoint;
  • Foi removido o suporte a um método do endpoint (GET, PUT, POST, etc);
  • Um novo parâmetro obrigatório é exigido para o correto funcionamento do endpoint;
  • Um novo endpoint foi adicionado a API.

Alterações que NÃO devem gerar uma nova versão "major"

...

  • Um novo formato de retorno é suportado pelo endpoint;
  • Novas propriedades são retornadas na entidade de retorno do endpoint;
  • Novos parâmetros opcionais podem ser passados para o endpoint.

...