sandbox.bankconnector.com API Reference

Operate / Operator API reference

Operator API reference

The setup & administration endpoints an operator or workspace admin uses to stand a tenant up and keep it running — bank connections and channel activation, approvals, users, workspace/company admin, and session sign-in. These are session-authenticated (an X-API-Key gets 403); the day-to-day integration surface is in the API reference.

Download the spec: openapi.json · openapi.yaml — the full spec covers both tracks.

Connections

Bank connection setup, channel activation, and EBICS onboarding (session-authenticated, Admin only)

GET/connectivity/profiles
List connectivity profiles (channel info per bank)

Read-only metadata: which channel each bank uses (sftp / danske-ws / nordea-ca / bankconnect / ebics), its pre-known server/endpoint details, and SFTP wizard config. No auth required.

Responses
StatusDescription
200Connectivity profiles
Example response (200)
{
  "items": [
    {}
  ]
}
GET/connections
List bank connections for a company
Parameters
NameInRequiredDescription
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200Connection list
401Sign in required
Example response (200)
{
  "items": [
    {
      "id": "string",
      "bankKey": "nordea-dk",
      "bankName": "Nordea Danmark",
      "environment": "test",
      "channelType": "sftp",
      "active": false,
      "steps": {
        "introEmailSent": false,
        "pgpGenerated": false,
        "bankPublicKeyAdded": false,
        "serverInfoAdded": false,
        "sftpUserAdded": false,
        "approversAssigned": false,
        "certsIssued": false,
        "bankCertAdded": false,
        "ebicsKeysGenerated": false,
        "ebicsBankKeysFetched": false,
        "wsConfigAdded": false
      },
      "sshPublicKey": "string",
      "pgpPublicKey": "string",
      "approverUserIds": [
        "string"
      ],
      "createdAt": "2026-01-01T00: 00: 00Z"
    }
  ]
}
POST/connections
Create (or find existing) bank connection: starts the setup wizard

Creates a bank connection for the given company, or returns the existing one if already set up. Platform-admin note: if you are authenticated as a workspace (platform) admin, you must enter a company context first via POST /auth/company-context before calling this endpoint. Without it you will receive: "select a company context first."

Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
bankKeyBankKeyyes
environmentenumno
Example
{
  "platformId": "string",
  "companyId": "string",
  "bankKey": "nordea-dk",
  "environment": "test"
}
Responses
StatusDescription
201Connection created
400Invalid request
401Sign in required
403Admin required
Example response (201)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
GET/connections/{id}
Get a single connection + readiness
Parameters
NameInRequiredDescription
id stringpathyes
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200Connection + readiness
404Not found
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
PUT/connections/{id}/signing-cert
Pin the bank's published signing certificate

Stores the bank's PUBLISHED X.509 signing certificate (PEM or base64-DER) on the connection so inbound Web Services signatures are verified against it (fail-closed on any mismatch). Admin only. Validates the cert parses (400 on bad input). Returns the cert subject + expiry so the operator can confirm they pinned the right cert; the raw PEM is never returned. GET /connections/{id} then surfaces signingCertSubject / signingCertExpiry.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
certstringyesThe bank's published signing certificate — PEM (-----BEGIN CERTIFICATE-----) or base64-DER.
Example
{
  "platformId": "string",
  "companyId": "string",
  "cert": "string"
}
Responses
StatusDescription
200Pinned
400Bad certificate or non-WS connection
401Sign in required
403Admin required
Example response (200)
{
  "connectionId": "string",
  "certSubject": "string",
  "certExpiry": "2026-01-01T00: 00: 00Z"
}
POST/connections/{id}/activate-danske
Activate Danske EDI Web Services (automated cert enrolment)

