Financeiro API

Introdução

O Financeiro possui uma API REST para interagir com seus recursos, através de XML ou JSON sobre HTTP, usando todos principais verbos HTTP (GET, POST, PUT, DELETE). Cada recurso possui sua própria URL e pode ser manipulado de maneira isolada, tentando assim seguir os princípios REST ao máximo.

Autenticação

Todo acesso à API é feito do ponto de vista de um usuário existente no Financeiro. Assim sendo, toda requisição à API deverá ser autenticada. A autenticação é feita via HTTP Basic, porém ao invés de passar o login e senha do usuário, como é tradicional, deve-se fornecer o "Token do módulo Financeiro" do usuário (Disponível no menu "Gerenciar meu perfil", aba "Segurança".) no campo 'login' e nada no campo 'password'.

Alguns clientes HTTP podem reclamar do fato do campo 'password' estar vazio, nesse caso pode-se informar 'X' como senha que o sistema irá ignorar.

Exemplo de chamada API autenticada (onde 7ezUPAqq8T1ny0w1bSXr é o authentication_token do usuário):

Exemplo de Requisição utilizando o comando curl

$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H "Accept: application/json" -H "Content-type: application/json" https://financeiro.fintera.com.br/people/816
$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H "Accept: application/xml" -H "Content-type: application/xml" https://financeiro.fintera.com.br/people/816

Exemplo de Resposta

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 26 Jan 2011 12:56:01 GMT
[
  {
    "person":
      {
        "created_at":"2011-07-18T10:56:29-03:00",
        "customer":true,
        "federation_subscription_number":null,
        "federation_subscription_number_only_numbers":null,
        "federation_subscription_type_id":null,
        "force_destroy":false,"id":816,
        "imported_from_sync":false,
        "modified_by_sync":false,"name":"Fulano",
        "supplier":true,
        "updated_at":"2011-07-18T10:56:29-03:00","type":"NaturalPerson"
      }
    }
  ]
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Date: Wed, 26 Jan 2011 12:56:01 GMT
<?xml version="1.0" encoding="UTF-8"?>
<people type="array">
  <person>
    <created-at type="dateTime">2011-07-18T10:56:29-03:00</created-at>
    <customer type="boolean">true</customer>
    <federation-subscription-number nil="true"/>
    <federation-subscription-number-only-numbers nil="true"/>
    <federation-subscription-type-id type="integer" nil="true"/>
    <force-destroy type="boolean">false</force-destroy>
    <id type="integer">816</id>
    <imported-from-sync type="boolean">false</imported-from-sync>
    <modified-by-sync type="boolean">false</modified-by-sync>
    <name>Fulano</name>
    <supplier type="boolean">true</supplier>
    <updated-at type="dateTime">2011-07-18T10:56:29-03:00</updated-at>
    <type>NaturalPerson</type>
  </person>
</people>

Já a mesma solicitação sem os parâmetros de autenticação (ou com valores errados), resultaria em:

Exemplo de Requisição com error utilizando o comando curl

$ curl -X GET -H "Accept: application/json" -H "Content-type: application/json" https://financeiro.fintera.com.br/people/816
$ curl -X GET -H "Accept: application/xml" -H "Content-type: application/xml" https://financeiro.fintera.com.br/people/816

Exemplo de Resposta com Erro

HTTP/1.1 401 Unauthorized
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/json; charset=utf-8
{"error":"unauthenticated"}
HTTP/1.1 401 Unauthorized
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<errors>
  <error>unauthenticated</error>
</errors>

Restrição

Toda resposta de requisição conterá os headers X-RateLimit-Limit, X-RateLimit-Reset e X-RateLimit-Remaining, significando respectivamente o limite de requisições por minuto, a data em que a contagem será resetada e quantas requisições restam.

Cada token de autorização está limitado a 100 requests por minuto. Após atingir a cota, todo acesso irá retornar erro 429 Too Many Requests até que o número de acessos seja resetado. Os acessos são resetados de 1 em 1 minuto, ou seja, se você realizou um request às 17:43:53, o reset acontecerá às 17:44:00 e não 17:44:53.

No exemplo abaixo, após o usuário ter feito 100 requisições, temos a tentativa número 101:

