Developers

DGMOS Banking Integration API · v1.0.0

Banking API

Banking is the read-only service that collects DGMOS customers' bank movements. The API is called by the DGMOS backend, never directly from a browser or a mobile app. Every request is signed with a secret API key that belongs to one customer and only sees that customer's data.

Base URL$BANKING_URLlocally http://localhost:8090
StyleREST · JSON/v1 only
ContractOpenAPI 3.1openapi.yaml
EventsAsyncAPI 3.0asyncapi.yaml

This page is generated from openapi.yaml and asyncapi.yaml. The contract itself is checked against the API's registered routes in the test suite, so the endpoints here are exactly the ones the running service serves.

Authentication

The key pair (access_key + secret_key) is issued for the customer by the banking team. The secret is shown only once; keep it in DGMOS's secret store and never put it in a client or in logs.

Every request carries three headers:

HeaderValue
X-Access-KeyThe public part of the key
X-TimestampUnix seconds. Must be within 5 minutes of the server clock.
X-Signaturehex(HMAC-SHA256(secret_key, text))

The signed text has four lines joined by \n, with no trailing newline:

METHOD\nPATH\nTIMESTAMP\nBODY
  • METHOD in upper case: GET, POST…
  • PATH is the path and query exactly as sent: /v1/transactions?from=2025-11-01
  • BODY is the raw body as sent; empty for GET.
  • A write request that already succeeded and arrives again with the same signature gets 409 duplicate_request. Failed requests may be retried with the same signature.
  • Key restrictions are enforced by the server: allowed IPs, allowed routes, per-minute limit, expiry, revocation.
# Environment: BANKING_URL, BANKING_ACCESS_KEY, BANKING_SECRET_KEY
# Usage: banking METHOD PATH [JSON]
banking() {
  local method=$1 path=$2 body=${3-} ts sig
  ts=$(date +%s)
  sig=$(printf '%s\n%s\n%s\n%s' "$method" "$path" "$ts" "$body" \
    | openssl dgst -sha256 -hmac "$BANKING_SECRET_KEY" | awk '{print $NF}')
  curl -sS -X "$method" "$BANKING_URL$path" \
    -H "X-Access-Key: $BANKING_ACCESS_KEY" \
    -H "X-Timestamp: $ts" -H "X-Signature: $sig" \
    ${body:+-H "Content-Type: application/json" --data-binary "$body"}
}

First request

GET /v1/me returns who the key belongs to. It is the best first call to verify a setup: on 401 check the signature, on 403 check the key's IP and route restrictions.

A typical flow from there:

  1. Find the bank in the catalog: GET /v1/banks
  2. Create the account: POST /v1/accounts
  3. Set up a connection or upload a statement: POST /v1/connections, POST /v1/statements/import
  4. Listen to banking.transactions.imported.v1 and read the movements: GET /v1/accounts/{id}/transactions

The steps in detail and how they fit together: Flows.

$ banking GET /v1/me
{
  "data": {
    "customer_id": 1001,
    "api_key_id": 7,
    "api_key_name": "dgmos-backend"
  }
}

Flows

This section walks the whole path, from connecting a customer's bank to movements showing up in DGMOS. Each step links to its endpoint and event; jump to the reference for the details.

BankSFTP server Banksends files Bankingpull · receive · parsededupe · reconcile REST API/v1 · signed banking.eventsRabbitMQ · amqps DGMOSbackend andevent consumer pull push queries notifies
The bank sends the file or banking pulls it; banking parses it and stores the movements. DGMOS reads data from the API and learns about changes from events right away.
FlowWhen
1. Connecting a bankWhen a customer adds a bank account; once
2. How files arriveEvery day on their own (scheduled pull, bank push) or by manual upload
3. From file to movementsWhenever a file arrives
4. Listening to eventsContinuously; keeps DGMOS screens and notifications current
5. Reading movementsWhen an event arrives or a user opens a screen
6. ProblemsWhen a sync fails, a balance does not reconcile or a file cannot be read

1. Connecting a bank

A bank shares a customer's movements only on the customer's written instruction. Track that process with the application workflow; the technical connection is set up with the steps below. A connection starts as DRAFT and receives files only when ACTIVE.

DRAFTTESTINGACTIVE

Side states: SUSPENDED (no new files are accepted), DISABLED.

  1. Find the bank. GET /v1/banks?q=akbank returns the bank's id and its channels: which method (SFTP_PULL, SFTP_PUSH…) and format it supports. See Banks and their requirements.
  2. Learn what the bank needs. GET /v1/application-templates?institution_id=6&channel_type=SFTP_PULL gives the form fields and documents that bank requires for this method.
  3. Create the account. POST /v1/accounts: IBAN or account number and currency.
  4. Create the connection. POST /v1/connections: the method and its config (table below). A method marked UNSUPPORTED in the catalog is refused.
  5. Bind the account. POST /v1/connections/{id}/accounts. One connection can cover several accounts.
  6. Keys. For pull, POST /v1/connections/{id}/ssh-key creates an SSH key for this connection; give its public_key to the bank. If the bank encrypts files with PGP, POST /v1/connections/{id}/pgp-key and PUT /v1/connections/{id}/pgp-settings. Private keys never leave banking.
  7. Test. POST /v1/connections/{id}/test: for pull it connects, verifies the host key and lists the directory.
  8. Activate. POST /v1/connections/{id}/activate.
  9. Schedule. PUT /v1/connections/{id}/sync-policy sets how often to pull. For past days, POST /v1/connections/{id}/backfill.
# 4. A pull connection
$ banking POST /v1/connections '{
  "institution_id": 6,
  "name": "Main account SFTP",
  "channel_type": "SFTP_PULL",
  "format": "MT940",
  "config": {
    "host": "sftp.bank.example",
    "port": 22,
    "username": "dgmos",
    "remote_dir": "/out",
    "pattern": "*.sta",
    "host_key_sha256": "SHA256:…"
  }
}'

Pull or push?

SFTP_PULL: banking pullsSFTP_PUSH: the bank sends
Who connectsBanking, to the bank's SFTP serverThe bank, to banking's SFTP server
confighost, port, username, remote_dir, pattern, host_key_sha256 (required), min_file_age_secondsauthorized_keys (the bank's SSH public keys, required), allowed_ips, pattern, temp_suffixes
Given to the bankOur SSH public key and egress IPpush in GET /v1/connections/{id}: address, username, server fingerprint
Asked from the bankServer address, user, directory, host key fingerprint (through an official channel)The bank's SSH public key and source IPs
TimingFrom sync-policy; manually POST /v1/connections/{id}/syncWhenever the bank sends

If the host key changes, pulling stops with HOST_KEY_MISMATCH. Do not change the config before the bank confirms the new fingerprint through an official channel.

2. How files arrive

Files arrive three ways; all go through the same processing and create a file record (GET /v1/statement-files, field source).

Pull SFTP_PULL

The scheduler or a manual sync opens a job, which downloads new files from the bank's server.

QUEUEDRUNNINGSUCCEEDED

Transient errors are retried with growing delays; a permanent one ends as DEAD and publishes banking.sync.failed.v1. Jobs: GET /v1/connections/{id}/sync-jobs.

Push SFTP_PUSH

The bank drops the file with the connection's own user (c<connection id>). The server is write-only: no reading, deleting or listing.

Source IP and SSH key must match the connection. Uploading under a temporary name (.part, .tmp) and renaming is supported; an interrupted transfer is discarded.

Manual upload MANUAL_UPLOAD

POST /v1/statements/import uploads a file directly; the response carries the processing result at once.

Handy before a connection exists, during a migration, or to retry a file.

3. From file to movements

  1. Same file? If the content's SHA-256 was seen before, the file is not processed again (duplicate: true).
  2. Archive. The raw file is written, encrypted, to an immutable archive.
  3. Decrypt. With PGP set up, the file is decrypted and its signature verified; on failure the file is FAILED.
  4. Format and profile. MT940, MT942, CAMT.053, CAMT.052, CSV or XLSX is recognised; the bank's profile (CSV columns, date format) is applied.
  5. Account matching. By IBAN or account number. Without a certain match the statement goes to quarantine and its movements are not written.
  6. Deduplication. A movement seen before is not written twice; see Deduplication.
  7. One transaction. Movements, the balance check and the events are written in the same database transaction: all or nothing.

File result

statusMeaning
PROCESSEDEvery statement was processed
PARTIALSome processed, some in quarantine
QUARANTINEDNo statement matched an account
FAILEDCould not be read or decrypted; details on the file record

Events published

4. Listening to events

Banking publishes events to the banking.events topic exchange on its own RabbitMQ. Each consuming service gets its own user.

From the banking teamValue
Addressamqps://<user>:<password>@<host>:5671/banking (vhost banking)
CA certificateca.pem: verify the server certificate with it; do not turn verification off
IP allow-listThe consumer's egress IP must be allowed on the banking side
  1. Declare your queue with a name starting with your user name: dgmos.banking-events. You have no rights on other names.
  2. Bind it to banking.events. The routing key is the event type: # for all, banking.transactions.* for movements only.
  3. Acknowledge after handling the message (manual ack). If handling stops halfway, the message comes back.
  4. Deduplicate on eventId: delivery is at least once.
  5. An event carries ids only; read current data from the API (table below).

Important: events published before your queue is bound never reach you. Declare and bind the queue once, before the first bank connection; after that, events wait in the queue while the broker or your consumer is down.

// github.com/rabbitmq/amqp091-go
pem, _ := os.ReadFile("ca.pem")
roots := x509.NewCertPool()
roots.AppendCertsFromPEM(pem)
conn, err := amqp.DialTLS(os.Getenv("BANKING_AMQP_URL"),
	&tls.Config{RootCAs: roots})
ch, _ := conn.Channel()
q, _ := ch.QueueDeclare("dgmos.banking-events", true, false, false, false, nil)
_ = ch.QueueBind(q.Name, "#", "banking.events", false, nil)
msgs, _ := ch.Consume(q.Name, "", false, false, false, false, nil)
for m := range msgs {
	if err := handle(m.MessageId, m.Type, m.Body); err != nil {
		m.Nack(false, true) // retry
		continue
	}
	m.Ack(false)
}

What to read for each event

EventPayloadRead
transactions.importedaccountId, countGET /v1/accounts/{id}/transactions
statement.importedfileId, statusGET /v1/statement-files/{id}
statement.quarantinedfileIdGET /v1/quarantine
quarantine.resolvedaccountId, transactionsNewGET /v1/accounts/{id}/transactions
statement.balance_mismatchaccountId, differenceFlag the account to the user; the statement should be confirmed with the bank
sync.failedjobId, errorCodeGET /v1/sync-jobs/{id}
application.state_changedrequestId, toGET /v1/applications/{id}

5. Reading movements

  • One account: GET /v1/accounts/{id}/transactions; all accounts: GET /v1/transactions (optional account_id).
  • Newest first; for the next page send next_cursor back as cursor (Responses and pagination).
  • When an event arrives, read the latest pages of that account, not its whole history; count says how many movements are new.
  • Amounts are decimal strings ("1234.56"); do not convert them to floating point.
  • A movement that arrives as PENDING in an intraday report becomes BOOKED on the same record at end of day: update it by id, do not create a new one.
$ banking GET '/v1/accounts/42/transactions?limit=50'
{
  "data": [
    { "id": 981, "booking_date": "2025-11-04",
      "signed_amount": "15000.00", "currency": "TRY",
      "description": "GELEN EFT ACME TİCARET A.Ş.", … }
  ],
  "next_cursor": "MjAyNS0xMS0wNHw5ODE"
}

6. Problems

SituationHow you noticeWhat to do
Sync failed permanentlysync.failed; job DEADError code in GET /v1/sync-jobs/{id}. If the bank's server, key or IP changed, fix the connection and start a new sync
Host key changedJob error HOST_KEY_MISMATCHMay be a security incident. Suspend the connection and confirm the new fingerprint with the bank through an official channel
Statement matched no accountstatement.quarantinedQuarantine: assign it to the right account or dismiss it
Balance does not reconcilestatement.balance_mismatchMovements were written but some may be missing or extra; confirm the statement with the bank
File could not be readFile record FAILEDError details in GET /v1/statement-files/{id}; usually the PGP key or a format change on the bank's side
Request rejected4xx with error.codeError codes

Banks and their requirements

Every bank differs: the methods and formats it supports and the forms and documents it asks for. Banking keeps this in its bank catalog and serves it through the API; the catalog is updated as banks answer.

What a bank supports

channels in GET /v1/banks/{id} has one entry per method and format: channel_type, format, intraday (intraday reports) and availability_status.

availability_statusMeaning
UNKNOWNNo information yet
REPORTEDStated by the bank or a customer, not verified
UNDER_REVIEWBeing verified (sample files, tests)
VERIFIEDVerified with real files; evidence in evidence_url/evidence_note
UNSUPPORTED, DEPRECATEDNo connection can be opened with this method

What a bank asks for

GET /v1/application-templates?institution_id=&channel_type= returns that bank's current template for the method: the form fields to fill (company details, accounts, formats, frequency…) and the documents (the bank's instruction form, signature circular…). An application is opened from this template and the server checks what is missing.