Calls the Danske bxd.fi activation endpoint with the one-time PIN, self-issues the signing + encryption certificates, and marks the connection active. Admin only.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
userIdstringyesAgreement number (User ID) from Danske.
pinstringyesOne-time transfer key from Danske.
Example
{
  "platformId": "string",
  "companyId": "string",
  "userId": "string",
  "pin": "string"
}
Responses
StatusDescription
200Activated
400Activation failed (wrong PIN, network, etc.)
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/activate-nordea
Activate Nordea Corporate Access (HMAC cert enrolment via SMS code)

Generates a Nordea-format signing CSR, sends the HMAC-signed enrolment request to Nordea's Corporate Access endpoint using the SMS activation code, and stores the issued certificate. Admin only.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
holderNamestringyesCertificate-holder name (CN) as printed in the Nordea agreement.
signerIdstringyesSigner ID from the agreement.
senderIdstringno
countrystringyes
activationCodestringyes10-digit SMS activation code from Nordea.
Example
{
  "platformId": "string",
  "companyId": "string",
  "holderName": "string",
  "signerId": "string",
  "senderId": "string",
  "country": "string",
  "activationCode": "string"
}
Responses
StatusDescription
200Activated
400Activation failed
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/activate-bankconnect
Activate Bank Connect (DK gateway: automated cert enrolment)

Enrols the signing certificate with the Bank Connect data central (BD/BEC/SDC), stores the issued certificate and bank public key, and marks the connection active. Data central and country are pre-filled from the bank profile. Admin only.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
organisationIdstringyesBank registration number.
functionIdstringyesPer-agreement routing code from the bank.
activationCodestringyesOne-time activation code from the bank.
Example
{
  "platformId": "string",
  "companyId": "string",
  "organisationId": "string",
  "functionId": "string",
  "activationCode": "string"
}
Responses
StatusDescription
200Activated
400Activation failed or bank has no Bank Connect data central
401Sign in required
403Admin required
404Connection not found
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/renew-danske
Renew the Danske EDI Web Services certificates

Issues fresh signing + encryption keypairs/CSRs to Danske's PKI via RenewCertificate — the request is enveloped-signed with the current signing certificate and XML-encrypted to the bank certificate (PKI WS spec §7) — and commits the new keys + certificates atomically on success. Run before the 2-year certificate expiry (the cert-expiring alerts fire at 30/14/7 days). A failed renewal leaves the current credentials untouched. Admin only.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Renewed
400Renewal failed (current credentials left untouched)
401Sign in required
403Admin required
404Connection not found
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/renew-nordea
Renew the Nordea Corporate Access signing certificate

Issues a fresh keypair + CSR (same subject as the current certificate) to Nordea's Certificate Service — the CertApplicationRequest is signed with the current certificate in place of the HMAC (Certificate Management §3.1.2), so no new SMS activation code is needed while the current certificate is valid — and commits the new key + certificate atomically on success. Run before the 2-year expiry (alerts at 30/14/7 days). A failed renewal leaves the current credentials untouched. Admin only.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Renewed
400Renewal failed (current credentials left untouched)
401Sign in required
403Admin required
404Connection not found
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/renew-bankconnect
Renew the Bank Connect customer certificate

Issues a fresh keypair + CSR (CN=functionId) to the Bank Connect data central via renewCustomerCertificate, signed with the current certificate, and commits the new key + certificate atomically on success. Run before the 3-year certificate expiry (the cert-expiring alerts fire at 30/14/7 days); the bank revokes the previous certificate 48 hours after a successful renewal. Admin only.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Renewed
400Renewal failed (current credentials left untouched)
401Sign in required
403Admin required
404Connection not found
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/generate-pgp
Generate our PGP key pair (SFTP channel)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200PGP key pair generated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/bank-key
Save the bank's PGP public key (SFTP channel)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
armoredKeystringyesASCII-armored PGP public key block.
Example
{
  "platformId": "string",
  "companyId": "string",
  "armoredKey": "string"
}
Responses
StatusDescription
200Bank key saved
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/server-info
Save SFTP server info (host, port, paths, fingerprint)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
hoststringyes
portintegerno
uploadPathstringno
downloadPathstringno
hostFingerprintstringno
Example
{
  "platformId": "string",
  "companyId": "string",
  "host": "string",
  "port": 22,
  "uploadPath": "string",
  "downloadPath": "string",
  "hostFingerprint": "string"
}
Responses
StatusDescription
200Server info saved
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/sftp-user
Set SFTP username and generate SSH key pair (single combined call)