Exemplo de Requisição utilizando o comando curl

$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H "Accept: application/json" -H "Content-type: application/json" https://financeiro.fintera.com.br/people/816
$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H "Accept: application/xml" -H "Content-type: application/xml" https://financeiro.fintera.com.br/people/816

Exemplo de Resposta

HTTP/1.1 429 TOO MANY REQUESTS
Content-Type: application/json; charset=utf-8
Date: Wed, 26 Jan 2011 12:56:45 GMT
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Reset: Wed, 26 Jan 2011 12:57:00 GMT
X-RateLimit-Remaining: -1

Retry Later
HTTP/1.1 429 TOO MANY REQUESTS
Content-Type: application/json; charset=utf-8
Date: Wed, 26 Jan 2011 12:56:45 GMT
Retry-After: 60
X-RateLimit-Limit: 20
X-RateLimit-Reset: Wed, 26 Jan 2011 12:57:00 GMT
X-RateLimit-Remaining: -1
Retry Later

Múltiplas contas

Caso você possua acesso a várias contas, é necessário informar o ID da conta que deseja utilizar. Isto é feito através do parâmetro ACCOUNT_ID no cabeçalho da requisição. Se for passado o ID de uma conta que você não tenha acesso, um erro será retornado.

Exemplo de Requisição utilizando o comando curl

$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H "Accept: application/json" -H "Content-type: application/json" -H "ACCOUNT_ID: 1" https://financeiro.fintera.com.br/people/816
$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H "Accept: application/xml" -H "Content-type: application/xml" -H "ACCOUNT_ID: 1" https://financeiro.fintera.com.br/people/816

Exemplo de Resposta

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 26 Jan 2011 12:56:01 GMT
[
  {
    "person":
      {
        "created_at":"2011-07-18T10:56:29-03:00",
        "customer":true,
        "federation_subscription_number":null,
        "federation_subscription_number_only_numbers":null,
        "federation_subscription_type_id":null,
        "force_destroy":false,"id":816,
        "imported_from_sync":false,
        "modified_by_sync":false,"name":"Fulano",
        "supplier":true,
        "updated_at":"2011-07-18T10:56:29-03:00","type":"NaturalPerson"
      }
    }
  ]
HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Date: Wed, 26 Jan 2011 12:56:01 GMT
<?xml version="1.0" encoding="UTF-8"?>
<people type="array">
  <person>
    <created-at type="dateTime">2011-07-18T10:56:29-03:00</created-at>
    <customer type="boolean">true</customer>
    <federation-subscription-number nil="true"/>
    <federation-subscription-number-only-numbers nil="true"/>
    <federation-subscription-type-id type="integer" nil="true"/>
    <force-destroy type="boolean">false</force-destroy>
    <id type="integer">816</id>
    <imported-from-sync type="boolean">false</imported-from-sync>
    <modified-by-sync type="boolean">false</modified-by-sync>
    <name>Fulano</name>
    <supplier type="boolean">true</supplier>
    <updated-at type="dateTime">2011-07-18T10:56:29-03:00</updated-at>
    <type>NaturalPerson</type>
  </person>
</people>

Já a mesma solicitação sem o ACCOUNT_ID no cabeçalho, resultaria em:

Exemplo de Requisição com error utilizando o comando curl

$ curl -X GET -H "Accept: application/json" -H "Content-type: application/json" https://financeiro.fintera.com.br/people/816
$ curl -X GET -H "Accept: application/xml" -H "Content-type: application/xml" https://financeiro.fintera.com.br/people/816

Exemplo de Resposta com Erro

HTTP/1.1 422 Unprocessable Entity
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/json; charset=utf-8
{
  "error":"O cabeçalho da requisição não possui o atributo ACCOUNT_ID",
  "status":"unprocessable_entity",
  "accounts": [{"account":{"id":1,"name":"Conta Um"}},{"account":{"id":2,"name":"Conta 2"}}]
}
HTTP/1.1 422 Unprocessable Entity
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<errors>
  <error>O cabeçalho da requisição não possui o atributo ACCOUNT_ID</error>
  <status>unprocessable_entity</status>
  <accounts type="array">
    <account>
      <id type="integer">1</id>
      <name>Conta Um</name>
    </account>
    <account>
      <id type="integer">2</id>
      <name>Conta Dois</name>
    </account>
  </accounts>