Column mappings of banks that send CSV or XLSX are in profiles: GET /v1/profiles.

What is exchanged with the bank

Given to the bankAsked from the bank
AlwaysCompany and technical contacts; banking's fixed IPThe customer's signed instruction; format and version; real sample files; file naming; end-of-day time and intraday frequency; whether intraday reports are incremental or full; character encoding
Bank sendsSFTP address, user name and server fingerprint (push field)Its SSH public key and source IPs
We pullOur SSH public key for the connectionServer address, user, directory and host key fingerprint
PGPOur PGP public key for the connectionThe bank's signing public key

Environment-specific values (SFTP address and fingerprint, IP, event address) come from the banking team.

Banks in Türkiye

The banks in the catalog and the statement service each describes on its own corporate pages. REPORTED: the bank's page states SFTP or a web service. UNKNOWN: the page mentions only SWIFT, e-mail or FTP, or no channel; ask the bank for SFTP. No bank is VERIFIED before real files have been tested.

Deposit banks · 38
BankStatement serviceStatusSource
Akbank
Akbank T.A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday REPORTED Bank page
DenizBank
Denizbank A.Ş.
MT940 DIRECT_APIMT942 DIRECT_API · intraday REPORTED Bank page
HSBC
HSBC Bank A.Ş.
MT940 MANUAL_UPLOAD REPORTED Bank page
QNB
QNB Bank A.Ş.
MT940 SFTP_PUSH REPORTED Bank page
Yapı Kredi
Yapı ve Kredi Bankası A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday REPORTED Bank page
Ziraat Bankası
Türkiye Cumhuriyeti Ziraat Bankası A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intradayMT940 DIRECT_API REPORTED Bank page
Alternatif Bank
Alternatifbank A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Anadolubank
Anadolubank A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Burgan Bank
Burgan Bank A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Fibabanka
Fibabanka A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Garanti BBVA
Türkiye Garanti Bankası A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday UNKNOWN Bank page
Halkbank
Türkiye Halk Bankası A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
ICBC Turkey
ICBC Turkey Bank A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
ING
ING Bank A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday UNKNOWN Bank page
Odeabank
Odea Bank A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
TEB
Türk Ekonomi Bankası A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday UNKNOWN Bank page
VakıfBank
Türkiye Vakıflar Bankası T.A.O.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday UNKNOWN Bank page
İş Bankası
Türkiye İş Bankası A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Şekerbank
Şekerbank T.A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
A&T Bank
Arap Türk Bankası A.Ş.
No information UNKNOWN —
Bank Mellat
Bank Mellat İstanbul Merkez Şubesi
No information UNKNOWN Bank page
Bank of China Turkey
Bank of China Turkey A.Ş.
No information UNKNOWN —
Birleşik Fon Bankası
Birleşik Fon Bankası A.Ş.
No information UNKNOWN Bank page
Citi Türkiye
Citibank A.Ş.
No information UNKNOWN —
Colendi Bank
Colendi Bank A.Ş.
No information UNKNOWN Bank page
Deutsche Bank Türkiye
Deutsche Bank A.Ş.
No information UNKNOWN —
Enpara Bank
Enpara Bank A.Ş.
No information UNKNOWN Bank page
FUPS Bank
FUPS Bank A.Ş.
No information UNKNOWN Bank page
Habib Bank
Habib Bank Limited İstanbul Merkez Şubesi
No information UNKNOWN Bank page
Intesa Sanpaolo
Intesa Sanpaolo S.p.A. İstanbul Merkez Şubesi
No information UNKNOWN Bank page
J.P. Morgan
JPMorgan Chase Bank N.A. İstanbul Merkez Şubesi
No information UNKNOWN Bank page
MUFG Bank Turkey
MUFG Bank Turkey A.Ş.
No information UNKNOWN —
Rabobank
Rabobank A.Ş.
No information UNKNOWN Bank page
Société Générale
Société Générale (SA) İstanbul Merkez Şubesi
No information UNKNOWN Bank page
Turkish Bank
Turkish Bank A.Ş.
No information UNKNOWN —
Turkland Bank
Turkland Bank A.Ş.
No information UNKNOWN Bank page
Türk Ticaret Bankası
Türk Ticaret Bankası A.Ş.
No information UNKNOWN Bank page
Ziraat Dinamik Banka
Ziraat Dinamik Banka A.Ş.
No information UNKNOWN Bank page
Participation banks · 11
BankStatement serviceStatusSource
Kuveyt Türk
Kuveyt Türk Katılım Bankası A.Ş.
MT940 SFTP_PUSHMT942 SFTP_PUSH · intraday REPORTED Bank page
Türkiye Finans
Türkiye Finans Katılım Bankası A.Ş.
MT940 SFTP_PUSH REPORTED Bank page
Albaraka
Albaraka Türk Katılım Bankası A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Ziraat Katılım
Ziraat Katılım Bankası A.Ş.
MT940 SFTP_PUSH UNKNOWN Bank page
Adil Katılım
Adil Katılım Bankası A.Ş.
No information UNKNOWN Bank page
Dünya Katılım
Dünya Katılım Bankası A.Ş.
No information UNKNOWN —
Emlak Katılım
Türkiye Emlak Katılım Bankası A.Ş.
No information UNKNOWN —
Hayat Finans
Hayat Finans Katılım Bankası A.Ş.
No information UNKNOWN —
T.O.M. Bank
T.O.M. Katılım Bankası A.Ş.
No information UNKNOWN Bank page
Vakıf Katılım
Vakıf Katılım Bankası A.Ş.
No information UNKNOWN —
İktisat Katılım
İktisat Katılım Bankası A.Ş.
No information UNKNOWN Bank page
Development and investment banks · 21
BankStatement serviceStatusSource
Aktif Bank
Aktif Yatırım Bankası A.Ş.
No information UNKNOWN —
Aytemiz Yatırım Bankası
Aytemiz Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Bank of America Yatırım Bank
Bank of America Yatırım Bank A.Ş.
No information UNKNOWN Bank page
BankPozitif
BankPozitif Kredi ve Kalkınma Bankası A.Ş.
No information UNKNOWN Bank page
D Yatırım Bankası
D Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Destek Yatırım Bankası
Destek Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Diler Yatırım Bankası
Diler Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
GSD Yatırım Bankası
GSD Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Golden Global Yatırım Bankası
Golden Global Yatırım Bankası A.Ş.
No information UNKNOWN —
Hedef Yatırım Bankası
Hedef Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Misyon Bank
Misyon Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Nurol Yatırım Bankası
Nurol Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Pasha Bank
Pasha Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Q Yatırım Bankası
Q Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Standard Chartered Yatırım Bankası
Standard Chartered Yatırım Bankası Türk A.Ş.
No information UNKNOWN Bank page
TKYB
Türkiye Kalkınma ve Yatırım Bankası A.Ş.
No information UNKNOWN —
TSKB
Türkiye Sınai Kalkınma Bankası A.Ş.
No information UNKNOWN —
Takasbank
İstanbul Takas ve Saklama Bankası A.Ş.
No information UNKNOWN Bank page
Tera Yatırım Bankası
Tera Yatırım Bankası A.Ş.
No information UNKNOWN Bank page
Türk Eximbank
Türkiye İhracat Kredi Bankası A.Ş.
No information UNKNOWN —
İller Bankası
İller Bankası A.Ş.
No information UNKNOWN Bank page

