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.
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):
$ 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
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:
$ 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
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>
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:
$ 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
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
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.
$ 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
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:
$ 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
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:
$ 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
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>
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.
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).
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.
O Financeiro permite que outros sistemas façam requisições externas, ou seja, chamadas feitas de domínios diferentes de app.myfinance.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.