Sets the SFTP username AND generates the SSH key pair in one call: you cannot pre-generate the key before you have the username. The username must be obtained from the bank first; only then can you call this endpoint. The response includes the connection + readiness state, from which you can retrieve the generated SSH public key to send to the bank for whitelisting.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
usernamestringyesSFTP username assigned by the bank. Required: the SSH key generation and username registration are a single atomic operation.
Example
{
  "platformId": "string",
  "companyId": "string",
  "username": "string"
}
Responses
StatusDescription
200Username set + SSH key generated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/approvers
Assign approver users to a connection

Assigns which users may approve payments on this connection. Approvers and approval policy are separate: the policy (under POST /approvals/policies) defines the rule (how many approvers, any amount thresholds); this endpoint assigns the eligible users per connection. Both must be in place for a connection to reach go-live. Note: users must first exist in the company: create them with POST /users before assigning them as approvers.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
userIdsstring[]yesUser IDs of company members with the Approver role. Must already exist in the company.
Example
{
  "platformId": "string",
  "companyId": "string",
  "userIds": [
    "string"
  ]
}
Responses
StatusDescription
200Approvers assigned
401Sign in required
403Admin required
422One or more user IDs are not valid approvers in this company
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/activate
Mark SFTP connection active (after the bank has whitelisted the SSH key)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Connection activated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/intro-email-sent
Mark intro email as sent (tracks wizard progress)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Updated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/ws-environment
Toggle a Web Services connection between TEST and PRODUCTION

Requires an already-activated connection (certificates issued); does not re-run PKI.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
environmentenumyes
Example
{
  "platformId": "string",
  "companyId": "string",
  "environment": "TEST"
}
Responses
StatusDescription
200Environment updated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/covered-banks
Set which member banks a shared connection covers