</errors>

Caso informe um ACCOUNT_ID inexistente, o resulta em:

Exemplo de Requisição com error utilizando o comando curl

$ curl -X GET -H "Accept: application/json" -H "Content-type: application/json" -H "ACCOUNT_ID: 1000" https://financeiro.fintera.com.br/people/816
$ curl -X GET -H "Accept: application/xml" -H "Content-type: application/xml" -H "ACCOUNT_ID: 1000" https://financeiro.fintera.com.br/people/816

Exemplo de Resposta com Erro

HTTP/1.1 422 Unprocessable Entity
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/json; charset=utf-8
{
  "error":"A conta informada não existe",
  "status":"unprocessable_entity",
  "accounts": [{"account":{"id":1,"name":"Conta Um"}},{"account":{"id":2,"name":"Conta 2"}}]
}
HTTP/1.1 422 Unprocessable Entity
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<errors>
  <error>A conta informada não existe</error>
  <status>unprocessable_entity</status>
  <accounts type="array">
    <account>
      <id type="integer">1</id>
      <name>Conta Um</name>
    </account>
    <account>
      <id type="integer">2</id>
      <name>Conta Dois</name>
    </account>
  </accounts>
</errors>

Autorização

Apenas usuários de contas em planos Plus ou superior têm acesso autorizado à API. Caso o acesso à API seja feito usando o authentication_token de um usuário cujo plano não permite acesso à API, uma resposta de erro 403 Forbidden será retornada.

Exemplo de Resposta com Erro

HTTP/1.1 403 Forbidden
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/json; charset=utf-8
{"error":"Seu plano não permite o uso da API."}
HTTP/1.1 403 Forbidden
Date: Mon, 17 Jan 2011 19:54:21 GMT
Content-Type: application/xml; charset=utf-8
<?xml version="1.0" encoding="UTF-8"?>
<errors>
  <error>Seu plano não permite o uso da API.</error>
</errors>

Uso Geral

Por padrão, a API deve ser acessada através das mesmas URLs e verbos HTTP da interface HTML normal, adicionando-se o formato desejado (.xml ou .json) ao final da URL, ou então passando os headers Content-type e Accept na requisição HTTP com os valores de acordo com o formato desejando (application/xml ou application/json, respectivamente).

Compressão gzip

A compressão gzip é uma compressão sem perda de dados. As vantagens de utilizá-la são o menor uso da largura de banda e a maior velocidade na resposta.

Para utilizar o recurso da compressão gzip nas requisições, basta adicionar o header Accept-Encoding com o valor gzip. Caso a resposta esteja comprimida, ela conterá um header Content-Encoding com o valor gzip. Em alguns casos, mesmo que o servidor mande uma resposta comprimida, a requisição pode vir sem compressão, pois pode existir algum proxy no caminho da resposta que realize a descompressão dos dados (podendo ou não remover o header Content-Encoding.

$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H 'Accept: application/json' -H 'Content-type: application/json' -H 'Accept-Encoding: gzip' https://financeiro.fintera.com.br/entities/2593/attachments/25940
$ curl -u 7ezUPAqq8T1ny0w1bSXr -X GET -H 'Accept: application/xml' -H 'Content-type: application/xml' -H 'Accept-Encoding: gzip' https://financeiro.fintera.com.br/entities/2593/attachments/25940

Como exemplo, a requisição acima sem compressão, possui um tamanho de 604 bytes. Enquanto a mesma requisição, comprimida, possui um tamanho de 290 bytes.

CORS


O Financeiro permite que outros sistemas façam requisições externas, ou seja, chamadas feitas de domínios diferentes de financeiro.fintera.com.br.

Esse tipo de requisição é chamada de cross-origin HTTP request (CORS) e permite que sistemas externos consumam a API do Financeiro via javascript, sem a necessidade de criar um proxy para o endpoint do Financeiro em sua aplicação.

Por questões de segurança, somente chamadas do tipo GET são permitidas utilizando esta técnica, não sendo possível incluir, alterar ou excluir qualquer informação através deste tipo de requisição.