Filtros, ordenação e busca
Como filtrar por qualquer campo, combinar condições, ordenar, buscar e paginar nos endpoints da Business API.
Todos os endpoints de listagem da Business API aceitam o mesmo formato de filtro. Você filtra pelos mesmos nomes de campo que aparecem na resposta — datas, valores, textos, status e campos personalizados.
| Parâmetro | Formato | Descrição |
|---|---|---|
filters | JSON (URL-encoded) | Lista de condições { id, operator, value } |
joinOperator | and | or | Como as condições de filters se combinam (padrão: and) |
sort | JSON (URL-encoded) | Lista de ordenações { id, desc } |
search | texto | Busca livre (apenas onde indicado) |
Cada página de endpoint tem a seção Campos filtráveis com a lista exata de campos, o tipo de cada um e quais aceitam ordenação.
Para recortar pela data principal do endpoint, use from/to — mais simples e igual em todos os endpoints (veja Período). filters serve para qualquer outro campo, inclusive outras datas.
Formato de um filtro
[
{ "id": "amount", "operator": "gte", "value": 1000 },
{ "id": "transactionAt", "operator": "isBetween", "value": ["2026-08-01", "2026-08-31"] },
{ "id": "type", "operator": "eq", "value": "DEBIT" }
]id: nome do campo, igual ao da respostaoperator: um dos operadores suportados pelo tipo do campo (tabela abaixo)value: string, número ou lista, conforme o operador — omitido emisEmpty/isNotEmpty
Como filters e sort são JSON dentro da query string, o valor precisa ser URL-encoded:
curl -G "https://api-business.openi.com.br/api/v1/companies/{companyId}/bank-accounts/transactions" \
-H "Authorization: Bearer oak_368ba506f7b2_9f2c..." \
--data-urlencode 'from=2026-08-01' \
--data-urlencode 'filters=[{"id":"amount","operator":"lte","value":-1000},{"id":"operationType","operator":"inArray","value":["PIX","TED"]}]' \
--data-urlencode 'sort=[{"id":"transactionAt","desc":false}]' \
--data-urlencode 'perPage=100'const params = new URLSearchParams({
from: "2026-08-01",
filters: JSON.stringify([
{ id: "amount", operator: "lte", value: -1000 },
{ id: "operationType", operator: "inArray", value: ["PIX", "TED"] },
]),
sort: JSON.stringify([{ id: "transactionAt", desc: false }]),
perPage: "100",
});
const res = await fetch(
`https://api-business.openi.com.br/api/v1/companies/${companyId}/bank-accounts/transactions?${params}`,
{ headers: { Authorization: `Bearer ${apiKey}` } },
);URLSearchParams já faz o encoding. Não é preciso informar variant nem filterId — o tipo do campo é conhecido pela API.
Tipos de campo e operadores
| Tipo | Exemplos | Operadores |
|---|---|---|
| texto | description, name | iLike, notILike, eq, ne, inArray, notInArray, isEmpty, isNotEmpty |
| número | amount (transações), rate, quantity | eq, ne, lt, lte, gt, gte, isBetween, isEmpty, isNotEmpty |
| valor | netValue, currentNetAmount | mesmos operadores de número |
| data | transactionAt, createdAt, placedAt | eq, ne, lt, lte, gt, gte, isBetween, isRelativeToToday, isEmpty, isNotEmpty |
| enum | status, type, origin | eq, ne, inArray, notInArray, isEmpty, isNotEmpty |
| uuid | id, accountId, investmentId | mesmos operadores de enum |
| campo personalizado | id (uuid) do campo | mesmos operadores de texto |
| Operador | Significado | value |
|---|---|---|
eq / ne | igual / diferente | valor único |
lt / lte | menor / menor ou igual | valor único |
gt / gte | maior / maior ou igual | valor único |
isBetween | entre dois valores, inclusivo | [inicio, fim] |
iLike / notILike | contém / não contém o texto, sem diferenciar maiúsculas | texto |
inArray / notInArray | é / não é um dos valores | lista não vazia |
isEmpty / isNotEmpty | vazio (nulo ou "") / preenchido | — |
isRelativeToToday | janela relativa à data de hoje | "-7 days", "-1 weeks", "-1 months" |
Datas
YYYY-MM-DDrepresenta o dia inteiro em UTC:eq "2026-08-01"casa qualquer instante do dia;lte "2026-08-31"inclui todo o dia 31;gt "2026-08-31"começa em 01/09.- Data-hora ISO 8601 (
2026-08-01T12:30:00-03:00,2026-08-01T15:30:00Z) compara o instante exato. isBetweencom["2026-08-01", "2026-08-31"]vai do início do primeiro dia ao fim do último.isRelativeToTodayrecebe"<N> days|weeks|months"e seleciona uma janela que começa em hoje + N:dayscobre 1 dia,weeks7 dias emonths30 dias. Ex.:"-1 weeks"são os 7 dias anteriores a hoje. Para "desde uma data", prefiragte.
Outros formatos (01/08/2026, timestamps numéricos) retornam 400.
Enums e ids
Campos enum com lista fixa de valores (ex.: type, status, classificationStatus) só aceitam os valores documentados na página do endpoint — um valor fora da lista retorna 400 com os valores aceitos, em vez de uma lista vazia. Campos uuid exigem um uuid válido.
Valores
Números e valores monetários usam ponto como separador decimal e podem ir como número ou string (1500.5 ou "1500.50"), sem símbolo de moeda — o mesmo formato das respostas. Nas transações bancárias amount tem sinal: positivo para entradas, negativo para saídas — para "saídas acima de R$ 1.000" use {"id":"amount","operator":"lte","value":-1000}, ou combine type = DEBIT com o valor.
Campos personalizados
Nos endpoints de lançamentos, o id de um campo personalizado (uuid) também é um campo filtrável e ordenável. Os ids e os valores já usados vêm do endpoint de atributos (bancários, investimentos):
[{ "id": "0d9e1f2a-3b4c-4d5e-6f7a-8b9c0d1e2f3a", "operator": "inArray", "value": ["Filial SP", "Filial RJ"] }]Valores de campos personalizados são sempre comparados como texto.
Combinando condições
joinOperator vale para todas as condições de filters — não há agrupamento. Com or, basta uma condição ser verdadeira:
filters=[{"id":"operationType","operator":"eq","value":"PIX"},{"id":"operationType","operator":"eq","value":"TED"}]
joinOperator=orPara "um de vários valores" com outras condições em and, use inArray no lugar de or:
[
{ "id": "operationType", "operator": "inArray", "value": ["PIX", "TED"] },
{ "id": "amount", "operator": "gte", "value": 1000 }
]Parâmetros de escopo (accountId, investmentId) e o período (from/to) sempre restringem o resultado, independentemente de joinOperator.
Ordenação
sort=[{"id":"transactionAt","desc":false}]desc:truepara decrescente (padrãofalse)- Vários critérios são aplicados na ordem informada
- Nem todo campo é ordenável — cada endpoint lista os seus. Sem
sort, cada endpoint usa sua ordem padrão (documentada na página)
Busca
Onde disponível, search procura o termo nos principais campos de texto (descrição, contraparte, documento...), sem diferenciar maiúsculas. Documentos formatados (12.345.678/0001-90) também encontram o valor sem máscara. A busca é sempre combinada em and com filters.
Paginação
| Endpoint | Parâmetros | Resposta |
|---|---|---|
| Transações, Transações por dia | page, perPage (1–500, padrão 10) | pagination: { page, limit, totalPages } |
| Lançamentos bancários e de investimentos | page, perPage (1–500, padrão 10) | pagination: { totalRecords, totalPages, hasMore } |
| Investimentos | page, perPage (1–500, padrão 10) | meta: { page, perPage, total, totalPages } |
| Contas, Fluxo de caixa, Campos personalizados | — | lista completa |
Nos lançamentos:
hasMoreestá sempre presente e indica se existe uma próxima página. Para percorrer tudo, avancepageenquantohasMorefortrue.- A contagem para 100 páginas à frente da página pedida. Quando o resultado passa disso,
totalRecordsetotalPagesvêmnull— o total ainda não é conhecido. Ao se aproximar do fim, eles voltam a ser o total exato.
// página 1 de um conjunto grande (perPage=500)
"pagination": { "totalRecords": null, "totalPages": null, "hasMore": true }
// página 150 — dentro das 100 páginas finais
"pagination": { "totalRecords": 111599, "totalPages": 224, "hasMore": true }
// última página
"pagination": { "totalRecords": 111599, "totalPages": 224, "hasMore": false }Erros
Filtros inválidos retornam 400 com a causa na mensagem — nunca são ignorados silenciosamente:
{
"status": "error",
"message": "filters.0.operator: operator \"iLike\" is not supported for \"amount\". Use one of: eq, ne, lt, lte, gt, gte, isBetween, isEmpty, isNotEmpty",
"cause": {
"target": "query",
"issues": [
{
"path": "filters.0.operator",
"code": "custom",
"message": "operator \"iLike\" is not supported for \"amount\". Use one of: eq, ne, lt, lte, gt, gte, isBetween, isEmpty, isNotEmpty"
}
]
}
}| Causa | Exemplo de mensagem |
|---|---|
| Período inválido ou invertido | from: must be an ISO 8601 date (YYYY-MM-DD) or date-time, from: must not be after to |
| Campo inexistente | unknown filter field "saldo". Filterable fields: ... |
| Operador não suportado pelo tipo | operator "iLike" is not supported for "amount" |
| Valor em formato errado | "transactionAt" with "eq" expects an ISO 8601 date (YYYY-MM-DD) or date-time |
| Valor fora da lista do enum | "status" with "eq" expects one of: POSTED, PENDING |
filters / sort não é JSON válido | must be a URL-encoded JSON array |
| Campo não ordenável | unknown sort field "description". Sortable fields: transactionAt |
search num endpoint sem busca | this endpoint does not support search |

