Case Management: Banking Circle raises a Case when it needs
something from you — most commonly an RFI (Request for Information,
usually a sanctions-screening hold on a payment) or a Recall Case (the
counterparty bank asking you to return a payment they sent you). A case
stays "OPEN" until you respond or a deadline passes, and not
responding has real consequences (payment delay/rejection, account
restriction), so treat list_cases/2 (or the case-opened webhook) as
something worth polling/handling promptly rather than best-effort.
Navigation
list_cases/2 (GET /api/v1/cases) returns cases of every type with a
links.self pointing you to the type-specific endpoint — e.g. an "RFI"
case links to /api/v1/cases/rfi/{case-id}. This module gives you
get_case/2 for the generic lookup and get_rfi_case/2 /
get_recall_case/2 for the typed ones directly, so you don't have to
round-trip through the generic endpoint if you already know the type.
This listing endpoint uses cursor-based pagination: once you've
fetched a page with a given limit, only cursor and direction are
valid on follow-up requests — the limit carries over from the initial
request and cannot be changed mid-cursor.
Responding to an RFI
get_rfi_case/2— get the questions and subject/transaction context.- For any attachment-type question,
upload_attachment/4first — each upload returns anattachmentIdto reference in your answer. submit_rfi_answers/3— either request a return (no answers needed) or answer every question asked (an empty string is an acceptable "I can't/won't answer" for a given question, but every question index must have a matching answer entry).
See BankingCircle.Cases.RFI for the answer-list building helpers.
Summary
Functions
Fetches a case by id regardless of type. The response's
links.self field tells you which typed endpoint (get_rfi_case/2,
get_recall_case/2, ...) to use for type-specific detail if you need it.
Fetches full detail for a Recall case (an incoming recall request from a counterparty bank).
Fetches full detail for an RFI case: questions, subject, and transaction context.
Lists all cases visible to you, regardless of type. Supports cursor
pagination: pass :limit on the first call, then only :cursor and
:direction (:next | :previous) on subsequent calls — other filters
are locked in once a cursor is in use.
Lists the question types an RFI may ask, with their input format/limitations.
Submits your response to an RFI case. response is either
Uploads an attachment to a case (needed before answering any
attachment-type RFI question). Returns {:ok, %{"attachmentId" => id}}
(or however the API names it) — thread that id into the matching
answer's attachmentIds list in submit_rfi_answers/3.
Types
Functions
@spec get_case(case_id(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Fetches a case by id regardless of type. The response's
links.self field tells you which typed endpoint (get_rfi_case/2,
get_recall_case/2, ...) to use for type-specific detail if you need it.
@spec get_recall_case(case_id(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Fetches full detail for a Recall case (an incoming recall request from a counterparty bank).
@spec get_rfi_case(case_id(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Fetches full detail for an RFI case: questions, subject, and transaction context.
@spec list_cases( keyword(), client() ) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Lists all cases visible to you, regardless of type. Supports cursor
pagination: pass :limit on the first call, then only :cursor and
:direction (:next | :previous) on subsequent calls — other filters
are locked in once a cursor is in use.
@spec rfi_question_types(client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Lists the question types an RFI may ask, with their input format/limitations.
@spec submit_rfi_answers(case_id(), map(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Submits your response to an RFI case. response is either:
%{request_return: true}— indicate you want the payment returned, no answers needed, or%{answers: [%{index: 0, answer: "...", attachment_ids: [...]}, ...]}— every question index the RFI asked must have a matching entry (an emptyansweris acceptable if you can't/won't answer a particular question — see the moduledoc).
See BankingCircle.Cases.RFI.build_answers/1 for a convenience builder.
@spec upload_attachment(case_id(), binary(), String.t(), String.t(), client()) :: {:ok, map()} | {:error, BankingCircle.Error.t()}
Uploads an attachment to a case (needed before answering any
attachment-type RFI question). Returns {:ok, %{"attachmentId" => id}}
(or however the API names it) — thread that id into the matching
answer's attachmentIds list in submit_rfi_answers/3.
content is the raw file bytes; filename and content_type describe
it for the multipart upload.