For a shared (group) connection. The store clamps the set to the bank's group and always includes the connection's own bank.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
coveredBankKeysstring[]yesBank keys this connection serves (clamped to the bank's group).
Example
{
  "platformId": "string",
  "companyId": "string",
  "coveredBankKeys": [
    "string"
  ]
}
Responses
StatusDescription
200Covered banks updated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/ebics-params
Save EBICS connection parameters (Host ID, Partner ID, User ID, …)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
urlstringyesEBICS server URL.
hostIdstringyesBank-assigned Host ID.
partnerIdstringyesCustomer ID (PartnerID) from the bank.
userIdstringyesSubscriber ID (UserID) from the bank.
protocolVersionstringno
signatureVersionstringno
subscriberModeenumno
Example
{
  "platformId": "string",
  "companyId": "string",
  "url": "string",
  "hostId": "string",
  "partnerId": "string",
  "userId": "string",
  "protocolVersion": "H005",
  "signatureVersion": "A006",
  "subscriberMode": "single"
}
Responses
StatusDescription
200EBICS params saved
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
POST/connections/{id}/ebics-generate-keys
Generate EBICS subscriber keys (authentication, encryption, signature)
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Keys generated
401Sign in required
403Admin required
Example response (200)
{
  "connection": {
    "id": "string",
    "bankKey": "nordea-dk",
    "bankName": "Nordea Danmark",
    "environment": "test",
    "channelType": "sftp",
    "active": false,
    "steps": {
      "introEmailSent": false,
      "pgpGenerated": false,
      "bankPublicKeyAdded": false,
      "serverInfoAdded": false,
      "sftpUserAdded": false,
      "approversAssigned": false,
      "certsIssued": false,
      "bankCertAdded": false,
      "ebicsKeysGenerated": false,
      "ebicsBankKeysFetched": false,
      "wsConfigAdded": false
    },
    "sshPublicKey": "string",
    "pgpPublicKey": "string",
    "approverUserIds": [
      "string"
    ],
    "createdAt": "2026-01-01T00: 00: 00Z"
  },
  "readiness": {
    "ready": false,
    "missing": [
      "string"
    ],
    "score": 0
  }
}
GET/connections/{id}/intro-email
Render the bank intro email (draft to send to the bank contact)
Parameters
NameInRequiredDescription
id stringpathyes
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200Rendered email (subject + body)
404Not found
GET/connections/{id}/ebics-letter
Download the EBICS initialisation letter (PDF, base64-encoded)

Returns the signed INI/HIA initialisation letter as a base64-encoded PDF. Print, sign, and send to the bank to complete EBICS subscriber activation.

Parameters
NameInRequiredDescription
id stringpathyes
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200PDF as base64
404Not found or keys not yet generated
Example response (200)
{
  "pdfBase64": "string",
  "filename": "string"
}
GET/banks/{bankKey}/setup-info
Per-bank setup descriptor for the wizard UI

Returns the channel kind, requirements text, field definitions, pre-known server/endpoint details, and SFTP wizard screens for a bank. Used by the setup wizard to render the correct flow.

Parameters
NameInRequiredDescription
bankKey BankKeypathyes
Responses
StatusDescription
200Setup descriptor
404Unknown bank
GET/banks/{bankKey}/settings
Get per-company settings for a specific bank
Parameters
NameInRequiredDescription
bankKey BankKeypathyes
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200Bank settings (null if none saved)
POST/banks/{bankKey}/settings
Update per-company settings for a specific bank

Payment-affecting fields (agreementId, chargeBearer, executionDateOffsetDays, approvalPolicyId) require Admin. The selected pin is open to any member.

Parameters
NameInRequiredDescription
bankKey BankKeypathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringno
companyIdstringno
agreementIdstringno
chargeBearerenumno
executionDateOffsetDaysintegerno
approvalPolicyIdstringno
selectedbooleanno
Example
{
  "platformId": "string",
  "companyId": "string",
  "agreementId": "string",
  "chargeBearer": "SLEV",
  "executionDateOffsetDays": 0,
  "approvalPolicyId": "string",
  "selected": false
}
Responses
StatusDescription
200Settings saved
401Sign in required
403Admin required for payment-affecting fields
GET/bank-settings
List all per-company bank settings in one call
Parameters
NameInRequiredDescription
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200All saved bank settings for this company
Example response (200)
{
  "settings": [
    {}
  ]
}

Approvals

Maker-checker approval policies + the pending-approval queue (session, Admin/Approver)

GET/approvals/pending
List payments awaiting approval
Parameters
NameInRequiredDescription
companyId stringqueryyes
Responses
StatusDescription
200Pending approval requests
401Sign in required
Example response (200)
{
  "requests": [
    {}
  ]
}
POST/approvals/{id}/approve
Approve a pending payment (maker ≠ checker enforced)

An approver other than the maker approves the request; once the policy's required approvals are met the payment proceeds to delivery. May require a 2FA code/backup code if step-up is configured.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
reasonstringno
codestringno2FA TOTP code (if step-up required).
backupCodestringno
Example
{
  "platformId": "string",
  "companyId": "string",
  "reason": "string",
  "code": "string",
  "backupCode": "string"
}
Responses
StatusDescription
200Approval recorded (and payment dispatched if fully approved)
401Sign in required
403Maker cannot approve own payment / not an approver
POST/approvals/{id}/reject
Reject a pending payment
Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
reasonstringno
Example
{
  "platformId": "string",
  "companyId": "string",
  "reason": "string"
}
Responses
StatusDescription
200Rejection recorded
401Sign in required
GET/approvals/policies
List approval policies for a company
Parameters
NameInRequiredDescription
companyId stringqueryyes
Responses
StatusDescription
200Policies
401Sign in required
Example response (200)
{
  "policies": [
    {}
  ]
}
POST/approvals/policies
Create an approval policy (Admin)

Defines required approver count + amount thresholds. Admin only.

Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
namestringyes
requiredApprovalsintegerno
thresholdAmountstringno
currencystringno
Example
{
  "platformId": "string",
  "companyId": "string",
  "name": "string",
  "requiredApprovals": 0,
  "thresholdAmount": "string",
  "currency": "string"
}
Responses
StatusDescription
201Policy created
401Sign in required
403Admin required
POST/approvals/policies/{id}
Edit a DRAFT approval policy (Admin)

Edit a policy's name / required approver count / thresholds. Works only on a DRAFT version — an Active version is immutable (409); change it via /approvals/policies/{id}/propose then co-sign.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
namestringno
requiredApprovalsintegerno
thresholdAmountstringno
currencystringno
Example
{
  "platformId": "string",
  "companyId": "string",
  "name": "string",
  "requiredApprovals": 0,
  "thresholdAmount": "string",
  "currency": "string"
}
Responses
StatusDescription
200Updated draft policy
401Sign in required
403Admin required
409Version is not a draft / conflict
Example response (200)
{
  "policy": {}
}
POST/approvals/policies/{id}/lock
Activate (lock) a draft approval policy (Admin)

Locks a DRAFT version → Active and immutable. Runs the quorum check (a dual policy needs ≥2 named approvers); fails 409 if it can't be met. An Active version is changed only via propose + co-sign.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Policy activated
401Sign in required
403Admin required
409Quorum not met / conflict
Example response (200)
{
  "policy": {}
}
POST/approvals/policies/{id}/propose
Propose a change to an Active policy (Admin)

Clones the Active version to an editable draft v(n+1). Edit the draft (POST /approvals/policies/{draftId}), then submit it for activation via POST /approvals/changes/{changeId}/submit and have a second Admin co-sign via POST /approvals/changes/{changeId}/cosign. The old version is retained forever once superseded.

Parameters
NameInRequiredDescription
id stringpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
201Draft version created
401Sign in required
403Admin required
409Base not Active / change already in progress
Example response (201)
{
  "policy": {}
}
GET/approvals/changes
List approval-policy change requests (Admin)

The dual-co-sign change requests for the company. ?status=pending (default) | activated | cancelled.

Parameters
NameInRequiredDescription
status enumqueryno
Responses
StatusDescription
200Change requests
401Sign in required
403Admin required
Example response (200)
{
  "changes": [
    {}
  ]
}
POST/approvals/changes/{changeId}/{action}
Submit / co-sign / cancel a policy change (Admin)

action=submit — the proposer submits the draft for activation (counts as the FIRST of 2 co-signs). action=cosign — a SECOND, distinct Admin co-signs: the new version goes Active, the base is Superseded, and attached banks re-point to the new version. action=cancel — any Admin cancels a pending change (the draft is discarded; the base stays Active). A 2nd co-sign by the same Admin is refused (409).

Parameters
NameInRequiredDescription
changeId stringpathyes
action enumpathyes
Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
Example
{
  "platformId": "string",
  "companyId": "string"
}
Responses
StatusDescription
200Change updated
401Sign in required
403Admin required
409Same-admin co-sign / conflict
Example response (200)
{
  "change": {},
  "policy": {},
  "supersededId": "string",
  "affectedBanks": [
    "string"
  ]
}

Auth

Login, session, and 2FA. Login + demo are PUBLIC; the rest need a session.

POST/auth/login
Log in (PUBLIC): returns a session token + sets the session cookie

PUBLIC. Exchanges subdomain + email + password for a signed session. If 2FA is enabled, returns a step-up challenge instead (complete it at POST /auth/2fa).

Request body required
PropertyTypeRequiredDescription
subdomainstringyes
emailstringyes
passwordstringyes
Example
{
  "subdomain": "demo",
  "email": "string",
  "password": "string"
}
Responses
StatusDescription
200Logged in (token) OR a 2FA step-up challenge
401Invalid credentials
Example response (200)
{
  "token": "string",
  "twoFactorRequired": false
}
Code samples
curl -X POST https://your-host/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"subdomain":"demo","email":"you@acme.com","password":"…"}'
const res = await fetch("https://your-host/auth/login", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"subdomain":"demo","email":"you@acme.com","password":"…"}),
});
const data = await res.json();
import requests

