{"openapi":"3.1.0","info":{"title":"POST /api/v1/credit/bank-connections","version":"1.0.0","description":"Start a merchant's bank connection"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/credit/bank-connections":{"post":{"tags":["credit"],"summary":"Start a merchant's bank connection","description":"The Connect step of the Apply wizard (§9.3), and the Link button of Change Payment Method (§6.2). Name the merchant (`program_id` and `external_merchant_id` while it applies, or `credit_line_id` once it has a line). DayZero uses the merchant's DayZero business, creating it the first time, gives your token read access to it, and returns a hosted Plaid Link (`hosted_link_url`, `expires_at`) for the merchant to complete in your wizard. Nothing is emailed. While one is pending for the same merchant (or line), a repeat returns it with `created: false`. When the merchant finishes, `credit.bank_connection.completed` is emitted and the bank backfill underwriting waits on starts.","operationId":"create_credit_bank_connection","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankConnectionStartRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_BankConnectionResponse_"}}}},"400":{"description":"Bad Request - Invalid input","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: due_date: Input should be a valid date","errors":{"due_date":"Input should be a valid date"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Resource does not exist","content":{"application/json":{"example":{"error":"not_found","message":"Resource not found","code":"NOT_FOUND_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests - Rate limit exceeded; back off and retry","content":{"application/json":{"example":{"error":"rate_limited","message":"Too many requests. Please slow down.","code":"GEN_005","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"example":{"error":"service_unavailable","message":"The service is temporarily unavailable. Please try again later.","code":"GEN_004","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"}}}}},"x-fastapi-operation-id":"create_credit_bank_connection_api_v1_credit_bank_connections_post"}}},"components":{"schemas":{"BankConnectionAccount":{"properties":{"plaid_account_id":{"type":"string","title":"Plaid Account Id","description":"The account's Plaid id: what `plaid_account_id` on the line holds and `credit.autopay.due` carries."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"The account's name."},"mask":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mask","description":"The last four digits of the account number."},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"Plaid's type: depository, credit, loan, ..."},"subtype":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subtype","description":"Plaid's subtype: checking, savings, ..."}},"type":"object","required":["plaid_account_id"],"title":"BankConnectionAccount","description":"One account the merchant shared. No numbers, no tokens."},"BankConnectionResponse":{"properties":{"id":{"type":"string","title":"Id","description":"The bank connection's id."},"status":{"type":"string","enum":["pending","completed","failed","expired"],"title":"Status","description":"pending: the Link is out. completed: the merchant connected a bank. failed: the merchant left Link or Plaid could not connect (see `failure_reason`); start again. expired: the Link lapsed unused."},"created":{"type":"boolean","title":"Created","description":"False when the call returned a connection already pending for this merchant instead of starting one.","default":false},"program_id":{"type":"string","title":"Program Id","description":"The program the connection is under."},"credit_line_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Line Id","description":"The line the chosen account is recorded on; null before one opens."},"external_merchant_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Merchant Id","description":"Your id for the merchant."},"merchant_business_id":{"type":"string","title":"Merchant Business Id","description":"The merchant's DayZero business. Send it as `subject_business_id` on `POST /credit/underwriting/assessments`, and as `merchant_business_id` on `POST /credit/lines` (a line opened with the same `external_merchant_id` is linked to it when you leave it out)."},"merchant_business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Business Name","description":"The merchant business's name."},"merchant_business_created":{"type":"boolean","title":"Merchant Business Created","description":"Whether starting this connection created the merchant's business.","default":false},"hosted_link_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hosted Link Url","description":"The hosted Plaid Link the merchant completes in your wizard. Null once the connection is no longer pending. On a sandbox it is a placeholder that opens nothing: finish it with `POST /credit/sandbox/bank-connections/{id}/complete`."},"expires_at":{"type":"string","format":"date-time","title":"Expires At","description":"When the Link stops working, UTC. Start again after it."},"completion_redirect_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completion Redirect Uri","description":"Where Plaid sends the merchant when Link finishes."},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"When the connection was started, UTC."},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At","description":"When the merchant finished Link (completed or failed), UTC."},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Reason","description":"When failed: exited (the merchant left Link), plaid_error (Plaid could not establish the connection) or no_accounts (nothing was shared)."},"institution_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Institution Name","description":"The bank the merchant connected."},"accounts":{"items":{"$ref":"#/components/schemas/BankConnectionAccount"},"type":"array","title":"Accounts","description":"The accounts the merchant shared, once completed."},"plaid_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plaid Account Id","description":"The repayment account: the one checking account the merchant shared, else the one depository account. Null when the merchant shared several and none stands out; choose with the merchant and send it on `PATCH /credit/lines/{id}`."},"linked_account_mask":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linked Account Mask","description":"The repayment account's last four."},"linked_account_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linked Account Name","description":"The repayment account's name."},"recorded_on_line":{"type":"boolean","title":"Recorded On Line","description":"True when the repayment account was written to the line (`plaid_account_id`, `linked_account_mask`, `linked_account_name`).","default":false},"sandbox":{"type":"boolean","title":"Sandbox","description":"True on a sandbox: no Plaid call was made.","default":false},"reconnect":{"type":"boolean","title":"Reconnect","description":"True when the Link repairs an existing bank connection (Plaid update mode) rather than linking a new bank.","default":false}},"type":"object","required":["id","status","program_id","merchant_business_id","expires_at"],"title":"BankConnectionResponse","description":"A started bank connection and where it stands."},"BankConnectionStartRequest":{"properties":{"program_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Program Id","description":"Your program the merchant is applying under. Required without `credit_line_id`; with it, must be the line's program if sent."},"external_merchant_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"External Merchant Id","description":"Your id for the merchant, as you will send it on `POST /credit/lines`. Required without `credit_line_id`. Every start for the same merchant uses the same DayZero business."},"credit_line_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credit Line Id","description":"An open line of yours (Change Payment Method, §6.2). The account the merchant chooses is recorded on it. The line's program and merchant are used; a different `program_id` or `external_merchant_id` is `400` `CREDIT_781`."},"merchant_legal_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Merchant Legal Name","description":"Names the merchant's DayZero business when this call creates it. Defaults to the line's `merchant_legal_name`, else \"Merchant <external_merchant_id>\". Ignored when the business exists."},"merchant_email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Merchant Email","description":"The merchant's email address, which Plaid asks for with the Link. DayZero does not email the merchant: the Link is returned to you. Defaults to the line's `merchant_email`; required when neither is there (`400` `CREDIT_785`)."},"merchant_business_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Business Id","description":"The merchant's existing DayZero business, when it already keeps its books on DayZero and your token can reach it. Leave it out and DayZero uses the business this merchant was linked to before, or creates one. Naming another business than the one the merchant is linked to is `400` `CREDIT_788`."},"completion_redirect_uri":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Completion Redirect Uri","description":"Where Plaid sends the merchant when Link finishes, e.g. your wizard's next step. Must be one of the program's `bank_link_redirect_uris`, exactly (`400` `CREDIT_782` otherwise). Without it Plaid shows its own finished page."},"reconnect":{"type":"boolean","title":"Reconnect","description":"Repair the merchant's existing bank connection instead of linking a new bank: the Link is Plaid's update mode on the connection that needs the merchant to log in again (the one an assessment's `waiting_on: bank_reconnect` and `credit.bank_connection.reconnect_required` point at). The merchant's business must already exist; with no such connection it is `400` `CREDIT_779`. Completion is `credit.bank_connection.completed`, as for a new bank.","default":false}},"additionalProperties":false,"type":"object","title":"BankConnectionStartRequest","description":"Start a merchant's bank connection: name the merchant, get a Link."},"SuccessEnvelope_BankConnectionResponse_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/BankConnectionResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[BankConnectionResponse]"},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}