Responses and pagination

  • Success is {"data": …}, plus "next_cursor" on paginated lists.
  • Errors are {"error": {"code", "message"}}. The code is stable, the message is for humans; let your program decide on the code.
  • For the next page, send next_cursor back as the cursor parameter; empty means last page.
  • Amounts are decimal strings: "1234.56", "-500.00". Do not convert them to floating point.
  • Dates are YYYY-MM-DD, timestamps are unix seconds.
  • You may send an X-Request-Id header; it is echoed in the response, appears in the logs and in the correlationId of events caused by a file upload.
  • When starting a sync, an Idempotency-Key makes a retry with the same key return the first job instead of creating a new one.
$ banking GET '/v1/transactions?from=2025-11-01&limit=2'
{
  "data": [ { "id": 981, "signed_amount": "15000.00", … },
            { "id": 977, "signed_amount": "-250.50", … } ],
  "next_cursor": "MjAyNS0xMS0wNHw5Nzc"
}

$ banking GET '/v1/transactions?from=2025-11-01&limit=2&cursor=MjAyNS0xMS0wNHw5Nzc'

Deduplication

The same movement can appear in several files: an intraday report and the end-of-day statement, a resent file, a backfill. Banking stores every movement once.

  • The same file content arriving twice (SHA-256) is not processed again; the response says duplicate: true.
  • For banks with reliable references the bank reference is the identity; otherwise a fingerprint of date, amount, direction and description plus the position within the file is used.
  • Two movements with the same date and amount are not merged. Both are stored; the second is flagged with duplicate_candidate_of.
  • A movement that arrived as PENDING in an intraday report is updated in place to BOOKED when the end-of-day statement books it.
  • occurrences tells in how many distinct statements the movement appeared.

Quarantine

When a statement does not match any account with certainty, nothing is guessed: the statement goes to quarantine, banking.statement.quarantined.v1 is published and no movements are written. The decision is left to the user on the DGMOS side.

Application workflow

A bank integration application starts from a versioned template, the form and documents are completed, and it goes through operations and bank steps. Allowed transitions are in allowed_next of the getApplication response; the server checks its rules (missing documents, references, connection status) on every transition.

DRAFTINTERNAL_REVIEWREADY_TO_SUBMITSUBMITTED_TO_BANKBANK_REVIEWAPPROVEDTECHNICAL_SETUPTESTINGACTIVE

Side paths: CUSTOMER_ACTION_REQUIRED, RETURNED_FOR_CORRECTION, SUSPENDED; endings: REJECTED, CANCELLED, EXPIRED. Every transition publishes banking.application.state_changed.v1.

Events

Banking publishes changes to the banking.events topic exchange in RabbitMQ; the routing key is the event type. An event is queued in the same database transaction that stores the change, so it cannot get lost.

  • Delivery is at least once: the same event may arrive twice. Deduplicate on eventId.
  • Events carry ids only; read the current data from the API.
  • Fields are added in a backward-compatible way; a breaking change comes as a new .vN type.
{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "…",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "…",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {}
}

banking.statement.imported.v1

A statement file was processed. Sent for every processed file, also when some of its statements were quarantined. aggregateType statement_file.

fileId integer

Statement file.

connectionId integer

0 for manual uploads

format string

File format; detected from the content when empty.

MT940MT942CAMT053CAMT052CSVXLSX
status string

Record status.

PROCESSEDPARTIALQUARANTINED
transactionsNew integer

New movements added.

transactionsSeen integer

Movements seen again.

quarantinedStatements integer

Number of quarantined statements.

statements object[]

Result per statement in the file.

{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.statement.imported.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "statement_file",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "fileId": 42,
    "connectionId": 42,
    "format": "MT940",
    "status": "PROCESSED",
    "transactionsNew": 1,
    "transactionsSeen": 1,
    "quarantinedStatements": 1,
    "statements": [
      {
        "index": 1,
        "account_id": 42,
        "quarantined": "…",
        "entries": 1,
        "new": 1,
        "seen": 1,
        "balance_check": "OK"
      }
    ]
  }
}

banking.transactions.imported.v1

New movements were added to an account. Sent per account and statement when at least one new movement was stored. Read them with GET /v1/accounts/{accountId}/transactions. aggregateType account.

accountId integer

Account.

statementId integer

Statement.

fileId integer

Statement file.

count integer

Number of new movements

{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.transactions.imported.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "account",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "accountId": 42,
    "statementId": 42,
    "fileId": 42,
    "count": 1
  }
}

banking.statement.quarantined.v1

Statements of a file could not be matched to an account. Resolve with POST /v1/quarantine/{id}/resolve or dismiss. aggregateType statement_file.

fileId integer

Statement file.

quarantinedStatements integer

Number of quarantined statements.

{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.statement.quarantined.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "statement_file",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "fileId": 42,
    "quarantinedStatements": 1
  }
}

banking.quarantine.resolved.v1

A quarantined statement was assigned to an account and imported. aggregateType quarantine_item.

quarantineId integer

Quarantine item.

fileId integer

Statement file.

accountId integer

Account.

transactionsNew integer

New movements added.

forced boolean

True when assigned although the account identifier in the file differed

{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.quarantine.resolved.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "quarantine_item",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "quarantineId": 42,
    "fileId": 42,
    "accountId": 42,
    "transactionsNew": 1,
    "forced": false
  }
}

banking.statement.balance_mismatch.v1

Opening balance plus movements does not equal the closing balance. The movements are stored; the statement is flagged. aggregateType statement.

statementId integer

Statement.

accountId integer

Account.

difference string | null

Decimal string

{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.statement.balance_mismatch.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "statement",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "statementId": 42,
    "accountId": 42,
    "difference": "…"
  }
}

banking.sync.failed.v1

A sync job gave up after all retries (dead-letter). aggregateType sync_job.

jobId integer

Sync job.

connectionId integer

Connection (0 for manual uploads).

errorCode string

Error code.

attempts integer

Attempts made.

{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.sync.failed.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "sync_job",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "jobId": 42,
    "connectionId": 42,
    "errorCode": "…",
    "attempts": 1
  }
}

banking.application.state_changed.v1

A bank integration application changed state. Use it for notifications and task lists. aggregateType integration_request.

requestId integer

Application.

from string

Start date (inclusive).

to string

Target state.

waitingParty string

Who has to act in the new state.

CUSTOMEROPERATIONSBANK
{
  "eventId": "0b9a6c1e-6f3d-4c55-9a43-1d2f6f0f6a11",
  "eventType": "banking.application.state_changed.v1",
  "occurredAt": 1762250400,
  "customerId": 42,
  "aggregateType": "integration_request",
  "aggregateId": 42,
  "schemaVersion": 1,
  "correlationId": "req-7f3c",
  "payload": {
    "requestId": 42,
    "from": "…",
    "to": "…",
    "waitingParty": "CUSTOMER"
  }
}

Error codes

Your program should decide on error.code. The same code may come with different messages.

Authentication and access