resp = requests.request(
  "POST", "https://your-host/auth/login",
  json={"subdomain":"demo","email":"you@acme.com","password":"…"},
)
resp.raise_for_status()
data = resp.json()
POST/2fa/setup
Begin 2FA enrollment (signed-in user) — returns a TOTP secret + otpauth URI

Generates a NOT-yet-active TOTP secret for the signed-in user and returns its otpauth:// URI (render as a QR). Activate it with POST /2fa/confirm. Session-only.

Responses
StatusDescription
200Pending secret + otpauth URI
401Sign in first
Example response (200)
{
  "secret": "string",
  "otpauthUri": "string",
  "issuer": "string"
}
POST/2fa/confirm
Confirm 2FA enrollment with a TOTP code — returns one-time backup codes

Verifies a code against the pending secret and activates 2FA. The backup codes are returned EXACTLY ONCE — surface + warn. Session-only; throttled per user.

Request body required
PropertyTypeRequiredDescription
codestringyes6-digit TOTP code
Example
{
  "code": "string"
}
Responses
StatusDescription
200Enabled + one-time backup codes
400Setup not started
409Already enabled
422Code didn't match
429Too many attempts (Retry-After)
Example response (200)
{
  "enabled": false,
  "backupCodes": [
    "string"
  ]
}
POST/2fa/disable
Disable 2FA (requires a fresh code; blocked when the company forces 2FA)

Turns off the signed-in user's 2FA after verifying a fresh TOTP or backup code; refused (403) when the company requires 2FA. Revokes the user's OTHER sessions. Session-only; throttled.

Request body required
PropertyTypeRequiredDescription
codestringno
backupCodestringno
Example
{
  "code": "string",
  "backupCode": "string"
}
Responses
StatusDescription
200Disabled
403Company requires 2FA
409Not enabled
422A valid code is required
429Too many attempts (Retry-After)
Example response (200)
{
  "enabled": false
}
POST/company/require-2fa
Admin: set the company-wide 2FA requirement

Admin-only. When enabled, every user in the company must enroll in 2FA. Distinct from the per-user enabled state — the response field is require2fa (company policy).

Request body required
PropertyTypeRequiredDescription
enabledbooleanyes
Example
{
  "enabled": false
}
Responses
StatusDescription
200Updated company policy
403Admin role required
Example response (200)
{
  "require2fa": false
}
GET/auth/me
Current principal (who am I)
Responses
StatusDescription
200The signed-in user + roles + company
401Not signed in
POST/auth/logout
Log out (invalidates the session)
Responses
StatusDescription
200Logged out
GET/auth/platform-info
Public platform branding for the login page

Returns the branding for the platform resolved from the request's subdomain (no auth — called before login). On a known subdomain: the platform's display name + subdomain. Otherwise the generic BankConnector branding. logoUrl is reserved for a later phase (null for now).

Responses
StatusDescription
200Platform branding
Example response (200)
{
  "platformId": "string",
  "displayName": "string",
  "subdomain": "string",
  "logoUrl": "string"
}
POST/auth/2fa
Complete a 2FA login step-up (PUBLIC)

PUBLIC. Submits the TOTP (or backup) code against the challenge from POST /auth/login to obtain the session.

Request body required
PropertyTypeRequiredDescription
challengestringyesThe challenge id from /auth/login.
codestringyes
backupCodestringno
Example
{
  "challenge": "string",
  "code": "string",
  "backupCode": "string"
}
Responses
StatusDescription
200Session granted
401Invalid code
Example response (200)
{
  "token": "string"
}

User Management