CodeHTTPMeaningWhat to do
missing_signature401X-Access-Key, X-Timestamp or X-Signature is missing.Send all three headers.
invalid_api_key401Unknown, revoked or expired key.Use a valid secret key.
invalid_signature401The signature does not match.Check the signed text: METHOD, PATH with query, TIMESTAMP and the raw BODY, separated by \n.
invalid_timestamp401The timestamp is more than 5 minutes off the server clock.Sync the server clock (NTP) and create a fresh timestamp for every request.
secret_key_required403Called with a public key.Use a secret key on the server side.
ip_not_allowed403The request came from an address not in the key's allowed IPs.Add the egress IP to the key.
route_not_allowed403The key's allowed routes do not cover this path.Widen the key's allowed_routes (e.g. /v1/*).
duplicate_request409The same signed request was already executed or is running now.Sign a new request with a new timestamp. Failed requests may be retried with the same signature.
rate_limited429The key's per-minute limit or the per-customer action limit was exceeded.Wait for the time in the Retry-After header.
auth_unavailable503The authentication backend is temporarily unreachable.Retry after a short wait.

General

CodeHTTPMeaningWhat to do
invalid_request400 / 422Invalid parameter or body; the message names the field.Fix the request.
not_found404The record does not exist or belongs to another customer.Check the id; another customer's records are never visible.
conflict409The record already exists (e.g. the same account).Use the existing record.
sync_in_progress409A job is already queued or running for the connection.Wait for the current job.
channel_not_automated422There is no automatic connector for this channel yet (e.g. DIRECT_API, EBICS).Use SFTP_PULL, SFTP_PUSH or MANUAL_UPLOAD.
channel_unsupported422The bank does not support this channel (UNSUPPORTED or DEPRECATED in the catalog).Pick one of the channels in the getBank response.
test_required422A successful connection test in the last 24 hours is required before activation.Call POST …/test first.
pgp_key_required422Generate the connection's PGP key before enabling decryption.Call POST …/pgp-key.
internal_error500Unexpected error.Retry; if it persists, report it with the X-Request-Id.
not_ready503A dependency of the service is not ready.Retry after a short wait.

Statements and quarantine

CodeHTTPMeaningWhat to do
UNSUPPORTED_FORMAT422The file format was not recognised.Name the format or ask the bank for a supported format.
PARSE_FAILED422The file does not follow its format.Check the file and the profile.
FILE_TOO_LARGE422The file exceeds the size limit.Split the file.
FILE_EMPTY422The file is empty.Upload the right file.
PROFILE_INVALID422The selected profile is invalid for this file.Pick the right profile.
ACCOUNT_UNRESOLVEDquarantineThe statement did not match any account with certainty.Pick the account with resolve or close it with dismiss.
ACCOUNT_MISMATCHquarantineThe chosen account differs from the account in the file.If correct, assign with force and a note.
CURRENCY_MISMATCHquarantine / 422The currency does not match the account; it cannot be forced.Pick the account in the right currency.
BALANCE_MISMATCHeventOpening + movements ≠ closing; movements are stored and the statement is flagged.Listen to banking.statement.balance_mismatch.v1.
CONFIRMATION_REQUIRED422Assigning to a different account needs confirmation.Send force: true and a note.
QUARANTINE_NOT_OPEN409The quarantine item is already closed.Read the current state.
STATEMENT_NOT_FOUND422The statement was not found in its source file.Report it to support.
RAW_FILE_PURGED422The raw file was deleted after its retention period; it cannot be reprocessed.Get the file from the bank again.
NOTE_REQUIRED422A note is required for this action.Send a note of at least 5 characters.

Bank applications

CodeHTTPMeaningWhat to do
no_template422No active application template for this bank and channel.Ask the banking team for a template.
invalid_transition409The target state cannot be reached from this state.See allowed_next in the getApplication response.
not_editable409The application cannot be edited in this state.Move it to an editable state first.
incomplete422A required field or document is missing.Complete the missing list.
invalid_form422A form value does not match the template.Fix the field named in the message.
invalid_document422The document type, size or expiry is not acceptable.Upload an allowed type within the limit that has not expired.
unknown_requirement422A document code that is not in the template.Use one of the template's codes.
invalid_account422The account does not belong to this customer or bank.Pick the right account.
note_required422This transition needs a note.Fill in note.
submission_reference_required422SUBMITTED_TO_BANK needs a submission reference.Send submission_reference.
bank_reference_required422APPROVED needs the bank's reference.Send bank_reference.
connection_required422TECHNICAL_SETUP needs a connection.Send connection_id.
connection_mismatch422The connection does not match the application's bank or channel.Pick the right connection.
connection_not_ready422The connection linked to the application is not set up.Create the connection and link it first.
connection_not_active422ACTIVE needs the connection to be active.Activate the connection first.

System

Health, readiness, caller identity and this document

GET/healthzunsigned

Liveness

Responses

Request

$ curl -sS "$BANKING_URL/healthz"

Response · 200 (example from the schema)

{
  "data": {
    "status": "ok"
  }
}

GET/readyzunsigned

Readiness (database, object store, secret store)

Responses

  • 200Ready · StatusData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 503Error: {"error": {"code", "message"}} · Error

Request

$ curl -sS "$BANKING_URL/readyz"

Response · 200 (example from the schema)

{
  "data": {
    "status": "ok"
  }
}

GET/openapi.yamlunsigned

This document

Responses

  • 200OpenAPI document
  • 4XXError: {"error": {"code", "message"}} · Error

Request

$ curl -sS "$BANKING_URL/openapi.yaml"

GET/v1/me

Identify the calling API key and its customer

Responses

  • 200Caller
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/me

Response · 200 (example from the schema)

{
  "data": {
    "customer_id": 42,
    "api_key_id": 42,
    "api_key_name": "dgmos-backend"
  }
}

Reference data

Bank catalog and parsing profiles

GET/v1/banks

Search the bank catalog

Parameters

countryquery string

ISO 3166-1 alpha-2

qquery string

Matches name or code

cursorquery string

next_cursor of the previous page

limitquery integer

Page size.

Responses

  • 200Banks · InstitutionPage
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/banks

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "code": "tr-ornek-banka",
      "country": "TR",
      "legal_name": "Örnek Bankası A.Ş.",
      "display_name": "Örnek Bankası",
      "parent_group_code": "",
      "institution_type": "BANK",
      "bic": "TGBATRIS",
      "lei": "",
      "status": "ACTIVE",
      "source_url": "https://www.tcmb.gov.tr",
      "verified_at": 1762250400,
      "channels": [
        {
          "id": 42,
          "institution_id": 42,
          "channel_type": "SFTP_PULL",
          "format": "MT940",
          "auth_type": "…",
          "intraday": true,
          "availability_status": "UNKNOWN",
          "evidence_url": "",
          "evidence_note": "",
          "verified_at": 1762250400
        }
      ]
    }
  ],
  "next_cursor": "MjAyNS0xMS0wNHw0Mg"
}

GET/v1/banks/{id}

Bank with its channel capabilities

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Bank
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/banks/42

Response · 200 (example from the schema)

{
  "data": {
    "id": 42,
    "code": "tr-ornek-banka",
    "country": "TR",
    "legal_name": "Örnek Bankası A.Ş.",
    "display_name": "Örnek Bankası",
    "parent_group_code": "",
    "institution_type": "BANK",
    "bic": "TGBATRIS",
    "lei": "",
    "status": "ACTIVE",
    "source_url": "https://www.tcmb.gov.tr",
    "verified_at": 1762250400,
    "channels": [
      {
        "id": 42,
        "institution_id": 42,
        "channel_type": "SFTP_PULL",
        "format": "MT940",
        "auth_type": "…",
        "intraday": true,
        "availability_status": "UNKNOWN",
        "evidence_url": "",
        "evidence_note": "",
        "verified_at": 1762250400
      }
    ]
  }
}

GET/v1/profiles

Latest active parsing profile per code (e.g. to pick a CSV/XLSX mapping)

Parameters

institution_idquery integer

Institution in the bank catalog.

formatquery Format

File format; detected from the content when empty.

Responses

  • 200Profiles
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/profiles

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "institution_id": 42,
      "code": "tr-ornek-banka",
      "version": 1,
      "format": "MT940",
      "config": {},
      "description": "GELEN EFT ACME TİCARET A.Ş.",
      "is_active": true,
      "created_at": 1762250400
    }
  ]
}

Accounts

Customer bank accounts

GET/v1/accounts

List accounts

Responses

  • 200Accounts
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/accounts

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "iban": "TR330006100519786457841326",
      "account_number": "6457841326",
      "currency": "TRY",
      "alias": "Ana hesap",
      "ownership_status": "UNVERIFIED",
      "status": "ACTIVE",
      "created_at": 1762250400
    }
  ]
}

POST/v1/accounts

Create an account

Body application/json

institution_idrequired integer

Institution in the bank catalog.

iban string

Validated (mod-97). Either iban or account_number is required.

account_number string

Bank-local identifier as it appears in statements

currencyrequired string

ISO 4217 currency.

alias string

Display name.

Responses

  • 201Created
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/accounts '{
  "institution_id": 42,
  "iban": "TR330006100519786457841326",
  "account_number": "6457841326",
  "currency": "TRY",
  "alias": "Ana hesap"
}'

Response · 201 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "institution_id": 42,
    "iban": "TR330006100519786457841326",
    "account_number": "6457841326",
    "currency": "TRY",
    "alias": "Ana hesap",
    "ownership_status": "UNVERIFIED",
    "status": "ACTIVE",
    "created_at": 1762250400
  }
}

GET/v1/accounts/{id}

Get an account

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Account
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/accounts/42

Response · 200 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "institution_id": 42,
    "iban": "TR330006100519786457841326",
    "account_number": "6457841326",
    "currency": "TRY",
    "alias": "Ana hesap",
    "ownership_status": "UNVERIFIED",
    "status": "ACTIVE",
    "created_at": 1762250400
  }
}

Transactions

Canonical movements (read-only)

GET/v1/accounts/{id}/transactions

Movements of one account (newest first)

Parameters

idrequiredpath integer

Identifier.

fromquery string · date

Booking date from (inclusive)

toquery string · date

Booking date to (inclusive)

statusquery string

Record status.

PENDINGBOOKEDUNKNOWN
directionquery string CREDITDEBIT
cursorquery string

next_cursor of the previous page

limitquery integer

Page size.

Responses

  • 200Movements · TransactionPage
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/accounts/42/transactions

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "account_id": 42,
      "booking_date": "2025-11-04",
      "value_date": "2025-11-04",
      "amount": "1234.56",
      "signed_amount": "1234.56",
      "currency": "TRY",
      "direction": "CREDIT",
      "is_reversal": false,
      "status": "PENDING",
      "description": "GELEN EFT ACME TİCARET A.Ş.",
      "bank_reference": "BNK0001",
      "customer_reference": "REF001",
      "end_to_end_id": "E2E-20251104-0001",
      "bank_tx_code": "NTRF",
      "counterparty_name": "ACME TİCARET A.Ş.",
      "counterparty_account": "TR120001000000000000000042",
      "duplicate_candidate_of": 1,
      "occurrences": 1,
      "first_seen_at": 1762250400
    }
  ],
  "next_cursor": "MjAyNS0xMS0wNHw0Mg"
}

GET/v1/transactions

Movements across accounts (newest first)

Parameters

account_idquery integer

Account.

fromquery string · date

Booking date from (inclusive)

toquery string · date

Booking date to (inclusive)

statusquery string

Record status.

PENDINGBOOKEDUNKNOWN
directionquery string CREDITDEBIT
cursorquery string

next_cursor of the previous page

limitquery integer

Page size.

Responses

  • 200Movements · TransactionPage
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/transactions

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "account_id": 42,
      "booking_date": "2025-11-04",
      "value_date": "2025-11-04",
      "amount": "1234.56",
      "signed_amount": "1234.56",
      "currency": "TRY",
      "direction": "CREDIT",
      "is_reversal": false,
      "status": "PENDING",
      "description": "GELEN EFT ACME TİCARET A.Ş.",
      "bank_reference": "BNK0001",
      "customer_reference": "REF001",
      "end_to_end_id": "E2E-20251104-0001",
      "bank_tx_code": "NTRF",
      "counterparty_name": "ACME TİCARET A.Ş.",
      "counterparty_account": "TR120001000000000000000042",
      "duplicate_candidate_of": 1,
      "occurrences": 1,
      "first_seen_at": 1762250400
    }
  ],
  "next_cursor": "MjAyNS0xMS0wNHw0Mg"
}

Connections

Bank channels, keys, sync policy and jobs

GET/v1/connections

List connections

Responses

  • 200Connections
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/connections

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "name": "Ana hesap SFTP",
      "channel_type": "SFTP_PULL",
      "format": "MT940",
      "profile_id": 42,
      "config": {},
      "has_secret": true,
      "status": "DRAFT",
      "approval_reference": "AKB-H2H-778",
      "approved_at": 1762250400,
      "last_test_ok_at": 1762250400,
      "pgp": {
        "decrypt": false,
        "require_signature": false,
        "has_key": false,
        "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… banking",
        "has_bank_public_key": false
      },
      "created_at": 1762250400,
      "updated_at": 1762250400
    }
  ]
}

POST/v1/connections

Create a connection (starts as DRAFT)

config depends on the channel:

  • SFTP_PULL: host, port, username, remote_dir, pattern, host_key_sha256 (required, SHA256:...), min_file_age_seconds
  • SFTP_PUSH: authorized_keys (bank SSH public keys, required), allowed_ips, pattern, temp_suffixes
  • MANUAL_UPLOAD: {}

Channels marked UNSUPPORTED/DEPRECATED in the catalog are refused.

Body application/json

institution_idrequired integer

Institution in the bank catalog.

namerequired string

Name.

channel_typerequired ChannelType

Channel type.

format Format

File format; detected from the content when empty.

profile_id integer

Parsing profile (for CSV/XLSX).

config object

Channel-specific configuration (see the description above).

Responses

  • 201Created
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections '{
  "institution_id": 42,
  "name": "Ana hesap SFTP",
  "channel_type": "SFTP_PULL",
  "format": "MT940",
  "profile_id": 42,
  "config": {}
}'

Response · 201 (example from the schema)

{
  "data": {
    "connection": {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "name": "Ana hesap SFTP",
      "channel_type": "SFTP_PULL",
      "format": "MT940",
      "profile_id": 42,
      "config": {},
      "has_secret": true,
      "status": "DRAFT",
      "approval_reference": "AKB-H2H-778",
      "approved_at": 1762250400,
      "last_test_ok_at": 1762250400,
      "pgp": {
        "decrypt": false,
        "require_signature": false,
        "has_key": false,
        "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… banking",
        "has_bank_public_key": false
      },
      "created_at": 1762250400,
      "updated_at": 1762250400
    },
    "capability_status": "UNKNOWN"
  }
}

GET/v1/connections/{id}

Connection with policy, bound accounts, last job and push endpoint details

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Connection details
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/connections/42

Response · 200 (example from the schema)

{
  "data": {
    "connection": {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "name": "Ana hesap SFTP",
      "channel_type": "SFTP_PULL",
      "format": "MT940",
      "profile_id": 42,
      "config": {},
      "has_secret": true,
      "status": "DRAFT",
      "approval_reference": "AKB-H2H-778",
      "approved_at": 1762250400,
      "last_test_ok_at": 1762250400,
      "pgp": {
        "decrypt": false,
        "require_signature": false,
        "has_key": false,
        "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… banking",
        "has_bank_public_key": false
      },
      "created_at": 1762250400,
      "updated_at": 1762250400
    },
    "sync_policy": {
      "connection_id": 42,
      "poll_interval_seconds": 3600,
      "bank_data_frequency": "…",
      "timezone": "Europe/Istanbul",
      "lookback_days": 3,
      "max_attempts": 6,
      "enabled": true,
      "last_attempt_at": 1762250400,
      "last_success_at": 1762250400,
      "last_data_at": 1762250400,
      "next_run_at": 1762250400
    },
    "accounts": [
      {
        "id": 42,
        "customer_id": 42,
        "institution_id": 42,
        "iban": "TR330006100519786457841326",
        "account_number": "6457841326",
        "currency": "TRY",
        "alias": "Ana hesap",
        "ownership_status": "UNVERIFIED",
        "status": "ACTIVE",
        "created_at": 1762250400
      }
    ],
    "last_job": {},
    "push": {
      "endpoint": "…",
      "username": "…",
      "host_key_fingerprint": "…"
    }
  }
}

POST/v1/connections/{id}/accounts

Bind an account to the connection

Parameters

idrequiredpath integer

Identifier.

Body application/json

account_idrequired integer

Account.

priority integer

Responses

  • 200Bound · FlagData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/accounts '{
  "account_id": 42,
  "priority": 1
}'

Response · 200 (example from the schema)

{
  "data": {}
}

POST/v1/connections/{id}/ssh-key

Generate (or rotate) the connection's SSH key; returns the public key for the bank

The private key is stored in the secret manager; the previous key is deleted.

Parameters

idrequiredpath integer

Identifier.

Responses

  • 201New key · PublicKeyData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/ssh-key

Response · 201 (example from the schema)

{
  "data": {
    "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… banking",
    "fingerprint": "SHA256:3q2+7w…"
  }
}

POST/v1/connections/{id}/pgp-key

Generate (or rotate) the connection's PGP key; returns the armored public key for the bank

Parameters

idrequiredpath integer

Identifier.

Responses

  • 201New key · PublicKeyData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/pgp-key

Response · 201 (example from the schema)

{
  "data": {
    "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… banking",
    "fingerprint": "SHA256:3q2+7w…"
  }
}

PUT/v1/connections/{id}/pgp-settings

Configure PGP decryption and bank signature verification

Parameters

idrequiredpath integer

Identifier.

Body application/json

decrypt boolean

Whether incoming files are PGP-decrypted.

bank_public_key string

Armored PGP public key of the bank

require_signature boolean

Requires bank_public_key

Responses

  • 200Settings
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking PUT /v1/connections/42/pgp-settings '{
  "decrypt": false,
  "bank_public_key": "…",
  "require_signature": false
}'

Response · 200 (example from the schema)

{
  "data": {
    "decrypt": false,
    "require_signature": false,
    "has_key": false,
    "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA… banking",
    "has_bank_public_key": false
  }
}

PUT/v1/connections/{id}/sync-policy

Set how often the channel is checked

Checking more often than the bank produces data does not produce newer data (a warning is returned).

Parameters

idrequiredpath integer

Identifier.

Body application/json

poll_interval_secondsrequired integer

How often the channel is checked (seconds).

bank_data_frequency string

How often the bank produces data.

UNKNOWNDAILYHOURLYINTRADAY
timezone string

Time zone of the bank's business day.

lookback_days integer

How many days each sync looks back.

max_attempts integer

Maximum attempts for a job.

enabled boolean

Whether scheduled syncs are on.

Responses

  • 200Policy
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking PUT /v1/connections/42/sync-policy '{
  "poll_interval_seconds": 3600,
  "bank_data_frequency": "UNKNOWN",
  "timezone": "Europe/Istanbul",
  "lookback_days": 3,
  "max_attempts": 6,
  "enabled": true
}'

Response · 200 (example from the schema)

{
  "data": {
    "sync_policy": {
      "connection_id": 42,
      "poll_interval_seconds": 3600,
      "bank_data_frequency": "…",
      "timezone": "Europe/Istanbul",
      "lookback_days": 3,
      "max_attempts": 6,
      "enabled": true,
      "last_attempt_at": 1762250400,
      "last_success_at": 1762250400,
      "last_data_at": 1762250400,
      "next_run_at": 1762250400
    },
    "warning": "…"
  }
}

POST/v1/connections/{id}/test

Test the channel (connect and list for SFTP pull; validate config for push)

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Test result (a failed test is still 200)
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/test

Response · 200 (example from the schema)

{
  "data": {
    "ok": false,
    "error_code": "CONNECTION_AUTH_FAILED",
    "message": "record not found"
  }
}

POST/v1/connections/{id}/activate

Activate (requires bank approval reference, a bound account and a successful test in the last 24h)

Parameters

idrequiredpath integer

Identifier.

Body application/json

approval_referencerequired string

The bank's approval, contract or ticket number.

Responses

  • 200Active · StatusData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/activate '{
  "approval_reference": "AKB-H2H-778"
}'

Response · 200 (example from the schema)

{
  "data": {
    "status": "ok"
  }
}

POST/v1/connections/{id}/suspend

Suspend the connection

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Suspended · StatusData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/suspend

Response · 200 (example from the schema)

{
  "data": {
    "status": "ok"
  }
}

POST/v1/connections/{id}/sync

Queue a sync now (pull channels only)

Parameters

idrequiredpath integer

Identifier.

Idempotency-Keyheader string

Retrying with the same key returns the original job

Responses

  • 202Queued
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/sync

Response · 202 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "connection_id": 42,
    "job_type": "SYNC",
    "trigger_type": "SCHEDULE",
    "params": {},
    "status": "QUEUED",
    "attempts": 1,
    "max_attempts": 6,
    "run_after": 1,
    "files_fetched": 1,
    "error_code": "",
    "error_detail": "",
    "created_at": 1762250400,
    "started_at": 1762250400,
    "finished_at": 1762250400
  }
}

POST/v1/connections/{id}/backfill

Re-read the channel from a past date (does not move the regular cursor)

Parameters

idrequiredpath integer

Identifier.

Idempotency-Keyheader string

Retrying with the same key returns the original job

Body application/json

fromrequired string · date

Within the last 400 days

Responses

  • 202Queued
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/connections/42/backfill '{
  "from": "2025-11-04"
}'

Response · 202 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "connection_id": 42,
    "job_type": "SYNC",
    "trigger_type": "SCHEDULE",
    "params": {},
    "status": "QUEUED",
    "attempts": 1,
    "max_attempts": 6,
    "run_after": 1,
    "files_fetched": 1,
    "error_code": "",
    "error_detail": "",
    "created_at": 1762250400,
    "started_at": 1762250400,
    "finished_at": 1762250400
  }
}

GET/v1/connections/{id}/sync-jobs

Recent jobs of a connection

Parameters

idrequiredpath integer

Identifier.

limitquery integer

Page size.

Responses

  • 200Jobs
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/connections/42/sync-jobs

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "customer_id": 42,
      "connection_id": 42,
      "job_type": "SYNC",
      "trigger_type": "SCHEDULE",
      "params": {},
      "status": "QUEUED",
      "attempts": 1,
      "max_attempts": 6,
      "run_after": 1,
      "files_fetched": 1,
      "error_code": "",
      "error_detail": "",
      "created_at": 1762250400,
      "started_at": 1762250400,
      "finished_at": 1762250400
    }
  ]
}

GET/v1/sync-jobs/{id}

Job status

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Job
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/sync-jobs/42

Response · 200 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "connection_id": 42,
    "job_type": "SYNC",
    "trigger_type": "SCHEDULE",
    "params": {},
    "status": "QUEUED",
    "attempts": 1,
    "max_attempts": 6,
    "run_after": 1,
    "files_fetched": 1,
    "error_code": "",
    "error_detail": "",
    "created_at": 1762250400,
    "started_at": 1762250400,
    "finished_at": 1762250400
  }
}

Statements

Statement files, manual import and quarantine

POST/v1/statements/import

Upload a statement file for an account

Formats: MT940, MT942, CAMT.053, CAMT.052 (auto-detected), CSV and XLSX (need profile_id). Re-uploading the same file returns 200 with duplicate: true; movements already known are counted as seen, never duplicated. Statements that do not match the account are quarantined.

Body multipart/form-data

filerequired string

The file itself.

account_idrequired integer

Account.

format Format

File format; detected from the content when empty.

profile_id integer

Parsing profile (for CSV/XLSX).

Responses

  • 201Imported
  • 200Same file already imported
  • 422Error: {"error": {"code", "message"}} · Error
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request · Go

data, _ := os.ReadFile("statement_251104.sta")
var res IngestResult
err := c.ImportStatement(ctx, 42, "statement_251104.sta", data, "", 0, &res)
// empty format = detected from the content; pass profileID for CSV/XLSX

Response · 201 (example from the schema)

{
  "data": {
    "file_id": 42,
    "duplicate": false,
    "status": "…",
    "format": "…",
    "transactions_new": 1,
    "transactions_seen": 1,
    "quarantined_statements": 1,
    "statements": [
      {
        "index": 1,
        "account_id": 42,
        "quarantined": "…",
        "entries": 1,
        "new": 1,
        "seen": 1,
        "balance_check": "OK"
      }
    ],
    "error_code": ""
  }
}

GET/v1/statement-files

Received files (newest first)

Parameters

cursorquery string

next_cursor of the previous response.

limitquery integer

Page size.

Responses

  • 200Files
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/statement-files

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "connection_id": 42,
      "source": "SFTP",
      "source_name": "ekstre_251104.sta",
      "sha256": "b89607672f7701e79e2cf435c094d3080666057ba1f3b3f6f8ded787a3366161",
      "size_bytes": 18342,
      "format": "MT940",
      "status": "RECEIVED",
      "error_code": "",
      "error_detail": "",
      "statements_count": 1,
      "transactions_new": 1,
      "transactions_seen": 1,
      "quarantined_count": 1,
      "received_at": 1762250400,
      "processed_at": 1762250400
    }
  ],
  "next_cursor": "MjAyNS0xMS0wNHw0Mg"
}

GET/v1/statement-files/{id}

File status

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200File
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/statement-files/42

Response · 200 (example from the schema)

{
  "data": {
    "id": 42,
    "connection_id": 42,
    "source": "SFTP",
    "source_name": "ekstre_251104.sta",
    "sha256": "b89607672f7701e79e2cf435c094d3080666057ba1f3b3f6f8ded787a3366161",
    "size_bytes": 18342,
    "format": "MT940",
    "status": "RECEIVED",
    "error_code": "",
    "error_detail": "",
    "statements_count": 1,
    "transactions_new": 1,
    "transactions_seen": 1,
    "quarantined_count": 1,
    "received_at": 1762250400,
    "processed_at": 1762250400
  }
}

GET/v1/quarantine

Quarantined statements

Parameters

statusquery string

Record status.

OPENRESOLVEDDISMISSED

Responses

  • 200Items
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/quarantine

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "file_id": 42,
      "statement_index": 1,
      "reason_code": "ACCOUNT_UNRESOLVED",
      "account_identifier": "TR33•••••••••••••••••1326",
      "currency": "TRY",
      "entries_count": 1,
      "status": "OPEN",
      "created_at": 1762250400
    }
  ]
}

POST/v1/quarantine/{id}/resolve

Import a quarantined statement into an account

The archived file is re-parsed. A different account identifier needs force and a note; a different currency is never allowed.

Parameters

idrequiredpath integer

Identifier.

Body application/json

account_idrequired integer

Account.

force boolean

Assign although the account number in the file differs (note required). A currency mismatch can never be forced.

note string

Explanation; written to the audit log.

Responses

  • 200Imported
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/quarantine/42/resolve '{
  "account_id": 42,
  "force": false,
  "note": "Bankaya iletildi"
}'

Response · 200 (example from the schema)

{
  "data": {
    "index": 1,
    "account_id": 42,
    "quarantined": "…",
    "entries": 1,
    "new": 1,
    "seen": 1,
    "balance_check": "OK"
  }
}

POST/v1/quarantine/{id}/dismiss

Close a quarantined statement without importing it

Parameters

idrequiredpath integer

Identifier.

Body application/json

noterequired string

Explanation; written to the audit log.

Responses

  • 200Dismissed · StatusData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/quarantine/42/dismiss '{
  "note": "Bankaya iletildi"
}'

Response · 200 (example from the schema)

{
  "data": {
    "status": "ok"
  }
}

Bank applications

Bank integration applications (spec §19)

GET/v1/application-templates

Templates; with institution_id and channel_type returns the latest active one

Parameters

institution_idquery integer

Institution in the bank catalog.

channel_typequery ChannelType

Channel type.

Responses

  • 200Template(s)
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/application-templates

Response · 200 (example from the schema)

{
  "data": {}
}

GET/v1/applications

List applications

Parameters

statequery ApplicationState

Responses

  • 200Applications
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/applications

Response · 200 (example from the schema)

{
  "data": [
    {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "channel_type": "SFTP_PULL",
      "template_id": 42,
      "template_version": 1,
      "template": {
        "fields": [
          {
            "code": "tr-ornek-banka",
            "label": "İmza sirküleri",
            "type": "text",
            "required": false,
            "pattern": "…",
            "options": [
              null
            ],
            "max_length": 1,
            "visible_if": {
              "field": null,
              "equals": null
            },
            "help": ""
          }
        ],
        "documents": [
          {
            "code": "tr-ornek-banka",
            "label": "İmza sirküleri",
            "required": false,
            "max_size_mb": 1,
            "allowed_types": [
              null
            ],
            "help": ""
          }
        ]
      },
      "form_data": {},
      "account_ids": [
        1
      ],
      "state": "DRAFT",
      "waiting_party": "CUSTOMER",
      "due_at": 1762250400,
      "submission_reference": "BAŞVURU-2025-118",
      "bank_reference": "BNK0001",
      "connection_id": 42,
      "created_at": 1762250400,
      "updated_at": 1762250400,
      "submitted_at": 1762250400,
      "decided_at": 1762250400
    }
  ]
}

POST/v1/applications

Open a DRAFT application with the latest template

Body application/json

institution_idrequired integer

Institution in the bank catalog.

channel_typerequired ChannelType

Channel type.

account_ids integer[]

Accounts covered by the application.

Responses

  • 201Created
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/applications '{
  "institution_id": 42,
  "channel_type": "SFTP_PULL",
  "account_ids": [
    1
  ]
}'

Response · 201 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "institution_id": 42,
    "channel_type": "SFTP_PULL",
    "template_id": 42,
    "template_version": 1,
    "template": {
      "fields": [
        {
          "code": "tr-ornek-banka",
          "label": "İmza sirküleri",
          "type": "text",
          "required": false,
          "pattern": "…",
          "options": [
            "…"
          ],
          "max_length": 1,
          "visible_if": {
            "field": "…",
            "equals": {}
          },
          "help": ""
        }
      ],
      "documents": [
        {
          "code": "tr-ornek-banka",
          "label": "İmza sirküleri",
          "required": false,
          "max_size_mb": 1,
          "allowed_types": [
            "application/pdf"
          ],
          "help": ""
        }
      ]
    },
    "form_data": {},
    "account_ids": [
      1
    ],
    "state": "DRAFT",
    "waiting_party": "CUSTOMER",
    "due_at": 1762250400,
    "submission_reference": "BAŞVURU-2025-118",
    "bank_reference": "BNK0001",
    "connection_id": 42,
    "created_at": 1762250400,
    "updated_at": 1762250400,
    "submitted_at": 1762250400,
    "decided_at": 1762250400
  }
}

GET/v1/applications/{id}

Application with documents, timeline, missing items and allowed next states

Parameters

idrequiredpath integer

Identifier.

Responses

  • 200Application
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/applications/42

Response · 200 (example from the schema)

{
  "data": {
    "request": {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "channel_type": "SFTP_PULL",
      "template_id": 42,
      "template_version": 1,
      "template": {
        "fields": [
          {
            "code": "tr-ornek-banka",
            "label": "İmza sirküleri",
            "type": "text",
            "required": false,
            "pattern": "…",
            "options": [
              null
            ],
            "max_length": 1,
            "visible_if": {
              "field": null,
              "equals": null
            },
            "help": ""
          }
        ],
        "documents": [
          {
            "code": "tr-ornek-banka",
            "label": "İmza sirküleri",
            "required": false,
            "max_size_mb": 1,
            "allowed_types": [
              null
            ],
            "help": ""
          }
        ]
      },
      "form_data": {},
      "account_ids": [
        1
      ],
      "state": "DRAFT",
      "waiting_party": "CUSTOMER",
      "due_at": 1762250400,
      "submission_reference": "BAŞVURU-2025-118",
      "bank_reference": "BNK0001",
      "connection_id": 42,
      "created_at": 1762250400,
      "updated_at": 1762250400,
      "submitted_at": 1762250400,
      "decided_at": 1762250400
    },
    "documents": [
      {
        "id": 42,
        "requirement_code": "imza_sirkuleri",
        "filename": "imza-sirkuleri.pdf",
        "content_type": "application/pdf",
        "size_bytes": 18342,
        "sha256": "b89607672f7701e79e2cf435c094d3080666057ba1f3b3f6f8ded787a3366161",
        "expires_at": 1762250400,
        "uploaded_at": 1762250400
      }
    ],
    "events": [
      {
        "id": 42,
        "from_state": "…",
        "to_state": "…",
        "actor": "api_key:dgmos-backend",
        "user_id": 42,
        "note": "Bankaya iletildi",
        "created_at": 1762250400
      }
    ],
    "missing": [
      "…"
    ],
    "allowed_next": [
      "DRAFT"
    ]
  }
}

PUT/v1/applications/{id}/form

Save form values (partial drafts allowed; only in DRAFT, CUSTOMER_ACTION_REQUIRED, RETURNED_FOR_CORRECTION)

Parameters

idrequiredpath integer

Identifier.

Body application/json

form_data object

Keys are template field codes

account_ids integer[]

Accounts covered by the application.

Responses

  • 200Updated application
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking PUT /v1/applications/42/form '{
  "form_data": {},
  "account_ids": [
    1
  ]
}'

Response · 200 (example from the schema)

{
  "data": {
    "request": {
      "id": 42,
      "customer_id": 42,
      "institution_id": 42,
      "channel_type": "SFTP_PULL",
      "template_id": 42,
      "template_version": 1,
      "template": {
        "fields": [
          {
            "code": "tr-ornek-banka",
            "label": "İmza sirküleri",
            "type": "text",
            "required": false,
            "pattern": "…",
            "options": [
              null
            ],
            "max_length": 1,
            "visible_if": {
              "field": null,
              "equals": null
            },
            "help": ""
          }
        ],
        "documents": [
          {
            "code": "tr-ornek-banka",
            "label": "İmza sirküleri",
            "required": false,
            "max_size_mb": 1,
            "allowed_types": [
              null
            ],
            "help": ""
          }
        ]
      },
      "form_data": {},
      "account_ids": [
        1
      ],
      "state": "DRAFT",
      "waiting_party": "CUSTOMER",
      "due_at": 1762250400,
      "submission_reference": "BAŞVURU-2025-118",
      "bank_reference": "BNK0001",
      "connection_id": 42,
      "created_at": 1762250400,
      "updated_at": 1762250400,
      "submitted_at": 1762250400,
      "decided_at": 1762250400
    },
    "documents": [
      {
        "id": 42,
        "requirement_code": "imza_sirkuleri",
        "filename": "imza-sirkuleri.pdf",
        "content_type": "application/pdf",
        "size_bytes": 18342,
        "sha256": "b89607672f7701e79e2cf435c094d3080666057ba1f3b3f6f8ded787a3366161",
        "expires_at": 1762250400,
        "uploaded_at": 1762250400
      }
    ],
    "events": [
      {
        "id": 42,
        "from_state": "…",
        "to_state": "…",
        "actor": "api_key:dgmos-backend",
        "user_id": 42,
        "note": "Bankaya iletildi",
        "created_at": 1762250400
      }
    ],
    "missing": [
      "…"
    ],
    "allowed_next": [
      "DRAFT"
    ]
  }
}

POST/v1/applications/{id}/documents

Upload a required document (PDF, PNG or JPEG; type checked from content)

Parameters

idrequiredpath integer

Identifier.

Body multipart/form-data

requirement_coderequired string

Document code from the template.

filerequired string

The file itself.

expires_at string · date

Expiry.

Responses

  • 201Stored
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request · Go

var buf bytes.Buffer
mw := multipart.NewWriter(&buf)
_ = mw.WriteField("requirement_code", "signature_circular")
fw, _ := mw.CreateFormFile("file", "signature-circular.pdf")
fw.Write(pdf)
mw.Close()
var doc ApplicationDocument
_, err := c.Do(ctx, "POST", "/v1/applications/42/documents",
	buf.Bytes(), mw.FormDataContentType(), bankingclient.Options{}, &doc)

Response · 201 (example from the schema)

{
  "data": {
    "id": 42,
    "requirement_code": "imza_sirkuleri",
    "filename": "imza-sirkuleri.pdf",
    "content_type": "application/pdf",
    "size_bytes": 18342,
    "sha256": "b89607672f7701e79e2cf435c094d3080666057ba1f3b3f6f8ded787a3366161",
    "expires_at": 1762250400,
    "uploaded_at": 1762250400
  }
}

GET/v1/applications/{id}/documents/{docId}

Download a document

Parameters

idrequiredpath integer

Identifier.

docIdrequiredpath integer

Responses

  • 200File
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking GET /v1/applications/42/documents/7

DELETE/v1/applications/{id}/documents/{docId}

Remove a document (editable states only)

Parameters

idrequiredpath integer

Identifier.

docIdrequiredpath integer

Responses

  • 200Deleted · FlagData
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking DELETE /v1/applications/42/documents/7

Response · 200 (example from the schema)

{
  "data": {}
}

POST/v1/applications/{id}/transition

Move the application to another state

Allowed transitions are returned as allowed_next. Guards:

  • INTERNAL_REVIEW, READY_TO_SUBMIT, SUBMITTED_TO_BANK: no missing fields/documents (incomplete)
  • SUBMITTED_TO_BANK: submission_reference; APPROVED: bank_reference
  • TECHNICAL_SETUP: connection_id of the same bank and channel
  • ACTIVE: the linked connection is ACTIVE
  • CUSTOMER_ACTION_REQUIRED, RETURNED_FOR_CORRECTION, REJECTED, CANCELLED, SUSPENDED: note

Which DGMOS role may perform which transition is decided by DGMOS.

Parameters

idrequiredpath integer

Identifier.

Body application/json

torequired ApplicationState

Target state.

note string

Explanation; written to the audit log.

submission_reference string

Required for SUBMITTED_TO_BANK: the reference of the submission to the bank.

bank_reference string

Required for APPROVED: the bank's approval reference.

connection_id integer

Required for TECHNICAL_SETUP: the connection being set up.

waiting_party string

Who has to act next.

CUSTOMEROPERATIONSBANK
due_at string · date

Due date.

Responses

  • 200New state
  • 4XXError: {"error": {"code", "message"}} · Error
  • 5XXError: {"error": {"code", "message"}} · Error

Request

$ banking POST /v1/applications/42/transition '{
  "to": "DRAFT",
  "note": "Bankaya iletildi",
  "submission_reference": "BAŞVURU-2025-118",
  "bank_reference": "BNK0001",
  "connection_id": 42,
  "waiting_party": "CUSTOMER",
  "due_at": "2025-11-04"
}'

Response · 200 (example from the schema)

{
  "data": {
    "id": 42,
    "customer_id": 42,
    "institution_id": 42,
    "channel_type": "SFTP_PULL",
    "template_id": 42,
    "template_version": 1,
    "template": {
      "fields": [
        {
          "code": "tr-ornek-banka",
          "label": "İmza sirküleri",
          "type": "text",
          "required": false,
          "pattern": "…",
          "options": [
            "…"
          ],
          "max_length": 1,
          "visible_if": {
            "field": "…",
            "equals": {}
          },
          "help": ""
        }
      ],
      "documents": [
        {
          "code": "tr-ornek-banka",
          "label": "İmza sirküleri",
          "required": false,
          "max_size_mb": 1,
          "allowed_types": [
            "application/pdf"
          ],
          "help": ""
        }
      ]
    },
    "form_data": {},
    "account_ids": [
      1
    ],
    "state": "DRAFT",
    "waiting_party": "CUSTOMER",
    "due_at": 1762250400,
    "submission_reference": "BAŞVURU-2025-118",
    "bank_reference": "BNK0001",
    "connection_id": 42,
    "created_at": 1762250400,
    "updated_at": 1762250400,
    "submitted_at": 1762250400,
    "decided_at": 1762250400
  }
}

Schemas

Error object

errorrequired object

Error code and message.

StatusData object

data object

Response content.

FlagData object

data object

Response content.

PublicKeyData object

data object

Response content.

Format string

MT940MT942CAMT053CAMT052CSVXLSX

ChannelType string

SFTP_PULLSFTP_PUSHDIRECT_APIOPEN_BANKINGHOST_TO_HOSTEBICSMANUAL_UPLOAD

AvailabilityStatus string

UNKNOWNREPORTEDUNDER_REVIEWVERIFIEDUNSUPPORTEDDEPRECATED

Money string

Institution object

id integer

Identifier.

code string

Code.

country string

ISO 3166-1 alpha-2 country code.

legal_name string
display_name string
parent_group_code string
institution_type string
bic string
lei string
status string

Record status.

source_url string
verified_at integer
channels Capability[]

InstitutionPage object

data Institution[]

Response content.

next_cursor string

Pass it as cursor to get the next page. Empty on the last page.

Capability object

id integer

Identifier.

institution_id integer

Institution in the bank catalog.

channel_type ChannelType

Channel type.

format Format

File format; detected from the content when empty.

auth_type string
intraday boolean
availability_status AvailabilityStatus
evidence_url string
evidence_note string
verified_at integer

Profile object

id integer

Identifier.

institution_id integer

Institution in the bank catalog.

code string

Code.

version integer
format Format

File format; detected from the content when empty.

config object

Channel-specific configuration (see the description above).

description string

Description.

is_active boolean
created_at integer

Creation time (unix seconds).

Account object

id integer

Identifier.

customer_id integer

DGMOS customer that owns the record.

institution_id integer

Institution in the bank catalog.

iban string

IBAN (validated with mod-97). Either iban or account_number is required.

account_number string

Bank-local account number as it appears in statements.

currency string

ISO 4217 currency.

alias string

Display name.

ownership_status string

Whether a bank file confirmed that the account belongs to the customer.

UNVERIFIEDVERIFIED_BY_BANK
status string

Record status.

created_at integer

Creation time (unix seconds).

Transaction object

id integer

Identifier.

account_id integer

Account.

booking_date string · date

Bank booking date.

value_date string · date

Value date.

amount Money

Absolute amount as a decimal string ("1234.56").

signed_amount Money

Signed amount: credits positive, debits negative.

currency string

ISO 4217 currency.

direction string CREDITDEBIT
is_reversal boolean

Reversal (refund/cancellation) entry.

status string

Record status.

PENDINGBOOKEDUNKNOWN
description string

Description.

bank_reference string

Required for APPROVED: the bank's approval reference.

customer_reference string
end_to_end_id string
bank_tx_code string
counterparty_name string
counterparty_account string
duplicate_candidate_of integer

Looks like this movement from another file; never merged automatically

occurrences integer

Number of statements in which the movement appeared

first_seen_at integer

When the movement was first seen (unix seconds).

TransactionPage object

data Transaction[]

Response content.

next_cursor string

Pass it as cursor to get the next page. Empty on the last page.

PGPSettings object

decrypt boolean

Whether incoming files are PGP-decrypted.

require_signature boolean

Whether a bank signature is required.

has_key boolean
public_key string

Public key to give to the bank.

has_bank_public_key boolean

Connection object

id integer

Identifier.

customer_id integer

DGMOS customer that owns the record.

institution_id integer

Institution in the bank catalog.

name string

Name.

channel_type ChannelType

Channel type.

format Format

File format; detected from the content when empty.

profile_id integer

Parsing profile (for CSV/XLSX).

config object

Channel-specific configuration (see the description above).

has_secret boolean

Whether the connection's credential is set in the secret store.

status string

Record status.

DRAFTTESTINGACTIVESUSPENDEDDISABLED
approval_reference string

The bank's approval, contract or ticket number.

approved_at integer
last_test_ok_at integer
pgp PGPSettings
created_at integer

Creation time (unix seconds).

updated_at integer

Last update time (unix seconds).

SyncPolicy object

connection_id integer

Required for TECHNICAL_SETUP: the connection being set up.

poll_interval_seconds integer

How often the channel is checked (seconds).

bank_data_frequency string

How often the bank produces data.

timezone string

Time zone of the bank's business day.

lookback_days integer

How many days each sync looks back.

max_attempts integer

Maximum attempts for a job.

enabled boolean

Whether scheduled syncs are on.

last_attempt_at integer
last_success_at integer
last_data_at integer

Newest movement date held (data freshness)

next_run_at integer

Job object

id integer

Identifier.

customer_id integer

DGMOS customer that owns the record.

connection_id integer

Required for TECHNICAL_SETUP: the connection being set up.

job_type string SYNCBACKFILL
trigger_type string SCHEDULEMANUAL
params object
status string

Record status.

QUEUEDRUNNINGSUCCEEDEDDEAD
attempts integer

Attempts made.

max_attempts integer

Maximum attempts for a job.

run_after integer
files_fetched integer
error_code string

Error code on failure.

error_detail string

Failure detail.

created_at integer

Creation time (unix seconds).

started_at integer
finished_at integer

StatementFile object

id integer

Identifier.

connection_id integer

Required for TECHNICAL_SETUP: the connection being set up.

source string SFTPSFTP_PUSHUPLOADAPI
source_name string
sha256 string
size_bytes integer
format Format

File format; detected from the content when empty.

status string

Record status.

RECEIVEDPROCESSEDPARTIALQUARANTINEDFAILED
error_code string

Error code on failure.

error_detail string

Failure detail.

statements_count integer
transactions_new integer

New movements added by this file.

transactions_seen integer

Movements already stored and seen again.

quarantined_count integer
received_at integer

When the file was received (unix seconds).

processed_at integer

When the file was processed (unix seconds).

StatementResult object

index integer
account_id integer

Account.

quarantined string

Quarantine reason code when not imported

entries integer
new integer
seen integer
balance_check string

Result of opening + movements = closing.

OKMISMATCHNOT_APPLICABLE

IngestResult object

file_id integer
duplicate boolean

True when the same content was uploaded before; it is not processed again.

status string

Record status.

format string

File format; detected from the content when empty.

transactions_new integer

New movements added by this file.

transactions_seen integer

Movements already stored and seen again.

quarantined_statements integer

Number of quarantined statements.

statements StatementResult[]

Result per statement in the file.

error_code string

Error code on failure.

QuarantineItem object

id integer

Identifier.

file_id integer
statement_index integer
reason_code string ACCOUNT_UNRESOLVEDACCOUNT_MISMATCHCURRENCY_MISMATCH
account_identifier string

Masked

currency string

ISO 4217 currency.

entries_count integer
status string

Record status.

OPENRESOLVEDDISMISSED
created_at integer

Creation time (unix seconds).

ApplicationState string

DRAFTINTERNAL_REVIEWCUSTOMER_ACTION_REQUIREDREADY_TO_SUBMITSUBMITTED_TO_BANKBANK_REVIEWAPPROVEDTECHNICAL_SETUPTESTINGACTIVERETURNED_FOR_CORRECTIONREJECTEDCANCELLEDEXPIREDSUSPENDED

ApplicationTemplate object

id integer

Identifier.

institution_id integer

Institution in the bank catalog.

channel_type ChannelType

Channel type.

version integer
name string

Name.

definition TemplateDefinition
is_active boolean
created_at integer

Creation time (unix seconds).

TemplateDefinition object

fields object[]
documents object[]

Application object

id integer

Identifier.

customer_id integer

DGMOS customer that owns the record.

institution_id integer

Institution in the bank catalog.

channel_type ChannelType

Channel type.

template_id integer
template_version integer
template TemplateDefinition
form_data object

Form values keyed by the template's field codes.

account_ids integer[]

Accounts covered by the application.

state ApplicationState
waiting_party string

Who has to act next.

CUSTOMEROPERATIONSBANK
due_at integer

Due date.

submission_reference string

Required for SUBMITTED_TO_BANK: the reference of the submission to the bank.

bank_reference string

Required for APPROVED: the bank's approval reference.

connection_id integer

Required for TECHNICAL_SETUP: the connection being set up.

created_at integer

Creation time (unix seconds).

updated_at integer

Last update time (unix seconds).

submitted_at integer
decided_at integer

ApplicationDocument object

id integer

Identifier.

requirement_code string

Document code from the template.

filename string
content_type string
size_bytes integer
sha256 string
expires_at integer

Expiry.

uploaded_at integer

ApplicationEvent object

id integer

Identifier.

from_state string
to_state string
actor string
user_id integer
note string

Explanation; written to the audit log.

created_at integer

Creation time (unix seconds).