Create, invite, and manage users within a company. Also covers workspace (platform) admin accounts.

GET/platforms/{platformId}/admins
List workspace admins for a platform

Returns all workspace (platform) admin accounts. Workspace-admin session required.

Parameters
NameInRequiredDescription
platformId stringpathyes
Responses
StatusDescription
200Workspace admins
403Not a workspace admin
Example response (200)
{
  "items": [
    {
      "id": "string",
      "email": "string",
      "name": "string"
    }
  ],
  "nextCursor": "string"
}
POST/platforms/{platformId}/admins
Create a workspace admin

Creates a new workspace (platform) admin account with a password. Bootstrap note: when the server is running in open/unauthenticated mode (no BANKCONNECTOR_API_KEYS set, e.g. first-time setup), this endpoint is accessible without a session: use it to create the very first admin. Once auth is enabled, an existing workspace-admin session is required.

Request body required
PropertyTypeRequiredDescription
emailstringyes
namestringyes
passwordstringyesInitial password. Minimum 8 characters.
Example
{
  "email": "admin@acme.com",
  "name": "Alice Admin",
  "password": "string"
}
Responses
StatusDescription
201Admin created
400Invalid request or duplicate email
403Not a workspace admin (when auth is enabled)
Example response (201)
{
  "id": "string",
  "email": "string",
  "name": "string"
}
GET/users
List users in a company

Returns all users in the company (name, email, roles, status). Readable by any authenticated company member.

Parameters
NameInRequiredDescription
platformId stringqueryyes
companyId stringqueryyes
Responses
StatusDescription
200Company users
401Sign in required
Example response (200)
{
  "users": [
    {
      "id": "string",
      "email": "string",
      "name": "string",
      "roles": [
        "admin"
      ],
      "status": "active"
    }
  ]
}
POST/users
Create or invite a company user

Company admin only. Two modes:

  • With password: creates the user immediately (active). Use for programmatic provisioning.
  • Without password: sends an invite email. The user receives a link to /auth/set-password where they set their own password.

The user must be given at least one role (admin, approver, and/or viewer). Users who will be assigned as payment approvers need the approver role.

Request body required
PropertyTypeRequiredDescription
platformIdstringyes
companyIdstringyes
emailstringyes
namestringyes
rolesenum[]yes
passwordstringnoIf omitted, an invite email is sent and the user sets their own password.
Example
{
  "platformId": "string",
  "companyId": "string",
  "email": "approver@acme.com",
  "name": "Bob Approver",
  "roles": [
    "approver"
  ],
  "password": "string"
}
Responses
StatusDescription
201User created or invite sent
400Invalid request, duplicate email, or no valid roles
403Company admin required
Example response (201)
{
  "id": "string",
  "email": "string",
  "name": "string",
  "roles": [
    "string"
  ],
  "invited": false
}
POST/auth/set-password
Complete an invite: set password from email token (PUBLIC)

PUBLIC. Called when an invited user clicks their invite link. Validates the one-time token and sets the user's password. Any existing sessions for the user are revoked. The token comes from the invite email.

Request body required
PropertyTypeRequiredDescription
tokenstringyesThe one-time invite token from the email link.
passwordstringyesThe user's chosen password.
Example
{
  "token": "string",
  "password": "string"
}
Responses
StatusDescription
200Password set
400Invalid or expired token
429Too many attempts: IP rate-limited
Example response (200)
{
  "ok": false,
  "email": "string"
}

Platform

Tenant dashboard + per-bank test payments

GET/bank-requests
List all bank requests (Admin only)
Responses
StatusDescription
200All requests
401Sign in required
403Admin required
Example response (200)
{
  "items": [
    {}
  ]
}
POST/bank-requests
Request a bank we don't support yet

Any signed-in user (or anonymous) can submit a BIC or bank name. The request is queued for the development team.

Request body required
PropertyTypeRequiredDescription
querystringyesBIC code or bank name.
emailstringno
Example
{
  "query": "string",
  "email": "string"
}
Responses
StatusDescription
201Request recorded
400Empty query
Example response (201)
{
  "ok": false,
  "request": {
    "id": "string",
    "query": "string",
    "createdAt": "2026-01-01T00: 00: 00Z"
  }
}

Workspace Admin

GET/platforms/{platformId}/companies
List the companies under a platform

Workspace (platform) admin only. The company list a workspace admin manages: drives the GUI company list + company-switcher (POST /auth/company-context).

Parameters
NameInRequiredDescription
platformId stringpathyes
Responses
StatusDescription
200Companies
403Not a workspace admin
Example response (200)
{
  "items": [
    {
      "id": "string",
      "name": "string",
      "createdAt": "2026-01-01T00: 00: 00Z"
    }
  ],
  "nextCursor": "string"
}
POST/platforms/{platformId}/companies
Create a company under a platform

Workspace (platform) admin only. Creates a new company (tenant) under the platform. Requires a session (workspace-admin login): not an API key. After creation, use POST /auth/company-context to enter the company and make company-scoped calls.

Parameters
NameInRequiredDescription
platformId stringpathyes
Request body required
PropertyTypeRequiredDescription
namestringyesDisplay name for the company.
Example
{
  "name": "Acme Payments Ltd"
}
Responses
StatusDescription
201Company created
400Invalid request
403Not a workspace admin
Example response (201)
{
  "company": {
    "id": "comp_…",
    "name": "string",
    "createdAt": "2026-01-01T00: 00: 00Z"
  }
}
POST/auth/company-context
Enter a company context (platform admin acts AS a company)

Workspace (platform) admin only. Sets the session's active company so the admin acts as an ADMIN of that company. The company must belong to the admin's platform. Cleared with DELETE.

Request body required
PropertyTypeRequiredDescription
companyIdstringyes
Example
{
  "companyId": "string"
}
Responses
StatusDescription
200Context set
403Not a workspace admin
404Unknown company in your platform
Example response (200)
{
  "ok": false
}
DELETE/auth/company-context
Exit the company context (back to pure platform-admin scope)
Responses
StatusDescription
200Context cleared
403Not a workspace admin
Example response (200)
{
  "ok": false
}
GET/platforms/{platformId}/api-keys
List a platform's API keys (metadata only: never the secret)

Workspace (platform) admin only. Returns active (non-revoked) keys with id, label, createdAt and lastUsedAt. The raw key is NEVER returned here: it is shown once, at creation.

Parameters
NameInRequiredDescription
platformId stringpathyes
Responses
StatusDescription
200API keys (no secret)
403Not a workspace admin
Example response (200)
{
  "items": [
    {
      "id": "string",
      "label": "string",
      "createdAt": "2026-01-01T00: 00: 00Z",
      "lastUsedAt": "2026-01-01T00: 00: 00Z"
    }
  ],
  "nextCursor": "string"
}
POST/platforms/{platformId}/api-keys
Create an API key: the raw key is returned ONCE

Workspace (platform) admin only. Mints a new platform API key; the raw key value appears ONLY in this 201 response and is never stored or retrievable again. Store it securely.

Parameters
NameInRequiredDescription
platformId stringpathyes
Request body required
PropertyTypeRequiredDescription
labelstringyesHuman name, e.g. "Production ERP".
Example
{
  "label": "string"
}
Responses
StatusDescription
201Key created: raw key shown once
400Invalid request
403Not a workspace admin
Example response (201)
{
  "id": "string",
  "key": "string",
  "label": "string",
  "createdAt": "2026-01-01T00: 00: 00Z"
}
DELETE/platforms/{platformId}/api-keys/{keyId}
Revoke an API key

Workspace (platform) admin only. Soft-revokes the key (it stays for audit but stops authenticating immediately).

Parameters
NameInRequiredDescription
platformId stringpathyes
keyId stringpathyes
Responses
StatusDescription
200Revoked
403Not a workspace admin
404Unknown key for this platform