# home Source: https://docs.synctera.com/home
Welcome to Synctera's docs

Explore our documentation to learn how to quickly and easily build a FinTech app or embedded banking product with Synctera.

## Get started Create a Synctera account to get your API key, access our sandbox, and explore the rest of our Console. Sign up ## Explore our documentation Learn everything you need to know about integrating with our APIs and how to make your use case come to life. View the API Guides Everything you need to make your project come to life can be found here. View the APIs ## Dive into our APIs Creates and manages records for personal customers Creates and manages records for business customers Creates and manages customer accounts Issues, activates, and manages cards for customers Transfer funds between two accounts in real-time Create and manage scheduled payments for customers Issue cards, accept payments, and transfer money between accounts Handles remote deposit capture (RDC) transactions Create and manage documentation for a customer and run verification checks Verify documentation for a customer Handles legally required disclosures to customers
# ACH Payments Source: https://docs.synctera.com/v2/docs/ach-guide If you’re building a service that will enable your customers to send and accept payments, issue cards, or transfer money between accounts at different institutions, chances are you’ll need ACH. ACH is a one-stop shop for a variety of payment use cases. From recurring payments and payroll deposits to online purchases and bill payment, ACH offers a fast and flexible way to send money. Originally established in 1970, expanding support and innovation around ACH payments has led it to become one of the most popular online payment rails in the world. ## What is an ACH Transaction? An ACH transaction (often referred to as an ACH transfer) is an electronic, bank-to-bank money transfer processed through the Automated Clearing House (ACH) Network. You can think of the ACH Network as a postal service for ACH files. Each file can contain up to 1000 ACH entries with each entry representing a transaction being sent from one bank to another. ACH transactions can be used to facilitate Person-to-person (P2P), Business-to-consumer (B2C), and Business-to-business (B2B) payments and is a convenient alternative to card networks, wire transfers, paper checks or cash. In addition to their convenience, ACH transactions are reliable, inexpensive, fast, and most importantly, safe. Most transfers are processed and settled within 1-2 business day with zero cost to the consumer. See our [ACH Transfers - Risk and Compliance](/docs/ach-payments-risk-and-compliance) guide for more details on risks and controls, account validation, and NACHA requirements surrounding return rates. ## What are the 2 types of ACH Transactions? Each ACH transaction involves 2 primary parties: 1. The **Originating Depository Financial Institution (ODFI)** which is the bank initiating the transaction; and 2. The **Receiving Depository Financial Institution (RDFI),** the bank receiving the transaction. All transactions fall into one of two categories, debit (“pull”) or credit (“push”). ### Push (Credit) Determining if a transaction is a push or pull is always with respect to the receiving account. For example, if Tom, a customer of Bank A wants to send money to John, a customer of Bank B. Tom’s bank can originate an ACH push transaction from his account to John’s account. The term “push” is used interchangeably with “credit”. The result is a credit to John’s (the receiver) account balance and a debit to Tom’s (the sender). A real life use case for push transactions are the deposits that result from an employee signing up for payroll direct deposit. Whenever payday rolls around, the employer’s bank initiates a push/credit to the employee’s bank account. ### Pull (Debit) Alternatively, if Tom want’s to request money from John, Tom’s bank can originate an ACH pull request from his account to John’s. The term “pull” is used interchangeably with “debit”. The result is a debit to John’s account and a credit to Tom’s. This is what occurs when users of a service sign up for recurring bill payments. The service provider ends up debiting the customer’s account via an ACH pull request. This is also the case when a banking customer deposits a check made out to him/her by an account holder at another financial institution. Checks are ultimately translated into pull request on the ACH network. The check contains the account holders routing and account number which are the only pieces of information required to initiate a credit or debit from an account at another institution. There is a difference between the direction of an ACH transaction and the direction of money flow. The direction of the transaction refers to the direction of the ACH message on the network. It always flows from the originator to the receiver while the direction of money flow relates to which account is receiving funds and which account is sending them. This means there are 2 ways to achieve the same direction of money movement. ## Scenario The desired result is to withdraw funds from an account at **Bank A** and deposit them into an account at **Bank B** ### Option 1 (This is how customers fund their accounts) Bank B sends an ACH **debit / pull** transaction requesting funds from the account at Bank A: ### Option 2 Bank A sends an ACH **credit / push** transaction to send funds to the account at Bank B. ## How does Synctera support ACH? From the outside, the ACH workflow may seem simple, but it’s actually quite complex. This is where Synctera comes in. Synctera works with your sponsor bank to serve as your connection to the ACH network and supports sending and accepting ACH transactions from other financial institutions. In ACH terms, Synctera acts as the **ODFI** (Originating Depository Financial Institution) when it comes to originating transactions and the **RDFI** (Receiving Depository Financial Institution) when it comes to receiving them. It means that we take care of all the batch processing and file generation while ensuring that all transactions are reflected in your customer account balances. ### FinTech in the Auth Flow Synctera allows the FinTech to participate in the transaction authorization decision for Inbound ACH Direct Debit. This capability can only be enabled for linked zero balance accounts and can be used to: * Restrict payments to certain institutions * Run your own balance checks against the linked balance carrying account If the transaction is declined by the FinTech, then an ACH return will be sent to the network. The FinTech does not have to participate unless there is an additional approval logic. If the FinTech opts not to participate in the Auth Flow, Synctera will use default authorization logic to authorize the transactions. In order to participate in Auth Flow for Pull (Debit) ACH transactions, the FinTech should support an **Authorization Gateway** and a corresponding **Gateway Endpoint** must be configured on the Synctera side. #### Authorization Gateway An authorization Gateway enables a FinTech to optionally take part in the decision of a Pull (Debit) ACH transaction’s authorization cycle. The FinTech receives an authorization request via the configured Gateway to either **approve** or **decline** corresponding ACH transactions based on the FinTech's own business logic. **Request Body** Synctera sends such information as a `POST` HTTP request to the FinTech about Pull (Debit) ACH transactions that needs to be authorized: ```json JSON theme={"system"} { "customer_id": "2b9cc6f2-d0bd-4d9d-aa20-5e53355f9469", "account_id": "0221e0a7-7774-48a4-8521-e678ec09a53a", "transaction_id": "9b59fc80-9bf5-4749-8dd2-511f183becf2", "settlement_date": "2022-03-25", "effective_date": "2022-03-25", "transaction_type": "incoming_debit", "dc_sign": "debit", "amount": 100, "currency": "USD", "network": "ACH", "company_entry_description": "ACCTVERIFY", "company_name": "PAYPAL" } ``` **Response HTTP code** To signal an authorization request decision, the FinTech must reply with the appropriate HTTP code: * HTTP code `200`: **approve** the corresponding ACH transaction * HTTP code `402`: **decline** the corresponding ACH transaction Receiving any other HTTP code in the response will stop the processing of the corresponding Pull (Debit) ACH transaction. However, in this case the transaction will ***not be declined***, but will be ***retried within 2 days*** until the FinTech responds with either `200` or `402` response. **Response timeout** Synctera waits for the authorization response within the timeout window which **defaults to 1.5 seconds**, but can be configured in the **Gateway Endpoint Configuration**. If the response is not received within the defined timeout window, the corresponding Pull (Debit) ACH transaction will stop being processed. But will ***not be declined*** and will be ***retried with exponential backoff*** until the FinTech sends the response within the defined timeout window. If no response is given within the retry window (default: 35 minutes, configurable per bank/partner via `auth_retry_config`), the ACH will be sent to suspense for a manual review by Payment Operations. #### Gateway Endpoint Configuration To configure a Gateway for the FinTech, a valid publicly accessible `url` must be provided. Additionally, `custom_headers` and custom response timeout in milliseconds `max_wait_ms` can be configured. Also, Gateways may be disabled by setting the `disabled` field to `true`. ```sh Shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ $baseurl/v0/ach/gateways \ --data-binary ' { "url": "https://example-fintech.com/ach/auth", "custom_headers": { "key1": ["value1", "value2"], "key2": ["value"] }, "max_wait_ms: 1500, "disabled": false }' ``` ## How are accounts funded using ACH? Once your customers have an account setup, they’ll need to fund their account by originating an ACH pull/debit transaction to be sent to their account at another institution. Synctera refers to this as an [external account](/v2/docs/external-accounts-guide). If you have just created account B on the Synctera platform and you want to add funds to it from account A at another financial institution, its natural to assume that funding involves *pushing* funds from account A to account B. Instead, funding your customers account involves originating an ACH debit/pull transaction with your Synctera account in order to withdraw funds from the external account. ## How do I get started with sending/receiving ACH payments? ### Step 1: Customer Creation 1.1 **Create a Customer** Any individual wanting to transact on the Synctera platform must be stored as a customer in our system. Part of that includes completing the KYC process. See the [Customer guide](/v2/docs/create-a-personal-customer) for details. ### Step 2: Account Creation 2.1 **Create an Account** In order to send and receive ACH payments you will need to create an account and associate it with your customer. [Account Guide](/v2/docs/create-accounts-guide) 2.2 **Create an External Account** In order for your customers to fund their accounts they’ll need to debit funds from an account at another institution. You'll need to create an external account on the Synctera platform which serves as the internal representation of the account to be debited. [External Account Guide](/v2/docs/external-accounts-guide) ### Step 3: Send/Receive an ACH 3.1 **Send an ACH request** Once the external account has been verified, ACH transactions (credits and debits) can be originated from your customer’s account. If you’re unsure what values to set in your API request take a look at the documentation [here](/v2/reference/addtransactionout). 3.2 **Receive an ACH transaction** As long as your customer has an account that is both active and verified, there is no work required by you or your customer to receive ACH transactions. Synctera will process the incoming transaction and debit/credit the account accordingly. ## What happens after I send an ACH request? After you send a request to originate an ACH transaction, the transaction is placed in a batch which, in turn, is placed in an ACH file to be sent out over the network. Depending on the time that you originate the transaction there may be some delay between the time the transaction is created and the time the file is sent. This is done to align with the [processing schedule](https://www.frbservices.org/resources/resource-centers/same-day-ach/fedach-processing-schedule.html) set by the federal reserve. The date the transaction is sent will ultimately determine when funds are settled across accounts and institutions. It will also have a bearing on if and when an ACH transaction can be returned by the recipient. The responsibilities and guidelines for participants in the ACH system are determined by the National Automated Clearing House Association, better known as NACHA. NACHA operates as the rule making body for all financial institutions wanting to use the ACH system. ## What do I need to do to receive an ACH transaction? Nothing. Unless an incoming transaction needs to be returned (see [Why would an ACH transaction be returned?](#why-would-an-ach-transaction-be-returned)), no action is required. Synctera will process all debit and credits for any ACH transactions that we receive on behalf of you or your customers. Check your Synctera dashboard to view all ACH transaction that have been sent or received. Synctera also supports webhooks to notify you of all ACH transactions. ## How long does it take to process an ACH transaction? The time it takes for the network to completely process an ACH transaction is dependent on a number of variables. The operating schedule of the federal reserve, the operating schedule of each bank, and the time of day the transaction was created are all key factors in determining when a transaction will settle. “Settle”. Integrators can influence the timing of an ACH transaction by setting the `is_same_day` field to `true` when posting a request to send a transaction. However, even when sending “same day” ACH transfers, there are a couple things to keep in mind: * Transactions can be returned up to 2 business days after the settlement day. This introduces risk for fintech’s who choose to make funds immediately available to account owner who have initiated a pull request. The ACH system operates on a “no news is good news” basis. The absence of a return within the 2-day timeframe typically means that the RDFI has accepted the transaction. * “Same day” ACH is only available within certain transmission windows set by the federal reserve. Take a look at the Fed [processing schedule](https://www.frbservices.org/resources/resource-centers/same-day-ach/fedach-processing-schedule.html) for more information on cut off times. In general, transactions submitted (Mon-Fri) by 4:45pm are eligible to settle on the same day. “Same day” is not available on non-banking days (weekends and holidays) and will automatically default to the next available “banking day”. * Submitting incorrect information may cause processing errors that result in delays. Errors may also increase the likelihood of a transaction being returned. ## Why would an ACH transaction be returned? ACH transactions can be returned for a variety of reasons. “Insufficient funds”, “invalid account number”, “account closed” are all fair game but but many of the return reasons are not so obvious. NACHA guidelines specify [85 different codes](https://engineering.gusto.com/how-ach-works-a-developer-perspective-part-2/#appendix) that may be associated with a returned transaction. The good news is that you and your customers are likely to see only the most common ones. Synctera will take care of processing any returned transaction and notify you of the resolution via webhooks. In the event that a returned transaction requires your immediate attention, you will be able to take action through the Synctera dashboard. The dashboard is also were you can generate returns from received ACH transactions. While most transaction failures such as insufficient funds, invalid account, etc., will result in automatic returns, you may occasionally identify transactions that were not authorized and choose to manually initiate a return. ## ACH same day vs non-same day cut-off times | ACH Type | Cut-off time | Comments | | ------------ | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | Same day | 4:45 pm ET (1:45 pm PT) (Monday - Friday) | Same day ACH payments with effective date of today submitted before 4:45 pm ET will be processed as ‘same day’ ACH | | Non-Same day | 24:00 pm ET (Monday-Friday) | Non same ACH payments with effective date of tomorrow or 2 days in the future submitted before 24:00 will be processed as ‘non-same day’ | **ACH (Debit/Credit) - External bank to Synctera account** | ACH Type | File processing time | Comments | | ------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | Same day | 10:30 am ET2:45 pm ET4:45 pm ET | ACH Batch files with same day payments (debits/credits/returns) directed to Synctera accounts will be processed at these times | | Non same day / future dated ACH | 10:30 am ET2:45 pm ET4:45 pm ET8:00 pm ET \*2:15 am ET \* | ACH Batch files with non-same day payments (debits/credits/returns) directed to the Synctera accounts will be processed at these times | Not all of our sponsor banks support 8:00 pm ET / 2:15 am ET exchange times **ACH Returns - External bank to Synctera account** | Return code | Days from original transaction | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | | **R01:** NSF | 2 Banking Days | | **R02:** Account closed | 2 Banking Days | | **R03:** No Account - Account number structure is valid, but doesn't match individual or Open account | 2 Banking Days | | **R04:** Invalid Account - Account number structure not valid, ie edit check digit or number failed | 2 Banking Days | | **R05:** Unauthorized Debit to Consumer Account Using Corporate SEC Code - A Debit entry that uses a corporate SEC code was transmitted to a consumer but was not authorized by the consumer | 60 Calendar Days | | **R07:** Authorization Revoked - Customer who previously authorized an entry claims, authorization has been revoked from the Originator | 60 Calendar Days | | **R08:** Payment Stopped: The customer has requested the stop payment of a specific ACH Debit Entry | 2 Banking Days | | **R09:** Sufficient ledger balance exists, but value of uncollected items brings available balance below amount of debit entry | 2 Banking Days | | **R10:** Customer Advises Not Authorized, Improper, Ineligible, Part of Incomplete transaction or Improperly reinitiated - Not authorized, wrong amount, debit date before authorized, incomplete transaction, improper source document or exceeds reinitiating attempt | 60 Calendar Days | | **R12:** Account sold to another FI | 2 Banking Days | | **R16:** Account frozen/Entry Returned Per OFAC Instruction - Access to account is restricted due to action by the bank | 2 Banking Days | | **R20:** Non-transaction Account - Policies and regulations restrict activity to account indicated | 2 Banking Days | | **R24:** Duplicate Entry - Entry is a duplication. The trace number, date, dollar amount, etc. match another entry | 2 Banking Days | | **R29:** Corporate Customer Advises Not Authorized | 2 Banking Days | | **R31:** Permissible Return Entry - Sender bank agreed on behalf of the Originator to accept a return after the deadline for an unauthorized corporate entry | Undefined | | **R37:** Source document Presented for Payment - The source document to which an ARC or BOC or POP entry relates has also been presented for payment | 60 Calendar Days | | **R38:** Stop Payment of Source Document - A Stop Payment has been placed on the source document to which the ARC or BOC Entry relates. | 60 Calendar Days | | **R39:** Improper Source Document/Source Document presented for payment - The RDFI determines the source document for the ARC, BOC or POP entry is not an eligible item or was presented for payments | 2 Banking Days | | **R50:** State Law Affecting RCK Acceptance - RDFI is located in a state that has not adopted Revised Article 4 of the UCC or RDFI is located in a state that requires all canceled checks to be returned to the receiver | 2 Banking Days | | **R51:** Item is Ineligible, Notice Not Provided, Signatures not Genuine, Item Altered or Amount of RCK Not Accurately Obtained from the Item | 60 Calendar Days | | | | ## Company Entry Description As of March 20, 2026, NACHA dictates that ACH transactions meeting the requirements for Payroll or Purchase transactions are required to be classified in the Company Entry Description as such: `PAYROLL`: wages, salary, or other similar types of compensation for labor or services. `PURCHASE`: e-commerce purchases authorized by a consumer receiver for the online purchase of goods. This does not include recurring bills such as utilities, mortgages or other types of bill payments. If sending a Payroll or Purchase payment via Synctera ACH, include the `PAYROLL` or `PURCHASE` descriptor in the `company_entry_description` field accordingly. ## Example: Funding a customer account To fund a customer account from an external bank account the Synctera API: ```shell shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ https://api.synctera.com/v0/ach \ --data-binary ' { "risk": { "client_ip": "127.0.0.1" }, "customer_id": "{CUSTOMER_ID}", "amount": 100, "currency": "USD", "receiving_account_id": "{EXTERNAL_ACCOUNT_ID}", "dc_sign": "debit", "originating_account_id": "{ACCOUNT_ID}", "reference_info": "Synctera test", "memo": "Synctera test" }' ``` It is important to note a few things in this example: 1. The `receiving_account_id` always refers to an [External Account](/v2/docs/external-accounts-guide). 2. The `originating_account_id` always refers to to an [Account](/v2/docs/create-accounts-guide). 3. The `dc_sign` is always from the perspective of the **receiving** account. So a `debit` to the receiving account results in a credit to the originating account. 4. The `amount` is always in the smallest denomination of the given currency. In this case, the currency is `USD`, which means the amount is in cents. 5. The `customer_id` indicates the person that is making the outgoing ACH request. This customer must be an account holder or authorized signer of `originating_account_id` # Adverse Actions Source: https://docs.synctera.com/v2/docs/adverse-actions-guide Adverse action notices record and communicate the reasons a credit decision adversely affected a customer, as required by the ECOA and FCRA. ## Overview Adverse action notifications are a cornerstone of regulatory compliance in financial services. Mandated by the Equal Credit Opportunity Act (ECOA) and the Fair Credit Reporting Act (FCRA), they ensure applicants are informed promptly and transparently when a decision adversely affecting them is made. The Adverse Actions API streamlines recording these notices and associating them with the application or account they concern. **An adverse action** captures the reasons a customer was denied credit — or offered less favorable terms than requested — along with the purpose of the decision and the resource it relates to. Key characteristics: * **Reason-bearing** — a notice carries up to four principal `reasons` (a fifth may be required if one reason is inquiry-related). * **Purpose-scoped** — the `purpose` records the point in the account lifecycle the decision was made (e.g. `ACCOUNT_OPENING`, `ACCOUNT_CLOSURE`). * **Associated** — every notice is tied to an application or account via `related_resource_id` and `related_resource_type`. * **Timely** — the notice of adverse action (NOAA) must generally be delivered within 30 days of the credit decision. A fintech must give customers specific reasons when credit is denied or terms are less favorable than requested — typically up to four principal reasons, plus a fifth if one is inquiry-related. Adverse actions apply across the credit lifecycle: account opening denial, denied line-increase request, penalty-based APR increase, account closure, and more. ## Prerequisites This guide assumes you are familiar with: * [Need to Know — Environments](/v2/reference/need-to-know#environments) * [Need to Know — Authentication](/v2/reference/need-to-know#authentication) * Credit [applications](/v2/reference/patchapplication) and accounts ## The adverse action object | Field | Description | | ------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `id` | Unique identifier (read-only, assigned on creation). | | `purpose` | The lifecycle event the decision concerns (e.g. `ACCOUNT_OPENING`, `ACCOUNT_CLOSURE`). | | `reasons` | The principal reasons for the adverse action (e.g. `TOO_MANY_INQUIRIES`, `INSUFFICIENT_CREDIT_HISTORY`). | | `related_resource_id` | The `id` of the associated customer or account. | | `related_resource_type` | The type of associated resource: `CUSTOMER` or `ACCOUNT`. | | `notification_time` | When the customer was notified of the decision. | | `creation_time` / `last_updated_time` | Timestamps (read-only). | ```json theme={"system"} { "id": "2fb2858b-f859-4dc8-9ad2-2a4e596fed89", "purpose": "ACCOUNT_OPENING", "reasons": ["TOO_MANY_INQUIRIES", "INSUFFICIENT_CREDIT_HISTORY"], "related_resource_id": "9337a443-fa03-471c-ab05-b138c41dbd17", "related_resource_type": "CUSTOMER", "notification_time": "2020-05-19T21:14:27.434964Z", "creation_time": "2023-09-19T15:48:24.10184Z", "last_updated_time": "2023-09-19T15:48:24.10184Z" } ``` See the [API reference](/v2/reference/createadverseaction) for the full schema. ## Recording adverse actions ### Example: a denied Line of Credit application When an application to open a Line of Credit account is denied, record the notice with [POST /v2/adverse\_actions](/v2/reference/createadverseaction), scoped to the customer: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/adverse_actions \ --data-binary ' { "notification_time": "2020-05-19T21:14:27.434964Z", "purpose": "ACCOUNT_OPENING", "reasons": ["TOO_MANY_INQUIRIES", "INSUFFICIENT_CREDIT_HISTORY"], "related_resource_id": "9337a443-fa03-471c-ab05-b138c41dbd17", "related_resource_type": "CUSTOMER" }' ``` The response includes the system-generated `id`: ```json theme={"system"} { "id": "2fb2858b-f859-4dc8-9ad2-2a4e596fed89", "purpose": "ACCOUNT_OPENING", "reasons": ["TOO_MANY_INQUIRIES", "INSUFFICIENT_CREDIT_HISTORY"], "related_resource_id": "9337a443-fa03-471c-ab05-b138c41dbd17", "related_resource_type": "CUSTOMER", "notification_time": "2020-05-19T21:14:27.434964Z", "creation_time": "2023-09-19T15:48:24.10184Z", "last_updated_time": "2023-09-19T15:48:24.10184Z" } ``` Associate the adverse action with the applicant on the Line of Credit application using [PATCH /v2/applications/\{APPLICATION\_ID}](/v2/reference/patchapplication), and move the application to `CREDIT_DENIED`: ```shell theme={"system"} curl \ -X PATCH \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/applications/{APPLICATION_ID} \ --data-binary ' { "applicants": [ { "adverse_action_id": "2fb2858b-f859-4dc8-9ad2-2a4e596fed89", "customer_id": "4a666a01-d23a-47b1-8c20-2eb5a923da35", "is_primary": true } ], "status": "CREDIT_DENIED" }' ``` ```json theme={"system"} { "id": "ebda67f0-e0a7-41e2-98ed-0617a1e815a6", "account_type": "LINE_OF_CREDIT", "type": "CREDIT", "purpose": "ACCOUNT_OPENING", "status": "CREDIT_DENIED", "applicants": [ { "adverse_action_id": "2fb2858b-f859-4dc8-9ad2-2a4e596fed89", "customer_id": "4a666a01-d23a-47b1-8c20-2eb5a923da35", "is_primary": true } ], "creation_time": "2022-10-26T19:14:45.861687Z", "last_updated_time": "2023-09-20T00:31:10.255042Z" } ``` ### Example: an account closed for delinquency When a charge-secured account is closed due to delinquency, record the notice scoped to the account with `related_resource_type` set to `ACCOUNT`: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/adverse_actions \ --data-binary ' { "notification_time": "2020-05-19T21:14:27.434964Z", "purpose": "ACCOUNT_CLOSURE", "reasons": ["FRAUDULENT_ACTIVITIES"], "related_resource_id": "9337a443-fa03-471c-ab05-c538c41dbd17", "related_resource_type": "ACCOUNT" }' ``` ```json theme={"system"} { "id": "2fb2858b-f859-4dc8-9ad2-3b4e596fed89", "purpose": "ACCOUNT_CLOSURE", "reasons": ["FRAUDULENT_ACTIVITIES"], "related_resource_id": "9337a443-fa03-471c-ab05-c538c41dbd17", "related_resource_type": "ACCOUNT", "notification_time": "2020-05-19T21:14:27.434964Z", "creation_time": "2023-09-19T15:48:24.10184Z", "last_updated_time": "2023-09-19T15:48:24.10184Z" } ``` ## Best practices The notice of adverse action must generally be delivered within **30 days** of the credit decision. Record the adverse action and notify the customer promptly to stay within the regulatory window. * **Limit to principal reasons** — provide up to four principal reasons, adding a fifth only when one reason is inquiry-related. * **Always associate the notice** — link every adverse action to its application (`ACCOUNT_OPENING`) or account (`ACCOUNT_CLOSURE`, APR increase, etc.). * **Set an accurate `notification_time`** — it anchors the compliance timeline; record when the customer was actually notified. * **Cover the full lifecycle** — record adverse actions for line-increase denials and penalty APR increases, not just openings and closures. ## Related guides The customer an adverse action is scoped to. Link adverse actions to the applications they concern. The credit accounts adverse actions apply to. ## API reference * [Create an adverse action](/v2/reference/createadverseaction) * [List adverse actions](/v2/reference/listadverseactions) * [Get an adverse action](/v2/reference/getadverseaction) * [Update an application](/v2/reference/patchapplication) # Applications Source: https://docs.synctera.com/v2/docs/applications-guide The Application API is used to collect applicants' data. As FinTech processes the application, they update the content and status of the application. For different use cases, Synctera supports distinct types of applications. The current application types are: 1. Credit Applications: Used for credit products where the end-user is a consumer or a business. See details [here](/v2/docs/credit-applications-guide). 2. Restricted Account Application: Application to process special cases of Business accounts. # Balance Floor and Ceiling and Linked Accounts Source: https://docs.synctera.com/v2/docs/balance-floor-ceiling Accounts can have a minimum and maximum balance, referred to as the balance floor and balance ceiling. These attributes can be used to implement a number of features, including pool accounts. Balance Floor and Ceiling can be set while creating an account using [`POST /v0/accounts`](/v2/reference/createaccount) ## Balance Floor An account's balance floor consists of two attributes: * `balance`: the minimum balance the account can have * `linked_account_id`: the ID of the linked account used to maintain the minimum balance The balance floor creates a lower limit for the available balance of that account. Any transaction that would put the available balance of the account below its balance floor triggers a just-in-time (JIT) funding transaction from the linked account in order to bring the balance back up to the floor. ## Balance Ceiling The balance ceiling creates an upper limit for the available balance. Any transaction that would put the available balance of the account above its balance ceiling triggers a just-in-time (JIT) funding transaction (also known as a sweep transaction) to the linked account in order to bring the balance back down to the ceiling. ## Example Use Cases ### Pool Account There are a number of use cases where you want an account that always has a zero balance, and gets its funds from another account. For example, you many have a single pool account containing the funds for multiple business expense cards. In this case, each card's account would be set up like: ```json JSON theme={"system"} balance_floor: { "balance": 0, "linked_account_id": "{POOL_ACCOUNT_ID}" } balance_ceiling: { "balance": 0, "linked_account_id": "{POOL_ACCOUNT_ID}" } ``` All credits and debits to any of the card accounts would flow through to the pool account. Refer to the [Business Expense Cards](/v2/docs/business-card) for more details. # Bank Migration Guide Source: https://docs.synctera.com/v2/docs/bank-migration Use the Migration Mapping API to link old and new resources when migrating from one sponsor bank to another on the Synctera platform. When a FinTech migrates from one sponsor bank to another on the Synctera platform, resources such as customers, accounts, and external accounts must be recreated under the new bank's tenant. The **Migration Mapping API** provides a persistent record of the relationship between an old resource and its newly created counterpart, bridging the two tenants throughout the migration and afterward. Migration mappings do not move data or trigger any automated migration process. They serve two key purposes: * **Operational continuity** — FinTech operators, Synctera support teams, and bank partners can navigate between old and new records in the Synctera dashboard during and after a migration. * **Behind-the-scenes integrations** — Synctera uses mappings internally to coordinate activities that require knowledge of both the old and new resource, such as transferring a credit-reporting tradeline from the old bank to the new one without disrupting the customer's credit history. ## Prerequisites Before using the Migration Mapping API you should be familiar with: * [Create a Personal Customer](/v2/docs/create-a-personal-customer) * [Create a Business Customer](/v2/docs/create-a-business) * Accounts — creating deposit and other account types You will need: * An API key for your **existing** (old) tenant * An API key for your **new** tenant * The resource IDs of records you intend to migrate (customers, accounts, etc.) ## The migration mapping object A migration mapping represents the link between one specific resource on the old tenant and its newly created equivalent on the new tenant. ```json theme={"system"} { "id": "191edb33-3fca-4c68-8ca5-871fa0d5e3f5", "tenant": "456", "resource_id": "def45678-0000-0000-0000-000000000002", "old_tenant": "123", "old_resource_id": "abc12345-0000-0000-0000-000000000001", "resource_type": "PERSON", "creation_time": "2026-03-01T10:00:00Z", "last_updated_time": "2026-03-01T10:00:00Z" } ``` | Field | Description | | ------------------- | ---------------------------------------------------------------------------- | | `id` | Unique identifier for the migration mapping | | `tenant` | Tenant ID of the **new** bank | | `resource_id` | ID of the resource in the **new** tenant | | `old_tenant` | Tenant ID of the **old** bank | | `old_resource_id` | ID of the resource in the **old** tenant | | `resource_type` | The type of resource being mapped. One of `PERSON`, `BUSINESS`, or `ACCOUNT` | | `creation_time` | ISO 8601 timestamp when this mapping was created | | `last_updated_time` | ISO 8601 timestamp when this mapping was last updated | ### Cross-tenant access Migration mappings are stored under the new tenant (`tenant`) but are queryable using an API key from either the old or the new tenant. This allows operators to look up a mapping regardless of which API key they have at hand during the migration process. ### Permissions Querying and managing migration mappings uses the same permissions as the underlying resource type: | `resource_type` | Required permission | | --------------- | ---------------------------------- | | `PERSON` | `customer:read` / `customer:write` | | `BUSINESS` | `customer:read` / `customer:write` | | `ACCOUNT` | `account:read` / `account:write` | ## Example: Migrate customers and accounts to a new bank The following example walks through the complete workflow for migrating personal customers and their associated accounts from an old tenant to a new tenant. Start by retrieving the list of customers to be migrated from your existing tenant. In this example, the old tenant ID is `123` and the new tenant ID is `456`. ```shell theme={"system"} curl -X GET https://api.synctera.com/v2/persons \ -H "Authorization: Bearer $old_apikey" ``` The response returns a paginated list of person objects. Record the `id` of each person you intend to migrate. ```json theme={"system"} { "persons": [ { "id": "abc12345-0000-0000-0000-000000000001", "first_name": "Jane", "last_name": "Smith", "email": "jane.smith@example.com" } ], "next_page_token": "..." } ``` For each customer, retrieve their accounts so you have the full picture of what needs to be recreated. ```shell theme={"system"} curl -X GET "https://api.synctera.com/v2/accounts?customer_id=abc12345-0000-0000-0000-000000000001" \ -H "Authorization: Bearer $old_apikey" ``` Record the `id` of each account alongside its owner's person ID. Using the information collected above, create each customer on the new tenant. Submit the same personal information as was on record under the old tenant. ```shell theme={"system"} curl -X POST https://api.synctera.com/v2/persons \ -H "Authorization: Bearer $new_apikey" \ -H "Content-Type: application/json" \ --data-binary '{ "first_name": "Jane", "last_name": "Smith", "dob": "1985-06-15", "email": "jane.smith@example.com", "phone_number": "+14155551234", "legal_address": { "street_line_1": "123 Main St", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country_code": "US" } }' ``` The response includes the new `id` for the person on the new tenant. Record this value — you will need it when creating the migration mapping. ```json theme={"system"} { "id": "def45678-0000-0000-0000-000000000002", "first_name": "Jane", "last_name": "Smith" } ``` Repeat this step for each customer in your migration list, keeping a record of the mapping from old IDs to new IDs. With the new customer IDs in hand, create corresponding accounts on the new tenant. Use the same account configuration (product type, etc.) as the original. ```shell theme={"system"} curl -X POST https://api.synctera.com/v2/accounts \ -H "Authorization: Bearer $new_apikey" \ -H "Content-Type: application/json" \ --data-binary '{ "account_type": "CHECKING", "customer_ids": ["def45678-0000-0000-0000-000000000002"] }' ``` Record the new account `id` returned in the response alongside the old account `id`. Now that each customer exists on both tenants, create a migration mapping for each person. This call can be made with either the old or the new API key. ```shell theme={"system"} curl -X POST https://api.synctera.com/v2/migration_mappings \ -H "Authorization: Bearer $new_apikey" \ -H "Content-Type: application/json" \ --data-binary '{ "tenant": "456", "resource_id": "def45678-0000-0000-0000-000000000002", "old_tenant": "123", "old_resource_id": "abc12345-0000-0000-0000-000000000001", "resource_type": "PERSON" }' ``` A successful response returns the complete migration mapping object: ```json theme={"system"} { "id": "191edb33-3fca-4c68-8ca5-871fa0d5e3f5", "tenant": "456", "resource_id": "def45678-0000-0000-0000-000000000002", "old_tenant": "123", "old_resource_id": "abc12345-0000-0000-0000-000000000001", "resource_type": "PERSON", "creation_time": "2026-03-01T10:00:00Z", "last_updated_time": "2026-03-01T10:00:00Z" } ``` Repeat this step for each migrated customer. Create a corresponding mapping for each account, linking the old account ID to the new account ID. ```shell theme={"system"} curl -X POST https://api.synctera.com/v2/migration_mappings \ -H "Authorization: Bearer $new_apikey" \ -H "Content-Type: application/json" \ --data-binary '{ "tenant": "456", "resource_id": "acct9999-0000-0000-0000-000000000004", "old_tenant": "123", "old_resource_id": "acct1111-0000-0000-0000-000000000003", "resource_type": "ACCOUNT" }' ``` You have now recreated your customers and accounts on the new tenant and established a persistent record linking each pair of old and new resources. Synctera will use these mappings to automatically coordinate any downstream processes that require knowledge of both records, such as transferring credit-reporting tradelines. ## Querying migration mappings You can look up migration mappings at any time using any combination of the following filters. ### Look up by resource ID The `resource_id` filter matches against **both** `resource_id` and `old_resource_id`. Use it whenever you have an ID and don't need to constrain which side of the mapping it belongs to — this is the most common lookup pattern. ```shell theme={"system"} curl -X GET "https://api.synctera.com/v2/migration_mappings?resource_type=PERSON&resource_id=def45678-0000-0000-0000-000000000002" \ -H "Authorization: Bearer $new_apikey" ``` ### Look up strictly by the old resource ID If you specifically want to match only on the old side of the mapping (for example, to find every record that originated from a particular old resource), use `old_resource_id`. ```shell theme={"system"} curl -X GET "https://api.synctera.com/v2/migration_mappings?resource_type=PERSON&old_resource_id=abc12345-0000-0000-0000-000000000001" \ -H "Authorization: Bearer $old_apikey" ``` ## Updating and deleting mappings ### Update a mapping Use `PATCH` to update mutable fields on an existing mapping (for example, if a resource ID was recorded incorrectly). ```shell theme={"system"} curl -X PATCH https://api.synctera.com/v2/migration_mappings/191edb33-3fca-4c68-8ca5-871fa0d5e3f5 \ -H "Authorization: Bearer $new_apikey" \ -H "Content-Type: application/json" \ --data-binary '{ "resource_id": "def99999-0000-0000-0000-000000000002" }' ``` ### Delete a mapping ```shell theme={"system"} curl -X DELETE https://api.synctera.com/v2/migration_mappings/191edb33-3fca-4c68-8ca5-871fa0d5e3f5 \ -H "Authorization: Bearer $new_apikey" ``` Deleting a migration mapping removes the link between the old and new resource. Synctera will no longer be able to automatically coordinate downstream processes (such as credit-reporting tradeline transfers) for the affected resource. Only delete a mapping if you are certain the association is no longer needed. ## Webhooks Synctera publishes webhook events for migration mapping lifecycle changes. Subscribe to these events to trigger your own automation during a migration. | Event | Description | | -------------------------- | ----------------------------------- | | `RESOURCE_MAPPING.CREATED` | A new migration mapping was created | | `RESOURCE_MAPPING.UPDATED` | An existing mapping was updated | | `RESOURCE_MAPPING.DELETED` | A mapping was deleted | See the [Webhooks guide](/v2/docs/webhooks-guide) for instructions on configuring webhook subscriptions. ## Related guides Recreate personal customers on the new tenant. Recreate business customers on the new tenant. Recreate accounts before mapping old and new IDs. Subscribe to migration mapping lifecycle events. ## API reference See the full Migration Mappings API reference for request/response schemas and all available parameters: * [List migration mappings](/v2/reference/listmigrationmappings) * [Create a migration mapping](/v2/reference/createmigrationmapping) * [Get a migration mapping](/v2/reference/getmigrationmapping) * [Update a migration mapping](/v2/reference/updatemigrationmapping) * [Delete a migration mapping](/v2/reference/deletemigrationmapping) ## Navigating migrated resources in the dashboard Once migration mappings exist, the Synctera dashboard surfaces links between old and new records. On any customer or account detail page, an action menu item — **View Migrated Resource** — will appear when a mapping exists. Selecting it navigates directly to the corresponding record on the other tenant, making it easy for FinTech operators, bank partners, and Synctera support to trace a resource through the migration. ## What happens after mappings are created After you create migration mappings for your customers and accounts, Synctera uses the mappings to handle certain processes automatically on your behalf. You do not need to take additional action for these: * **Credit-reporting tradeline transfer** — For FinTechs that report to credit bureaus, Synctera will record a sale of the tradeline on the old bank and a corresponding purchase on the new bank, ensuring your customers' credit histories remain uninterrupted. Other post-migration steps — such as re-running KYC, issuing new cards, and migrating balances — must be completed by your team as part of your broader migration runbook. Work with your Synctera implementation manager for a full migration checklist. # Bulk Card Orders Source: https://docs.synctera.com/v2/docs/bulk-card-orders The Synctera platform supports the issuance of cards in bulk and can be configured for automatic daily fulfillment or fulfillment at your request. ### In order to create bulk orders your card product needs to be configured for bulk issuance. ## Bulk Order Creation Steps ### 1. Create a Bulk Order Configuration A bulk order configuration provides the shipping instructions for individual bulk orders. Once a bulk order configuration has been set up in the Synctera system, cards can be issued in bulk and will be shipped to the destination specified in the configuration. Fulfillment of the bulk order configuration is based on the bulk issuance policy specified in the configuration. #### Bulk Issuance Policy | Bulk Issuance Policy | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | AUTO | Bulk orders configured with an AUTO fulfillment policy will be fulfilled nightly at 9:30pm PST (UTC -8:00). All cards that have been issued with the corresponding bulk order config id prior to the cut-off time will be included in the daily bulk order. | | MANUAL | Bulk orders configured with a MANUAL fulfillment policy will be fulfilled at the request of the integrator. All cards that have been issued with the corresponding bulk order config id prior to the requested fulfillment will be included in the bulk order. | Call [POST /v1/cards/bulk\_issuance](/v2/reference/createbulkorderconfig) to create a bulk order config. ```sh Shell theme={"system"} -X POST \ $baseurl/v1/cards/bulk_issuance \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ --data-binary ' { "name": "Sample Bulk Order Config", "card_product_id": {CARD_PRODUCT_ID}, "bulk_issuance_policy": "AUTO", "shipping": { "recipient_name": { "first_name": "Jane", "last_name": "Smith" }, "address": { "address_line_1": "123 Main St", "city": "Seattle", "state": "WA", "postal_code": "98109", "country_code": "US" }, "method": "INTERNATIONAL" } }' ``` This will return a response with the created bulk order configuration: ```json JSON theme={"system"} { "id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "creation_time": "2010-05-06T12:23:34.321Z", "name": "Sample Bulk Order Config", "card_product_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "shipping": { "recipient_name": { "first_name": "Jane", "last_name": "Smith" }, "address": { "address_line_1": "123 Main St", "city": "Seattle", "state": "WA", "postal_code": "98109", "country_code": "US" }, "is_expedited_fulfillment": false, "method": "INTERNATIONAL", }, "bulk_issuance_policy": "AUTO", "tenant": "abcdef_ghijkl" } ``` Note the returned `id` attribute. This is used in future card issuance requests in order to include the card as part of a bulk shipment and in order to fulfill bulk orders configured for `MANUAL` fulfillment. ### 2. Issue Cards Cards are dynamically added to a bulk order by providing the bulk order configuration `id` in the card issuance request. Call [POST /v1/cards](/v2/reference/issuecard) to issue a card. ### 3. Fulfill Bulk Order ### bulk order configurations with an auto policy are automatically fulfilled nightly at 9:30pm PST (UTC -8:00) #### Manual Order Fulfillment Call [POST /v1/cards/bulk\_issuance](/v2/reference/fulfillbulkorder) to fulfill the bulk order. ```sh Shell theme={"system"} -X POST \ $baseurl/v1/cards/bulk_issuance/{$bulk_order_config_id}/fulfill \ -H "Authorization: Bearer $apikey" ``` This will return a `202 Accepted` response. All cards issued with the corresponding bulk order config id since the last fulfillment request will be included in the bulk order. #### Card Fulfillment Once a card has been shipped a webhook will be triggered with the updated shipping details. Including a tracking number if available. To subscribe to the `CARD.UPDATED` webhook refer to the [Webhooks Guide](/v2/docs/webhooks-guide). # Business Expense Cards Source: https://docs.synctera.com/v2/docs/business-card This guide will show how to set up business expense cards in Synctera's platform. In this guide we will create a business expense account which will fund card purchases made by the business's employees, subject to spending controls. The purpose of this guide is to give an overview of how the various entities in Synctera's platform work together to be able to handle this type of use case. ## Prerequisites Before continuing in this guide you will also need a card product set up using a commercial BIN. We will refer to its UUID as `{{card_product_id}}`. Please also have a business created and fully verified such that is has a `verification_status` of `"ACCEPTED"`. We will refer to the UUID of this business as `{{business_id}}`. You will also need one or more persons in the system that have been verified and passed KYC. This means they must have a `kyc_status` of `"ACCEPTED"`. We will refer to their UUIDs as `{{employee1_id}}`, `{{employee2_id}}`, etc. Refer to the [KYC Verification API Overview](/v2/reference/verify) for the process to get your customers verified. ## Business expense account Create an account template by performing a [POST /v0/accounts/templates](/v2/reference/createaccounttemplate) with the following request body. ```json JSON theme={"system"} { "name": "business expense accounts", "is_enabled": true, "template": { "account_type": "CHECKING", "bank_country": "US", "currency": "USD", "is_ach_enabled": false, "is_card_enabled": false, "is_p2p_enabled": true } } ``` Note that cards are not enabled for accounts created using this template but the accounts can be funded via P2P transactions (money movement within Synctera's platform). The request should return a new account template. We will refer to this template's UUID as `{{business_account_template_id}}`. Using this new template, create a new account by performing a [POST /v0/accounts](/v2/reference/createaccount) with the following request body. ```json JSON theme={"system"} { "account_template_id": "{{business_account_template_id}}", "relationships": [ { "relationship_type": "ACCOUNT_HOLDER", "business_id": "{{business_id}}" } ] } ``` We will refer to this new account's UUID as `{{business_account_id}}`. Because we disabled cards in the account template, we can not issue cards for this account directly. The cards will be issued against the employee expense accounts which will in turn be connected to this account. ## Spend control Create a spend control rule by performing a [POST /v0/spend\_controls](/v2/reference/createspendcontrol) with the following request body. For more details, see the [spend controls guide](/v2/docs/spend-controls-guide). ```json JSON theme={"system"} { "name": "Employee monthly limit", "amount_limit": 100000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 30 }, "action_decline": true, "action_case": false, "is_active": true } ``` The request should return a new spend control rule. We will refer to this rule's UUID as `{{spend_control_id}}`. ## Employee expense accounts Create another account template by performing a [POST /v0/accounts/templates](/v2/reference/createaccounttemplate) with the following request body. ```json JSON theme={"system"} { "is_enabled": true, "name": "employee spending accounts", "template": { "account_type": "CHECKING", "bank_country": "US", "currency": "USD", "balance_floor": { "balance": 0, "linked_account_id": "{{business_account_id}}" }, "balance_ceiling": { "balance": 0, "linked_account_id": "{{business_account_id}}" }, "is_ach_enabled": false, "is_card_enabled": true, "is_p2p_enabled": false, "spend_control_ids": [ "{{spend_control_id}}" ] } } ``` This request references the spend control. This request also includes balance floor and balance ceiling objects. The balance floor is zero and the `overdraft_account_id` refers to the business account we created earlier. This means that for any account created using this template, the business account will provide real-time funding in order to keep the account's balance at or above zero. Similarly, the balance ceiling is also zero and the `overflow_account_id` also refers to the business account we created earlier. This means that for any account using this template, the business account will receive funds flowing in to the account in order to keep the account's balance at or below zero. In other words, accounts created using this template never hold a balance and card transactions on these accounts effectively move money to and from the business account. The accounts are still limited by their individual spending limits of \$1000 per month. For more information, see the guide [Balance Floor and Ceiling and Linked Accounts](/v2/docs/balance-floor-ceiling). Note that the only payment rail enabled for this account template is cards. The request should return a new account template. We will refer to this template's UUID as `{{employee_account_template_id}}`. With this template we can now create accounts for all the business's employees by performing a [POST /v0/accounts](/v2/reference/createaccount) with the following request body. ```json JSON theme={"system"} { "account_template_id": "{{employee_account_template_id}}", "relationships": [ { "relationship_type": "ACCOUNT_HOLDER", "customer_id": "{{employee1_id}}" } ] } ``` This will create a new account. We will refer to the new account's ID as `{{employee1_account_id}}`. Repeat this request using `{{employee2_id}}` to create `{{employee2_account_id}}`, then using `{{employee3_id}}` to create `{{employee3_account_id}}`, etc. ## Employee cards Create a card for each employee by performing a [POST /v0/cards](/v2/reference/issuecard) with the following request body. This assumes your card product is for physical cards. For virtual cards replace `"PHYSICAL"` with `"VIRTUAL"`. ```json JSON theme={"system"} { "form": "PHYSICAL", "account_id": "{{employee1_account_id}}", "card_product_id": "{{card_product_id}}", "customer_id": "{{employee1_id}}", "type": "DEBIT" } ``` Then repeat this request to create cards for the other employees and their accounts. ## Transactions Experiment with the employee cards by doing some simulated card transactions. Card transaction authorizations will automatically create "JIT funding" transactions between the business account and the respective employee accounts. For example, a $10 authorization for employee 1's card will decrease the balance of the business account by $10 and increase the ledger balance of employee 1's account by $10. This $10 will be placed on hold so the available balance of employee 1's account remains zero. If this authorization is reversed the \$10 automatically moves back into the business account. Card transactions will appear in the employee account transaction histories. There will be corresponding "JIT funding" transactions that appear in the employee accounts and the business accounts. The monthly limit applies to each employee independently. Any attempt to authorize a transaction over the limit will be declined. # Card Issuer 3DS Source: https://docs.synctera.com/v2/docs/card-3ds "Three Domain Secure" (3DS) is a protocol designed to be an additional security layer for credit and debit card transactions when there is no physical card present, such as in online purchases. ## Overview When a merchant initiates the 3DS process the Synctera platform responds according to your configuration. You may specify the desired 3DS behaviour at the card product level or on a per-request basis. ### Card Product Each product can be configured with a `three_ds_policy`. This field has two possible values: `SMS_OTP` and `EXEMPT`. If no value is specified, the default is `SMS_OTP`. If you choose `SMS_OTP` then for each 3DS process involving the card product the cardholder will receive an SMS message with a one-time code which they must then supply to the merchant to verify their identity. The SMS will be sent to the customer's phone number that is stored in the platform. If you choose `EXEMPT` then each 3DS process involving the card product will succeed with no further steps. You may override the card product's 3DS policy by implementing a decision gateway. ### Decision Gateway 3DS decision gateways allow you to make real-time decision about each 3DS request. 3DS gateways are independent entities in the Synctera platform which can be associated with any number of card products. These associations are defined by the `three_ds_decision_gateways` endpoints, not the card product endpoints. #### Creation Create a 3DS decision gateway by calling `POST /v1/cards/three_ds_decision_gateways` with a body like this: ```json JSON theme={"system"} { "is_active": true, "decision_url": "https://your.server/3ds_decision", "card_products": [ "2957a146-ce3b-4d04-8328-ab3ea6e76cac" ], "fallback_decision": "EXEMPT", "custom_headers": { "X-Custom-Data": "arbitrary value" } } ``` Every time the Synctera platform makes a 3DS decision for a card from the card products you specify, it will now attempt to send a `POST` request to your `decision_url`. The request will include all the `custom_headers` key-value pairs you specify as HTTP headers in the request. Custom headers are optional to use as you see fit. For the purpose of authenticating requests, rather than using custom headers, you can [create a signature secret for request validation](/v2/docs/webhooks-guide#integration-steps) and then check the `Synctera-Signature` HTTP header of each request to your gateway. The `fallback_decision` will be used if something goes wrong and the Synctera platform can't get a response from your decision endpoint or the request times out. The values for `fallback_decision` are the same as the `three_ds_policy` options for a card product (`SMS_OTP` and `EXEMPT`) and have the same meaning. If an active decision gateway is configured for a card product, then the API responses for that card product will indicate that the `three_ds_policy` is `DECISION_GATEWAY`. This means that the decision gateway overrides the `three_ds_policy` of the card product and if the Synctera platform can't get a response from the decision gateway it will use the gateway's `fallback_decision` rather than the card product's `three_ds_policy`. #### 3DS Decision Request The body of the request to your 3DS decision server will look like this: ```json JSON theme={"system"} { "card_id": "f8c84f73-91a5-4dfe-9c12-a35bfa1df716", "card_product_id": "2957a146-ce3b-4d04-8328-ab3ea6e76cac", "acs_transaction_id": "a0c165f9-23ae-408c-b8c3-a7c486750b1e", "authentication_request_type": "PAYMENT", "client_ip_address": "10.1.2.3", "device_channel": "BROWSER", "transaction_amount": 6187, "currency_code": "USD", "transaction_type": "PAYMENT", "transaction_sub_type": "PURCHASE", "merchant": { "name": "Best Buy", "country_code": "840", "id": "345954985882", "category_code": "5732" } } ``` The `transaction_amount` is in minor units of the currency (in this case, cents). The currency is specified in the `currency_code` field as a 3 character alphabetical code. `authentication_request_type` is one of `PAYMENT`, `RECURRING`, `INSTALLMENT`, `ADD_CARD`, `MAINTAIN_CARD` or `EMV_CARDHOLDER_VERIFICATION`. `device_channel` is one of `BROWSER`, `APP_BASED` or `THREEDS_REQUESTER_INITIATED`. `transaction_type` is either `PAYMENT` or `NON_PAYMENT`. `transaction_sub_type` is one of `PURCHASE`, `ACCOUNT_VERIFICATION`, `ACCOUNT_FUNDING`, `QUASI_CASH` or `PREPAID_ACTIVATION_AND_LOAD`. The `merchant.country_code` is specified as the ISO 3166-1 three-digit numeric country code. #### 3DS Decision Response To indicate your 3DS decision, your 3DS decision server responds with HTTP status OK (200) and writes a single field the response body. For example: ```json JSON theme={"system"} { "decision": "EXEMPT" } ``` The allowed values for your `decision` are `SMS_OTP` and `EXEMPT`. These values have the same meaning as described above for the `three_ds_policy` of a card product. If the Synctera platform sees a response status code other than 200 or can't decode the response body then it will use the gateway's `fallback_decision`. # Card Activation Widget (Deprecated) Source: https://docs.synctera.com/v2/docs/card-activation-widget-legacy Using this widget you can add card activation to your website. It requires a Synctera widget vault token to initialize it with. The user will have 5 minutes to complete the activation submission. This widget is deprecated. For new integrations, use the [Activate Card Widget](/v2/docs/card-widgets-activate). The Card Activation Widget injects a configurable set of iframes into your app, allowing your user to securely enter a PAN & CVV in a PCI compliant manner. This helps remove some (but not all) of the PCI compliance requirements you would otherwise need to handle. The iframes injected by Synctera allow you complete control over the styling over the widget using only CSS. ## Quick start 1. Add `` to your page. 2. Embed the Card Activation widgets when and as needed (both the card-pan and card-cvv widgets are needed): ```html HTML theme={"system"} ``` 3. Add your own submit button under the Card Activation widgets. 4. Listen for the `validity` event on the Controller Card Activation widget (the one with the id): ```typescript TypeScript theme={"system"} const activationWidget = document.getElementById('synctera-activate); activationWidget.onValidity = (e, isValid) => button.disabled = !isValid; ``` 5. Have the button call `activationWidget.submit()` to activate the card.It returns a promise, which resolves if the activation submission was successful, or rejects if it failed. ### *Basic Example*: ```html HTML theme={"system"}
PAN
CVV
```
**Styling: If you add a custom class name to the Card Activation widget, custom styling will be activated (see [Custom Styling](#custom-styling)).** By default, the widgets use the browser's inbuilt styling for the Card PAN and Card CVV input text fields (note that without custom styling the widget iframe is 4px bigger than the input field inside to allow for any browser outline effects). *See [Custom Styling Example](#custom-styling-example) for a complete working example.* ## Environments * Sandbox: [https://widgets-sandbox.synctera.com/assets/activate/activate\_v1.0.1.js](https://widgets-sandbox.synctera.com/assets/activate/activate_v1.0.1.js) * Production: [https://widgets.synctera.com/assets/activate/activate\_v1.0.1.js](https://widgets.synctera.com/assets/activate/activate_v1.0.1.js) ## Browser support The widgets work on both mobile and desktop, and we ensure support for all modern browsers. It also works in many older browsers, which we try to support where feasible. | **Browser** | **Minimum tested version** | | ----------- | -------------------------- | | Chrome | 29 (2013) | | Firefox | 27 (2014) | | Edge | 79 (2020), 15 (2017) | | Safari | 12 (2018) | | Opera | 20 (2014) | | IE | 11 (2013) | ## Card Activation flow > **Summary** > > Fetch widget token from backend → Render widgets with token → Listen for "validity" event → User submits *controller* widget → Widget submits PAN & CVV to Synctera → And returns success or failure → Widget auto-destroys **Note: It is recommended to also add 'load' and 'error' [listeners](#events) for UI management (see [Widget API](#widget-api) below).** The flow for using the widgets: 1. On your backend, request a widget token from Synctera for the particular card you wish to use. 2. Make sure the Synctera Activation widget Javascript has been added to your website. 3. Render the two specialized Card PAN and Card CVV HTML tags as above, setting the token attribute, and your own button to submit the widget. 4. You can style these fields however you like (as explained below in [Custom Styling](#custom-styling)). 5. Listen for the "validity" event from the *controller* widget. 6. When valid, enable your button. 7. When the button is clicked, call the `submit()` function on the *controller* widget. 8. The submit function will activate the card. 9. It also returns a promise which resolves when successful, or rejects when there's a failure. 10. Once submitted, the widgets will auto-destroy and you can now remove them. ## Widget API ### Element Attributes: | **Name** | **Value** | **Default** | **Details** | **Example** | | --------- | ------------------- | ----------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- | | **token** | widget token ID | - | Required | `` | | **class** | class name (string) | Omitted | Optional*If present, it will activate custom styling* | ``\\` | ### Events: | **Name** | **Called when...** | **Why?** | ***addEventListener*** | ***on*** | | ------------ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | | **load** | The widgets have are fully loaded | For best user experience, show the widgets only when this event is triggered | `cardPanEl.addEventListener('load', () => ...);` | `cardPanEl.onLoad = () => ...` | | **validity** | The widgets are now (in)valid | Only allow `submit()` to be called when valid*To get the status, check the "isValid" property* | `cardPanEl.addEventListener('validity', () => {``␠ buttonEl.disabled = !cardPanEl.isValid;``});` | `cardPanEl.onValidity = (e, isValid) => {``␠ buttonEl.disabled = !isValid;``};` | | **error** | The widgets failed to load | Non-recoverable error states*To get the error, check the "error" property* | `cardPanEl.addEventListener('error', () => {``␠ console.log(cardPanEl.error);``});` | `cardPanEl.onError = () => {``␠ console.log(cardPanEl.error);``};` | | **success** | The widget submitted successfully | Know when the widget is done and the card was activated*Alternatively: The "submit()" method returns a promise resolving when done* | `cardPanEl.addEventListener('success', () => ...);` | `cardPanEl.onSuccess = () => ...` | | **failure** | The widget submitted unsuccessfully | Know if the card was not activated and the user will need to try again*Alternatively: The "submit()" method returns a promise rejecting on failure\*\*To get the failure, check the "error" property* | `cardPanEl.addEventListener('failure', () => {``␠ console.log(cardPanEl.error);``});` | `cardPanEl.onFailure = (e, errorDetails) => ...` | ### Fields: | **Name** | **Value / Parameters** | **Default / Returns** | **Details** | **Example** | | ------------ | ------------------------------ | --------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | | **isValid** | truefalse | false | true if both fields are valid and form is ready to submit | `cardPanEl.isValid` | | **error** | \{ errorType:'...', error: \*} | undefined | Error details if an error or failure occurs | `cardPanEl.error` | | **submit()** | *No parameters* | *Returns:* Promise | Submits the PAN & CVV to Synctera's servers*Alternatively:* The widget fires "success" and "failure" events | `cardPanEl.submit()``␠ .then(// success)``␠ .catch(// error)` | ## Custom styling > **Summary** > > * Add a class name to `card-pan` or `card-cvv` tags to activate Custom Styling: ` * Style as desired (i.e. border), but [Font Styles](#font-styles) are special > * For pseudo-selectors, e.g. `:hover`, `:focus`, etc - use pseudo-attributes instead: *Example:* `.customStyles[_hover] { border: 1px solid #616161; }` > * Font styles are *auto-forwarded*, but only certain values are allowed (see below) > * Optional: You can use `.customStyles[_required]` to show the widgets once they have loaded By default, without custom styling, the widgets use the browser's inbuilt styling for the PAN and CVV input text fields (note that the widget iframe is 4px bigger than the input field inside to allow for any browser outline effects). You may want to style the widget to match your webapp design or to add things like placeholders. This can be done entirely through css styling. When a `class` attribute is added to the widget, the 4px spacing is removed, the input box styling is stripped and the background is made transparent such that any elements placed behind the widget will be visible (i.e. a placeholder element). The text input is set to always take up 100% of the height and width of the iframe, and likewise for the iframe in the widget tag. Input text field pseudo selectors such as `:hover`, `:focus` and `:blank` are indirectly supported through css-like attributes instead of actual pseudo selectors. As the user hovers, focuses and types in the field, attributes will be added/removed on the `card-pan` and `card-cvv` tags automatically. Supported "pseudo attributes" are inspired from: [https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#input\_pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#input_pseudo-classes) *Where `customStyles` is the class name added to widget tags, e.g. ` ```html html theme={"system"}
PAN
CVV
``` ## Font Styles You can style the or tag as you see fit (border, background, etc). Css font properties are handled in a special way to forward them to the iframe for styling the input, in a secure and sanitized manner. As such only certain css font properties are supported and only with certain values (all other values may be ignored, if they work they are not guaranteed across all browsers): | **Font css property name** | **Allowed values** | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | color | `rgb(, , )` or `rgba(, , , )` | | font-family | **One of:** courier: `Courier New, Courier, Lucida Console, Lucida Sans Typewriter, monospace` arial: `Arial, Helvetica, sans-serif` georgia: `Georgia, Times New Roman, Times, serif` helvetica: `Helvetica, Arial, sans-serif` lucida: `Lucida Console, Lucida Sans Typewriter, Courier New, Courier, monospace` times: `Times New Roman, Times, Georgia, serif` tahoma: `Tahoma, Verdana, sans-serif` verdana: `Verdana, Tahoma, sans-serif` | | font-size | `px` | | font-weight | `00` (a number, not 'bold' etc) | | line-height | `px` | | letter-spacing | `px` | Note that with the `font-family` property, we look for a keyword in the first font in the comma separated list of fonts you supply. If there's a match, we use the font-family strings in the above table and not the font-family specified (for security). The above list of fonts are designed to ensure maximum coverage across different operating systems for similar style fonts. Custom fonts are not supported at this time. ## Additional Resources For examples showing the Card Activation & Set PIN widget implementation please see the following: # Card Transaction Disputes Source: https://docs.synctera.com/v2/docs/card-transaction-disputes Manage card disputes with the Synctera API: submit disputes, upload supporting documentation, and track status through the card network. ## Version 2 Rollout This is the **Version 2 (V2)** Card Transaction Disputes guide. For the Version 1 flow, see [Card Transaction Disputes (V1)](/v1/docs/card-transaction-disputes). The planned rollout for Version 2 of Synctera's Dispute Management is as follows: * **Mastercard programs:** September 7 – October 7, 2026 * Synctera will notify you of the exact date. Until then, follow the [V1](/v1/docs/card-transaction-disputes) flow. * **Visa and PULSE programs:** TBD * Keep following the [V1](/v1/docs/card-transaction-disputes) flow until further notice. **Key changes between V1 and V2:** * Reason codes have been streamlined (deprecated codes remain accepted for backward compatibility) * Comprehensive evidence gathering at dispute creation to strengthen the case — see [`evidence`](/v2/reference/createdispute#body-one-of-0-evidence) in the Create Dispute spec. * New lifecycle states, including more granular declined-dispute states: Withdrawn, Refunded, Expired, Rejected * Dispute document categories — some reason codes require specific categories on submission ## Overview In order to manage the card dispute process, the Synctera API provides support for the required tasks such as submitting a dispute, uploading supporting documentation, and tracking status through the card network. Synctera evaluates evidence and interacts with the card network on your behalf. As mentioned under [Transaction Disputes](/v2/docs/transaction-disputes), a [Dispute Case](/v2/docs/dispute-cases-fintechs) gets automatically created once a dispute is opened. The Dispute Case is used to track and reflect the dispute status through the Synctera Console. ## What Transactions Can Be Disputed? * Only posted transactions can be disputed, and only if within 120 days from the settlement. A pending transaction cannot be disputed. * A dispute cannot exceed the amount of the original transaction. * For fraud disputes (`reason_code` = `UNAUTHORIZED_TRANSACTION`), the card must be terminated before the dispute can be created. ## Chargeback Dispute Lifecycle The chargeback dispute lifecycle involves a series of **actions** between the issuer and acquirer, which continues until a decision is reached on who is financially responsible for the dispute. The dispute lifecycle is also described in [this article](/v2/docs/dispute-cases-fintechs). Card disputes start in `EVIDENCE_GATHERING`. After evidence is submitted via `EVIDENCE_GATHERING.COMPLETE`, Synctera evaluates the case and files with the card network when appropriate. Subsequent lifecycle updates (chargeback, representment, outcomes, and similar) are applied automatically and surfaced via `DISPUTE.UPDATED` webhooks and GET responses. #### 1. Chargeback > Time frame within 120 days of settlement of the transaction. A chargeback is filed when the transaction meets the conditions listed in the [reason codes](/v2/docs/card-transaction-disputes#reason-code) found below. This happens after `EVIDENCE_GATHERING.COMPLETE`, when Synctera determines a chargeback should be filed. #### 2. Representment > Time frame within 45 days of chargeback. A representment occurs when the acquiring bank either has evidence to prove that the chargeback does not meet the requirements of the reason code or can provide information that addresses the original reason for the dispute. #### 3. Pre-arbitration > Time frame within 45 days of representment. Pre-arbitration is the final chance for the issuing bank to provide further evidence that the cardholder should be refunded for their transaction. #### 4. Arbitration > Time frame within 75 days of pre-arbitration. In the event that the issuer and acquirer cannot settle on an outcome of the financial responsibility of the transaction, the dispute can be raised to arbitration. Arbitration leaves the decision of who is financially responsible in the hands of third party arbitrators (the card network). Issuers and acquirers generally choose to avoid arbitration as it involves fees as high as \$500 or more per case in addition to any other fees associated with the dispute. ## Write-Offs In cases where a transaction's value is lower than the cost of pursuing a dispute, it can be written off instead of filing with the card network. A write-off is submitted (`WRITE_OFF.SUBMITTED`) automatically or by an issuer, then accepted automatically (`WRITE_OFF.ACCEPTED`). Any provisional credit is reversed, a final credit is posted, and the dispute is closed. ### Automatic Write-Offs Synctera can configure an automatic write-off threshold for your program. When a dispute is created and both of the following are true, Synctera routes it through the automatic write-off workflow instead of filing with the network: * The disputed amount is less than or equal to the configured threshold * The dispute is created no more than 120 days after the disputed transaction's effective date Those disputes are created with `managed_by` = `AUTO_WRITE_OFF` and `network` = `NONE`. Synctera later submits a `WRITE_OFF` action automatically, moving the dispute to the `WRITE_OFF` lifecycle. No issuer network actions are available on automatic write-off disputes. Automatic write-off is enabled by default with a **\$25** threshold. Contact your Synctera representative to disable it or change the threshold for your program. ## Reason Code When creating a dispute, the **Reason Code** is the most critical field in your request. It acts as the formal classification for the claim, signaling to the network exactly why the transaction is being challenged. Selecting the correct code ensures the case is evaluated under the proper network rules and significantly improves the chances of a successful resolution. #### Selecting a Reason Code To ensure your dispute meets all technical requirements, please refer to the supported codes in our documentation. **View the Codes:** Click the link below and ensure the **Card Dispute** tab is selected in the **Body** parameters section to see the full list of codes and required documentation. * [View Available Reason Codes](/v2/reference/createdispute) Some reason codes also require additional `evidence` on create, or a dispute document uploaded with a specific `category` before the case can be filed — see [Upload Supporting Documents](/v2/docs/transaction-disputes#2-upload-supporting-documents). Please ensure you are using **Active** codes. While some legacy codes are still accepted for backward compatibility, they are deprecated and will be automatically mapped to their modern equivalents by the API. Using the active code from the start ensures better tracking and transparency for your case. ## Card Dispute Lifecycle States | Lifecycle | Description | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | EVIDENCE\_GATHERING | Initial state after a dispute is created. Supporting documents and evidence can be added before the case is filed with the network. | | EVALUATION | Evidence gathering is complete and the case has been submitted for evaluation / network filing. | | MANUAL\_REVIEW | The case requires manual review before proceeding. | | WRITE\_OFF | The dispute has been written off and will not be filed with the card network. | | CHARGEBACK | A chargeback has been filed with the card network. The acquiring bank may accept or file a re-presentment. | | REPRESENTMENT | The acquiring bank has filed a re-presentment. The case may proceed to pre-arbitration or resolve as won/lost. | | PRE\_ARBITRATION | A pre-arbitration case has been created with the network. The acquiring bank may rebut or the case may resolve. | | PRE\_ARBITRATION\_RESPONSE | The acquiring bank has rebutted the pre-arbitration case. The case may escalate to arbitration or resolve. | | ARBITRATION | An arbitration case has been created with the card network. The network determines the outcome. | | WITHDRAWN | The dispute has been withdrawn at the request of the cardholder. | | REFUNDED | The cardholder has been refunded directly by the merchant through a separate channel. | | EXPIRED | The dispute has expired. | | REJECTED | The dispute has been rejected. | ## Available Actions Actions on a card dispute come from different actors. FinTech actions are available via the Disputes API. Issuer actions may be issued automatically or manually by a Synctera operator when a case needs review. Acquirer / network actions are applied automatically as the case progresses with the card network and appear in `action_history` via `DISPUTE.UPDATED` webhooks. ### Issuer Actions (FinTech) Issuer actions available to FinTechs via the Disputes API. | Lifecycle | Action | Decision | Description | | ------------------- | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------ | | EVIDENCE\_GATHERING | `EVIDENCE_GATHERING.COMPLETE` | ONGOING | Submit collected evidence and file the case with the network. Moves the dispute to `EVALUATION`. | | \* (any open state) | `PROVISIONAL_CREDIT.CREATE` | — | Issue provisional credit as required by regulation or policy. | | \* (any open state) | `PROVISIONAL_CREDIT.REVERSE` | — | Reverse provisional credit as required by regulation or policy. | ### Issuer Actions (Synctera) Issuer actions that may be issued automatically or manually by a Synctera operator (for example in `MANUAL_REVIEW` after chargeback or representment review, or after a pre-arbitration rebuttal). These appear in `action_history` and trigger `DISPUTE.UPDATED` webhooks. | Lifecycle | Action | Decision | Description | | --------------------------- | ------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------- | | \* (any open state) | `PROVISIONAL_CREDIT.SUBMITTED` | — | Issue provisional credit as required by regulation or policy. | | \* (any open state) | `PROVISIONAL_CREDIT.REVERSED` | — | Reverse provisional credit as required by regulation or policy. | | EVALUATION / MANUAL\_REVIEW | `WRITE_OFF.SUBMITTED` | ONGOING | Case written off without (or instead of) pursuing a chargeback. Moves to `WRITE_OFF`. | | EVALUATION / MANUAL\_REVIEW | `CHARGEBACK.SUBMITTED` | ONGOING | Chargeback filed with the card network. Moves to `CHARGEBACK`. | | EVALUATION / MANUAL\_REVIEW | `DISPUTE.REJECTED` | NONE | Case rejected. | | CHARGEBACK | `DISPUTE.WITHDRAWN` | NONE | Case withdrawn while in chargeback. | | REPRESENTMENT | `WRITE_OFF.SUBMITTED` | ONGOING | Case written off instead of continuing after representment; issuer accepts liability. Moves to `WRITE_OFF`. | | REPRESENTMENT | `DISPUTE.LOST` | LOST | Cardholder accepts liability after representment; case lost. | | REPRESENTMENT | `DISPUTE.REFUNDED` | NONE | Merchant credited the cardholder. | | REPRESENTMENT | `DISPUTE.WITHDRAWN` | NONE | Case withdrawn while in representment. | | MANUAL\_REVIEW | `PRE_ARBITRATION.SUBMITTED` | ONGOING | Pre-arbitration filed after representment review. Moves to `PRE_ARBITRATION`. | | MANUAL\_REVIEW | `DISPUTE.WITHDRAWN` | NONE | Case withdrawn at cardholder / Synctera request. | | PRE\_ARBITRATION\_RESPONSE | `WRITE_OFF.SUBMITTED` | ONGOING | Case written off instead of pursuing arbitration; issuer accepts liability. Moves to `WRITE_OFF`. | | PRE\_ARBITRATION\_RESPONSE | `DISPUTE.LOST` | LOST | Cardholder accepts liability after pre-arbitration rebuttal; case lost. | | PRE\_ARBITRATION\_RESPONSE | `DISPUTE.REFUNDED` | NONE | Merchant credited the cardholder. | | PRE\_ARBITRATION\_RESPONSE | `ARBITRATION.SUBMITTED` | ONGOING | Arbitration filed after pre-arbitration rebuttal. Moves to `ARBITRATION`. | | PRE\_ARBITRATION\_RESPONSE | `DISPUTE.WITHDRAWN` | NONE | Case withdrawn after pre-arbitration response. | ### Acquirer / Network Actions Applied automatically as the dispute progresses with the acquirer and card network. Action values below match `action_history` responses. | Lifecycle | Action | Decision | Description | | --------------------------- | --------------------------- | -------- | ---------------------------------------------------------------------------------- | | EVALUATION / MANUAL\_REVIEW | `DISPUTE.REFUNDED` | NONE | Merchant credited the cardholder outside the chargeback flow. Moves to `REFUNDED`. | | EVALUATION / MANUAL\_REVIEW | `DISPUTE.EXPIRED` | NONE | Case expired. | | CHARGEBACK | `REPRESENTMENT.SUBMITTED` | ONGOING | Acquirer filed a re-presentment. Moves to `REPRESENTMENT`. | | CHARGEBACK | `DISPUTE.WON` | WON | Chargeback accepted / case won (no representment). | | REPRESENTMENT | `PRE_ARBITRATION.SUBMITTED` | ONGOING | Pre-arbitration filed. Moves to `PRE_ARBITRATION`. | | PRE\_ARBITRATION | `PRE_ARBITRATION.REBUTTED` | ONGOING | Acquirer rebutted pre-arbitration. Moves to `PRE_ARBITRATION_RESPONSE`. | | PRE\_ARBITRATION | `DISPUTE.WON` | WON | Case won in pre-arbitration. | | PRE\_ARBITRATION | `DISPUTE.LOST` | LOST | Case lost in pre-arbitration. | | ARBITRATION | `DISPUTE.WON` | WON | Case won in arbitration. | | ARBITRATION | `DISPUTE.LOST` | LOST | Case lost in arbitration. | ## Provisional Credits Provisional credits may be issued to the cardholder as a temporary measure while investigating the dispute. Whether or not a provisional credit is required, is determined by the applicable regulations. The relevant regulations/timelines that apply can be derived from the transaction being disputed by identifying which type of card program the transaction belongs to. | BIN Country | Customer Type | Card/BIN Type | Regulation | | ----------- | ------------- | ------------- | ------------ | | US | Consumer | Debit | Regulation E | | US | Consumer | Credit | Regulation Z | | US | Commercial | Debit | N/A | | US | Commercial | Credit | N/A | ### To Summarize: * Regulation E (US) applies to consumer debit transactions - it mandates issuance of provisional credit to the customer account while the dispute is under investigation (within 10 business days for established customers, and within 20 business days for new customers) * Regulation Z (US) applies to consumer credit transactions - it mandates that a transaction that is under dispute is not included in the outstanding/due balances, and is not included in the available credit balance * These regulations also have strict timelines around customer notifications, which is ultimately the responsibility of the FinTech - for details, see [this article](/v2/docs/customer-support-and-complaints) * There are no specific regulations around commercial transactions * Card networks also have their own “zero liability” policies - cardholders won’t be held responsible for unauthorized charges made with their card or card information provided they promptly report the issue * Note that although issuance of provisional credit may not be mandated by regulations, the FinTech may still decide to issue provisional credit ## Complex Business Flow Example The following example walks through a card dispute: create → upload evidence → complete evidence gathering → chargeback filed → provisional credit → representment → dispute lost. ### 1. Dispute Created A dispute is created on behalf of the cardholder. Disputes start in `EVIDENCE_GATHERING`. Include any required `evidence` fields for the chosen `reason_code`. ##### Request ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "CARD", "transaction_id": "{$transaction_id}", "disputed_amount": 500, "date_customer_reported": "2024-05-28T12:25:00.000Z", "memo": "Ordered item never arrived.", "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } } } ' ``` ##### Response ```json JSON theme={"system"} { "account_id": "018fc166-8874-7f3c-943a-178ad1c31903", "applicable_regulation": "REGULATION_Z", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "NONE", "currency": "USD", "customer_id": "018fc166-b34b-7211-aa8d-1ca6c6b7b1e8", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [], "disputed_amount": 500, "id": "018fc167-7672-729d-8d43-653518f3d939", "last_updated_time": "2024-05-28T22:48:24.279984Z", "managed_by": "GROUND_CONTROL", "memo": "Ordered item never arrived.", "network": "DECISIONLY", "payment_rail": "CARD", "status": "OPEN", "tenant": "asbght_iujkio", "transaction_id": "018fc168-3ce3-7839-8cd3-a653bc4aa9bc", "action_history": [], "available_actions": [ { "action": "PROVISIONAL_CREDIT", "state": "CREATE" }, { "action": "EVIDENCE_GATHERING", "state": "COMPLETE" } ], "lifecycle_state": "EVIDENCE_GATHERING", "network_eligibility": { "is_digital_wallet_token": false, "is_three_ds": false, "is_network_eligibility_overridden": false }, "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } }, "acquirer_reference_number": "52405245204967729855476" } ``` ### 2. Upload Documents and Complete Evidence Gathering Supporting documentation is uploaded to the dispute. Files must be JPEG, PNG, or PDF, max 4.5MB each, up to 10 documents. Optionally set `category` (for example `TRANSACTION_RECEIPT`, `MERCHANT_CORRESPONDENCE`, `OTHER`). ##### Request ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/documents \ -H "Authorization: Bearer $apiKey" \ -F file=@file.pdf \ -F category=OTHER ``` ##### Response ```json JSON theme={"system"} { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "file.pdf", "id": "018fc16b-bd41-70bc-89fe-f4330867ba73", "category": "OTHER", "tenant": "asbght_iujkio" } ``` Complete evidence gathering to create and file the case with the network. ##### Request ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/actions \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "state": "COMPLETE" } ' ``` ##### Response ```json JSON theme={"system"} { "id": "018fc16e-0355-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-28T22:58:30.396998Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "status": "COMPLETED", "external_reference_id": "018fc167-7672-729d-8d43-653518f3d939" } ``` #### Dispute State The dispute moves to `EVALUATION`. Synctera then evaluates and may file a chargeback (or write-off / request review). Further network steps arrive as webhook-driven action history updates. ```json JSON theme={"system"} { "account_id": "018fc166-8874-7f3c-943a-178ad1c31903", "applicable_regulation": "REGULATION_Z", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "NONE", "currency": "USD", "customer_id": "018fc166-b34b-7211-aa8d-1ca6c6b7b1e8", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "file.pdf", "id": "018fc16b-bd41-70bc-89fe-f4330867ba73", "category": "OTHER", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "018fc167-7672-729d-8d43-653518f3d939", "last_action_by": "INITIATOR", "last_updated_time": "2024-05-28T22:58:30.396998Z", "managed_by": "GROUND_CONTROL", "memo": "Ordered item never arrived.", "network": "DECISIONLY", "payment_rail": "CARD", "status": "OPEN", "tenant": "asbght_iujkio", "transaction_id": "018fc168-3ce3-7839-8cd3-a653bc4aa9bc", "action_history": [ { "id": "018fc16e-0355-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-28T22:58:30.396998Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "status": "COMPLETED", "external_reference_id": "018fc167-7672-729d-8d43-653518f3d939" } ], "available_actions": [ { "action": "PROVISIONAL_CREDIT", "state": "CREATE" } ], "lifecycle_state": "EVALUATION", "network_eligibility": { "is_digital_wallet_token": false, "is_three_ds": false, "is_network_eligibility_overridden": false }, "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } }, "acquirer_reference_number": "52405245204967729855476" } ``` ### 3. Chargeback Submitted After evaluation, Synctera files a chargeback with the card network. This appears as a `DISPUTE.UPDATED` webhook with `CHARGEBACK.SUBMITTED` in `action_history`. The dispute moves to `CHARGEBACK`. #### Dispute State ```json JSON theme={"system"} { "account_id": "018fc166-8874-7f3c-943a-178ad1c31903", "applicable_regulation": "REGULATION_Z", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "NONE", "currency": "USD", "customer_id": "018fc166-b34b-7211-aa8d-1ca6c6b7b1e8", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "file.pdf", "id": "018fc16b-bd41-70bc-89fe-f4330867ba73", "category": "OTHER", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "018fc167-7672-729d-8d43-653518f3d939", "last_action_by": "NETWORK", "last_updated_time": "2024-05-29T09:00:00.000000Z", "managed_by": "GROUND_CONTROL", "memo": "Ordered item never arrived.", "network": "DECISIONLY", "payment_rail": "CARD", "status": "OPEN", "tenant": "asbght_iujkio", "transaction_id": "018fc168-3ce3-7839-8cd3-a653bc4aa9bc", "action_history": [ { "id": "018fc16e-0355-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-28T22:58:30.396998Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "status": "COMPLETED", "external_reference_id": "018fc167-7672-729d-8d43-653518f3d939" }, { "id": "018fcb2e-1111-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-29T09:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "CHARGEBACK", "status": "SUBMITTED" } ], "available_actions": [ { "action": "PROVISIONAL_CREDIT", "state": "CREATE" } ], "lifecycle_state": "CHARGEBACK", "network_eligibility": { "is_digital_wallet_token": false, "is_three_ds": false, "is_network_eligibility_overridden": false }, "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } }, "acquirer_reference_number": "52405245204967729855476" } ``` ### 4. Post Provisional Credit A provisional credit may be issued after the chargeback has been filed. ##### Request ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/actions \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "CARD", "action": "PROVISIONAL_CREDIT", "state": "CREATE" } ' ``` ##### Response ```json JSON theme={"system"} { "id": "018fcb2f-50f4-7514-a82d-e6143f57f25f", "creation_time": "2024-05-29T10:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "PROVISIONAL_CREDIT", "status": "SUBMITTED" } ``` #### Dispute State ```json JSON theme={"system"} { "account_id": "018fc166-8874-7f3c-943a-178ad1c31903", "applicable_regulation": "REGULATION_Z", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "PROVISIONAL", "currency": "USD", "customer_id": "018fc166-b34b-7211-aa8d-1ca6c6b7b1e8", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "file.pdf", "id": "018fc16b-bd41-70bc-89fe-f4330867ba73", "category": "OTHER", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "018fc167-7672-729d-8d43-653518f3d939", "last_action_by": "INITIATOR", "last_updated_time": "2024-05-29T10:00:00.000000Z", "managed_by": "GROUND_CONTROL", "memo": "Ordered item never arrived.", "network": "DECISIONLY", "payment_rail": "CARD", "status": "OPEN", "tenant": "asbght_iujkio", "transaction_id": "018fc168-3ce3-7839-8cd3-a653bc4aa9bc", "action_history": [ { "id": "018fc16e-0355-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-28T22:58:30.396998Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "status": "COMPLETED", "external_reference_id": "018fc167-7672-729d-8d43-653518f3d939" }, { "id": "018fcb2e-1111-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-29T09:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "CHARGEBACK", "status": "SUBMITTED" }, { "id": "018fcb2f-50f4-7514-a82d-e6143f57f25f", "creation_time": "2024-05-29T10:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "PROVISIONAL_CREDIT", "status": "SUBMITTED" } ], "available_actions": [ { "action": "PROVISIONAL_CREDIT", "state": "REVERSE" } ], "lifecycle_state": "CHARGEBACK", "network_eligibility": { "is_digital_wallet_token": false, "is_three_ds": false, "is_network_eligibility_overridden": false }, "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } }, "acquirer_reference_number": "52405245204967729855476" } ``` ### 5. Webhook Received for Representment #### Dispute State A representment from the acquirer is reflected on the dispute via `DISPUTE.UPDATED`, including any supporting documentation from the network. ```json JSON theme={"system"} { "account_id": "018fc166-8874-7f3c-943a-178ad1c31903", "applicable_regulation": "REGULATION_Z", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "PROVISIONAL", "currency": "USD", "customer_id": "018fc166-b34b-7211-aa8d-1ca6c6b7b1e8", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "file.pdf", "id": "018fc16b-bd41-70bc-89fe-f4330867ba73", "category": "OTHER", "tenant": "asbght_iujkio" }, { "creation_time": "2024-05-30T20:32:00.000000Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "representment.pdf", "id": "018fcb30-90a1-7221-9160-28917c2cfc2d", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "018fc167-7672-729d-8d43-653518f3d939", "last_action_by": "NETWORK", "last_updated_time": "2024-05-30T20:32:03.787519Z", "managed_by": "GROUND_CONTROL", "memo": "Ordered item never arrived.", "network": "DECISIONLY", "payment_rail": "CARD", "status": "OPEN", "tenant": "asbght_iujkio", "transaction_id": "018fc168-3ce3-7839-8cd3-a653bc4aa9bc", "action_history": [ { "id": "018fc16e-0355-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-28T22:58:30.396998Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "status": "COMPLETED", "external_reference_id": "018fc167-7672-729d-8d43-653518f3d939" }, { "id": "018fcb2e-1111-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-29T09:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "CHARGEBACK", "status": "SUBMITTED" }, { "id": "018fcb2f-50f4-7514-a82d-e6143f57f25f", "creation_time": "2024-05-29T10:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "PROVISIONAL_CREDIT", "status": "SUBMITTED" }, { "id": "018e62f5-8141-708f-a924-c706d82876a5", "creation_time": "2024-05-30T20:32:03.787519Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "REPRESENTMENT", "status": "SUBMITTED", "supporting_doc_id": "018fcb30-90a1-7221-9160-28917c2cfc2d", "message": "Merchant provided proof of delivery" } ], "available_actions": [ { "action": "PROVISIONAL_CREDIT", "state": "REVERSE" } ], "lifecycle_state": "REPRESENTMENT", "network_eligibility": { "is_digital_wallet_token": false, "is_three_ds": false, "is_network_eligibility_overridden": false }, "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } }, "acquirer_reference_number": "52405245204967729855476" } ``` ### 6. Dispute Lost The issuer records that the cardholder accepts liability after representment (`DISPUTE.LOST`). ##### Request ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/actions \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "CARD", "action": "DISPUTE", "state": "LOST" } ' ``` #### Dispute State The dispute now reflects the final decision. Any outstanding provisional credit is reversed on a delay (not immediately). ```json JSON theme={"system"} { "account_id": "018fc166-8874-7f3c-943a-178ad1c31903", "applicable_regulation": "REGULATION_Z", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "PROVISIONAL", "currency": "USD", "customer_id": "018fc166-b34b-7211-aa8d-1ca6c6b7b1e8", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "LOST", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "file.pdf", "id": "018fc16b-bd41-70bc-89fe-f4330867ba73", "category": "OTHER", "tenant": "asbght_iujkio" }, { "creation_time": "2024-05-30T20:32:00.000000Z", "dispute_id": "018fc167-7672-729d-8d43-653518f3d939", "file_name": "representment.pdf", "id": "018fcb30-90a1-7221-9160-28917c2cfc2d", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "018fc167-7672-729d-8d43-653518f3d939", "last_action_by": "INITIATOR", "last_updated_time": "2024-05-31T20:32:03.787519Z", "managed_by": "GROUND_CONTROL", "memo": "Ordered item never arrived.", "network": "DECISIONLY", "payment_rail": "CARD", "status": "OPEN", "tenant": "asbght_iujkio", "timestamp_final_decision": "2024-05-31T20:32:03.787519Z", "transaction_id": "018fc168-3ce3-7839-8cd3-a653bc4aa9bc", "action_history": [ { "id": "018fc16e-0355-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-28T22:58:30.396998Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "EVIDENCE_GATHERING", "status": "COMPLETED", "external_reference_id": "018fc167-7672-729d-8d43-653518f3d939" }, { "id": "018fcb2e-1111-7cea-bf80-b0eddd63d48a", "creation_time": "2024-05-29T09:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "CHARGEBACK", "status": "SUBMITTED" }, { "id": "018fcb2f-50f4-7514-a82d-e6143f57f25f", "creation_time": "2024-05-29T10:00:00.000000Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "PROVISIONAL_CREDIT", "status": "SUBMITTED" }, { "id": "018e62f5-8141-708f-a924-c706d82876a5", "creation_time": "2024-05-30T20:32:03.787519Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "REPRESENTMENT", "status": "SUBMITTED", "supporting_doc_id": "018fcb30-90a1-7221-9160-28917c2cfc2d", "message": "Merchant provided proof of delivery" }, { "id": "018e62fa-4e7a-7814-9634-e130c66f6444", "creation_time": "2024-05-31T20:32:03.787519Z", "tenant": "asbght_iujkio", "payment_rail": "CARD", "action": "DISPUTE", "status": "LOST" } ], "available_actions": [ { "action": "PROVISIONAL_CREDIT", "state": "REVERSE" } ], "lifecycle_state": "REPRESENTMENT", "network_eligibility": { "is_digital_wallet_token": false, "is_three_ds": false, "is_network_eligibility_overridden": false }, "reason_code": "GOODS_OR_SERVICES_NOT_PROVIDED", "evidence": { "merchant_contact": { "was_attempted": true, "date": "2024-05-20", "was_successful": false, "description": "Called merchant support; no tracking information provided." }, "delivery": { "expected_date": "2024-05-15" } }, "acquirer_reference_number": "52405245204967729855476" } ``` ### 7. Close Dispute After the provisional credit has been reversed (`credit_status` = `NONE`), close the dispute. ##### Request ```bash Shell theme={"system"} curl \ -X PATCH \ $baseurl/v1/disputes/{$dispute_id} \ -H "Authorization: Bearer $apiKey" \ --json ' { "status": "CLOSED" } ' ``` ## Simulating Network Dispute Actions **Sandbox Environment Only** Simulations are intended for use only in the testing environment to simulate a network action on a dispute. For dispute creation and issuer actions, follow the steps listed in the [Transaction Disputes API Guide](/v2/docs/transaction-disputes). In production, acquirer / network actions are applied automatically as the case progresses with the card network. In sandbox, use simulations to advance those same steps without waiting on a live network response. Network dispute simulations must follow the logical order of the dispute lifecycle — for example, after a chargeback is submitted you can simulate a representment. For a complete list of network actions, see [Acquirer / Network Actions](/v2/docs/card-transaction-disputes#acquirer--network-actions). To progress a dispute to the next lifecycle and simulate a network response, use [`POST /v1/disputes/simulations/{$dispute_id}/actions`](/v2/reference/simulatedisputeaction). Request bodies use `state` (for example `CREATE`); matching entries in `action_history` use `status` (for example `SUBMITTED`). ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/simulations/{$dispute_id}/actions \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "CARD", "action": "REPRESENTMENT", "state": "CREATE", "message": "Merchant provided proof of delivery" } ' ``` # Card Transactions Source: https://docs.synctera.com/v2/docs/card-transactions A card transaction is defined as a transaction that occurs on a customer issued card. ## Card Transactions All Synctera payment types utilize the common `/transactions` resource - see [API reference](/v2/reference/gettransactionsbatchpayments) for details. ### Transaction Flows The flow of a transaction is split into two major components: ### Funding Request Funding requests are initiated at the time of card usage. When a cardholder initiates a transaction, the merchant sends a request to the network. The network then sends a funding request to Synctera, expecting an approved or denied response. A [Pending Transaction](/v2/reference/gettransactionsbatchpayments) is created when the funding request is received, which publishes a [webhook](/v2/docs/webhooks-guide)) on the `transaction.pending.created` topic with initial status `PENDING`. Synctera then makes a determination on whether to approve or decline the funding request. See [declined transactions](#declined-transactions) for more details. While evaluating the funding request, the [Pending Transaction](/v2/reference/gettransactionsbatchpayments) may be updated with supplemental data gathered during the process. A `transaction.pending.upated` [webhook](/v2/docs/webhooks-guide) is published when the transaction is updated. For example, [enhanced transaction](#enhanced-transactions) information may be added. #### Funding Request Flow ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram Customer->>Merchant: Initiate transaction Merchant->>Network: Request Network->>Synctera: Funding request Synctera->>FinTech: Pending transaction created webhook Synctera->>Synctera: Evaluate funding request Synctera->>FinTech: Pending transaction updated webhook Synctera-->>Network: Response Network-->>Merchant: Response ``` In addition, the FinTech can elect to participate in the funding request authorization flow - see [FinTech in the auth flow](#fintech-in-the-auth-flow) - which adds an additional decision point to the evaluation. ### Clearing The transaction is not fully complete until it has cleared. The clearing process causes a transaction to change from **pending** to **posted**. This is when money actually moves. Note that **pending** and **posted** transactions are distinct resources - see [API reference](/v2/reference/gettransactionsbatchpayments) for more details. After the funding request is approved - sometimes hours - the merchant initiates a request to the network for retrieving the funds for all of their pending transactions. Synctera receives the clearing notification, updates the [Pending Transaction](/v2/reference/gettransactionsbatchpayments) and creates a [Posted Transaction](/v2/reference/gettransactionsbatchpayments). Two [webhooks](/v2/docs/webhooks-guide) are published when clearing is complete. First, `transaction.pending.updated` when [Pending Transaction](/v2/reference/gettransactionsbatchpayments) status is changed to `CLEARED`. Second, `transaction.posted.created` when the [Posted Transaction](/v2/reference/gettransactionsbatchpayments) is created. #### Clearing Flow ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram Merchant->>Network: Request Network->>Synctera: Notification Synctera->>FinTech: Pending transaction updated webhook Synctera->>FinTech: Posted transaction created webhook ``` ### Declined Transactions Transactions may be declined for various reasons, including: * Insufficient funds * Suspected fraud * Customer or account in bad standing * Gateway ([FinTech in the auth flow](#fintech-in-the-auth-flow)) * [Network Stand-In](#network-stand-in-scenario) * Address Verification Service (AVS) did not match address on file When a transaction is declined, the status is updated to `DECLINED`. In most cases, a `transaction.pending.updated` will be issued to signal change of status. However, in the case of network declination, there will only be a `transaction.pending.created` webhook with initial status of `DECLINED`. The `data.reason` field of the [Pending Transaction](/v2/reference/gettransactionsbatchpayments) body contains the reason for why the transaction was declined. Below is a list of reasons and their sources: Customer/account standing: * `NO_CHECKING_ACCOUNT` * `NO_SAVINGS_ACCOUNT` * `NO_CREDIT_ACCOUNT` * `CLOSED_ACCOUNT` Fraud: * `SUSPECTED_FRAUD` Ledger: * `INSUFFICIENT_FUNDS` * `DISABLED_PAYMENT_TYPE` * `BALANCE_VIOLATION` * `DUPLICATE_TRANSACTION` * `SPEND_CONTROL_VIOLATED` (see [Spend Controls](/v2/docs/spend-controls-guide)) Network stand-in: * `NETWORK_DECLINED` For network declined transactions, there will be additional details under `data.user_data.network_decline_details` of the [Pending Transaction](/v2/reference/gettransactionsbatchpayments) body. Gateway: * `GATEWAY_DECLINED` * `GATEWAY_ERROR` Address Verification Service (AVS): * `ADDRESS_VERIFICATION_FAILED` General purpose: * `TRANSACTION_NOT_PERMITTED` The list of possible decline reasons is subject to grow, so code should be written defensively around processing declined transactions. ### Network Stand-In Scenario Stand-in scenario happens when a funding request from the network is not responded to in time, so the network must *stand in* to be the decision maker. It is intended to be a fallback mechanism and not to be consistently relied upon, as there is less control over the decision which may result in undesired money movement. In rare cases, Synctera may never recieve a funding request and only be informed that a transaction has taken place after the fact. In this case, there will only be a [Posted Transaction](/v2/reference/gettransactionsbatchpayments), no [Pending Transaction](/v2/reference/gettransactionsbatchpayments). ### Card Transaction Simulations Synctera provides a variety of endpoints that simulate card transactions. These endpoints mimic how real transaction will look in a production environment. This gives FinTechs the tools to develop and test their application against the different types of card transactions without any real money movement or financial impact. All card transaction simulation endpoints are found under the `/cards/transaction_simulations` path - see [API reference](/v2/reference/simulateauthorization) for details. These endpoints can only be used in the [Synctera Sandbox](/v2/reference/need-to-know#sandbox) environment. This guide will explain how to simulate a selection of typical transaction scenarios. #### Merchant Information Fields Many of these endpoints require a `card_acceptor` object, which contains merchant information: ```json JSON theme={"system"} { "address": "address", "city": "city", "country": "country", "mcc": "mcc", "name": "name", "state": "state", "zip": "zip" } ``` The `mcc` (MCC - Merchant Category Code) field is a universal code assigned to merchants for the purpose of classifying the type of goods and services they provide. In addition, the top level `mid` (MID - Merchant Identification Number) field is sometimes required. This is a unique identifier assigned to all merchants that process card transactions. For simulations, the content used for `card_acceptor` and `mid` is not neccesarily important. However, merchant information is often crucial for [FinTech in the Auth Flow](#fintech-in-the-auth-flow). #### 1. Authorization & Clearing This describes the typical case where a cardholder purchases something from a physical or online merchant. The transaction amount is authorized, then later cleared. To simulate this scenario, an **authorization**, then **clearing** is performed. Note that an **authorization** equates to a [funding request](#funding-request). To simulate, first call [Simulate authorization](/v2/reference/simulateauthorization), providing the appropriate `card_id`, along with the authorization `amount`. This will generate an **authorization** (funding request), which applies a hold for the given amount of money and creates a [Pending Transaction](/v2/reference/gettransactionsbatchpayments). On a successful call, a transaction `token` is generated. The `token` is needed for clearing. Next, call [Simulate clearing or refund](/v2/reference/simulateclearing) with the same `amount` as was used in the **authorization** and `original_transaction_id` set to the **authorization** transaction `token`. #### 2. Authorization Adjustment In some circumstances, a merchant may want to authorize for a different amount than what is ultimately cleared. For example, at a gas pump, it is common for a customer to pre-authorize up to a certain amount, but only be charged for the amount of gas that was actually pumped. In this case, an initial **authorization** is created for the pre-authorized amount. Once the final sale price is determined, an **authorization advice** is performed to adjust the hold. Like the previous scenario, a final **clearing** is done to capture the funds. To simulate, first call [Simulate authorization](/v2/reference/simulateauthorization) like in the previous example and retain the transaction `token`. Next, issue an **authorization advice** with [Simulate authorization advice](/v2/reference/simulateauthorizationadvice), providing the new `amount` and `original_transaction_id` (`token`). Finally, issue the **clearing** with [Simulate clearing or refund](/v2/reference/simulateclearing), using the final `amount` from the **authorization advice** and `original_transaction_id` set to the transaction `token` from the original **authorization** response. #### 3. Reversals & Refunds **Reversals** and **refunds** both refer to the undoing of a previous action, the only difference being the action that is being undone. **Reversals** release an existing **authorization** hold and **refunds** undo a cleared transaction and move funds back to a cardholder's card. To simulate a **reversal**, an existing **authorization** hold must already exist. To issue the reversal, call [Simulate reversal](/v2/reference/simulatereversal), providing the full **authorization** `amount` and `original_transaction_id` set **authorization** transaction `token` for `original_transaction_id`. Likewise, to simulate a **refund**, a cleared transaction must already exist. To issue the refund, call [Simulate clearing or refund](/v2/reference/simulateclearing), providing the final `amount` from the **clearing** and the original **authorization** transaction `token` for `original_transaction_id`. #### 4. Single Message All above listed scenarios involve **dual message** transactions. Meaning, the transaction occurs in two parts: **authorization**, then **clearing**. However, there are also **single message** transactions, where **authorization** and **clearing** occur in a single action. Common examples include PIN-debit transactions and ATM transactions. Below are descriptions of the common **single message** simulation endpoint use cases: * [Simulate financial](/v2/reference/simulatefinancial): This endpoint is used to simulate a PIN-debit transaction - when a cardholder provides their PIN code at the time of purchase. The `amount` and `card_id` must be provided. * [Simulate ATM withdrawal](/v2/reference/simulatewithdrawal): This endpoint simulates a cash withdrawal from an ATM (Automated Teller Machine). Similarly, `amount` and `card_id` must be provided. #### 5. L2L3 data Level 2 and Level 3 card processing data provide detailed information about a transaction. These additional fields within a payment message offer a comprehensive view of the specific items or services being paid for. To simulate a l2l3, an existing cleared transaction must already exists. Meaning, the transaction occurs in three parts: authorization, clearing then l2l3. To issue a l2l3, call [Simulate l2l3](/v2/reference/simulatel2l3), providing the clearing transaction token for original\_transaction\_id and the l2l3 data. ### Enhanced Transactions By default, transaction metadata (merchant name, location, category, etc.) is provided by the network - found in the transaction `data.user_data` object. For the most part, this information is limited and often inconsistently formatted. If desired, a card product can be configured with a supported third party provider to add enhanced metadata to each transaction. Synctera's current supported enhanced transaction provider is [MX](https://www.mx.com). For example, given the following network provided merchant name and MCC (merchant category code): ```json JSON theme={"system"} { "mcc": "4816", "name": "EIG*HOSTGATOR.COM" } ``` Enhanced transaction can provide a cleanly formatted name and consistent category: ```json JSON theme={"system"} { "category": "Hosting", "enhanced_description": "HostGator" } ``` Enhanced transaction information is found in the transaction `data.user_data.enhanced_transaction` object. `enhanced_raw` contains the complete set of data received from the enhanced transaction provider. ```json JSON theme={"system"} { "category": "Hosting", "enhanced_description": "HostGator", "enhanced_raw": [ { "amount": 12.75, "categorized_by": 13, "category": "Hosting", "category_guid": "CAT-b74fdd98-4391-8015-eafa-e9ca0fad3bee", "described_by": 6, "description": "HostGator", "extended_transaction_type": null, "id": "2ffa6d90-e4d0-47e3-a290-17240e7a3ae4", "is_bill_pay": false, "is_direct_deposit": false, "is_expense": null, "is_fee": null, "is_income": false, "is_international": null, "is_overdraft_fee": false, "is_payroll_advance": false, "is_subscription": false, "memo": "ad0f57f1-f823-4ba7-8563-a1c4aa458371", "merchant_category_code": 4816, "merchant_guid": "MCH-dae1c6b5-292b-4d3e-ba15-998ab24a79c2", "merchant_location_guid": null, "original_description": "EIG*HOSTGATOR.COM", "type": "DEBIT" } ] } ``` ### L2/L3 Data Some transactions contain Level 2 / Level 3 (L2/L3) data, which provides much more detailed information about the transaction. For details on L2/L3 data, see [this article](/v2/docs/level-2-level-3-data). When available, L2/L3 data is received from the processor as part of card transaction clearing events/webhooks, i.e. as a transaction transitions from authorized/pending to cleared/posted. On occasion, for a single transaction with Level 2/Level 3 data, we may receive a clearing event followed by the L2/L3 data several hours later. As a result, a transaction might initially be posted without detailed L2/L3 data, only to be subsequently updated when this additional information becomes available. When available, L2/L3 data is found in the transaction user\_data.l2l3 object on a posted transaction. Example: ```json JSON theme={"system"} { "l2l3": { "enhanced_data_id": "e3434344d343434dfdf3564645jk4282328032903j323923023u4h434343", "financial": { "tax_id": "123456789", "total_tax_amount_indicator": "D" }, "fleet_emv": { "vat_tax_rate": "0", "service_type": "S", "odometer_reading": "0000000", "fuel_net_amount": 1000, "fuel_gross_amount": 1000, "fuel_unit_price": "358.9", "fuel_unit_of_measure": "G", "fuel_quantity": "2.786", "expanded_fuel_type": "01", "type_of_purchase": "3", "non_fuel_gross_amount": 1625, "non_fuel_item_details": [ { "product_code": "ZC" } ] }, "inventory_details": [ { "description": "Edelmann 92397 Power Steering Press", "item_discount_amount_indicator": "C", "item_discount_applied_indicator": "N", "item_extended_amount": 5048, "item_extended_amount_indicator": "D", "product_code": "B00J5W6CZQ", "quantity": "1", "unit_of_measure": "PCE" } ] } } ``` ### FinTech in the Auth Flow #### Authorization Gateway An authorization Gateway enables a FinTech to optionally take part in the funding request decision of a card transaction’s authorization cycle. The FinTech receives an authorization request via the configured Gateway to either approve or decline the card transaction based on the FinTech's own business logic. If the fintech opts not to participate in the auth flow Synctera will use default authorization logic to authorize the transactions. The fintech does not have to participate unless there is additional approval logic they would like to incorporate into the decision process that is not supported by Synctera or proprietary in nature. The authorization request must be responded to within a firm timeout window of **1.5 seconds**. Synctera will default to declining the funding request if a response is not received within the timeout window. The information in the authorization request includes, but is not limited to: * Customer/Account/Card ID's * Available balance * Merchant information ```json JSON theme={"system"} { "customer_id": "2b9cc6f2-d0bd-4d9d-aa20-5e53355f9469", "account_id": "0221e0a7-7774-48a4-8521-e678ec09a53a", "transaction_id": "9b59fc80-9bf5-4749-8dd2-511f183becf2", "card_id": "6128498a-85a9-4bd8-a3ea-bfe3717b64f6", "card_format": "PHYSICAL", "last_four": "1234", "type": "card_transaction", "user_transaction_time": "2022-03-25T10:41:01-04:00", "settlement_date": "0001-01-01T00:00:00Z", "amount": { "amount": 100, "currency": "USD", "currency_conversion": { "original_amount": 100, "conversion_rate": 1, "original_currency_code": "840", "original_currency_code_alpha": "USD" } }, "balance": { "available_balance": 4210000 }, "merchant": { "mid": "4445001899609", "mcc": "5411", "name": "WHOLEFDS EGW 101", "city": "EDGEWATER", "state": "NJ", "postal_code": "07020", "country_code": "USA", "sub_merchant_id": "", "payment_facilitator_id": "" }, "user": {}, "network_fraud": { "transaction_risk_score": 18 }, "network": "MASTERCARD", "subnetwork": "", "dc_sign": "debit", "pos": { "pan_entry_mode": "MAG_STRIPE", "pin_present": false, "terminal_id": "10000000", "cvv_presence": "CVV1" }, "processor": "MARQETA", "processor_data": {} } ``` Addionally, if [enhanced transactions](#enhanced-transactions) are enabled for the FinTech, this information will also be included. To signal an authorization request decision, the FinTech must reply with the appropriate HTTP code: * HTTP code `200`: **approve** the funding request * HTTP code `402`: **decline** the funding request Note that while HTTP code `402` is conventional, any code other than `200` will also be interpreted as a **decline**. #### FinTech Included in Funding Request Authorization Flow ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram Customer->>Merchant: Initiate transaction Merchant->>Network: Request Network->>Synctera: Funding request Synctera->>FinTech: Pending transaction created webhook Synctera->>Synctera: Evaluate funding request Synctera->>FinTech: Authorization request FinTech->>FinTech: Evaluate authorization request FinTech-->>Synctera: Response Synctera->>FinTech: Pending transaction updated webhook Synctera-->>Network: Response Network-->>Merchant: Response ``` #### Sandbox Implementation 1. Create a new Gateway configuration via [Synctera API](/v2/reference/listcards) 2. Generate an authorization [card transaction simulation](#card-transaction-simulations) and ensure the Gateway endpoint successfully recieves and responds to the request For local testing, [ngrok](https://ngrok.com) or [beeceptor](https://beeceptor.com) can be used to produce a publicly accesable URL that terminates to a local development endpoint. #### Gateway Endpoint Configuration To create a Gateway, a valid, publicly accessable URL must be supplied, along with a list of Card Product ID's that will utilize the Gateway. Additionally, customer headers may be supplied that will be included in authorization calls to the Gateway. If not supplied, `active` status is set to `true` by default. Gateways may be turned off by setting this field `false`. Note that a Card Product may not be configured on more than one active Gateway at a time. ```bash Shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ $baseurl/v0/cards/gateways \ --data-binary ' { "active": true, "url": "https://example.com", "custom_headers": { "key": "value" }, "card_products": [ "41e81dff-05d4-4421-b7f0-149e3a536979", "e8361f07-1e7d-440c-91bd-def3e18a907f" ] }' ``` # Card Widgets Source: https://docs.synctera.com/v2/docs/card-widgets With the Card Widgets, your customers can view and interact with sensitive card information inside the application. Synctera provides secure, PCI-compliant widgets that let your customers interact with sensitive card data directly in your application. Since the widgets communicate directly between the client and Synctera, your application does not need to handle sensitive card data, removing the need for PCI certification. There are four widgets available: ### Reveal Card Widget Securely display sensitive card information — card number (PAN), security code (CVV), and expiration date. Reveal Card Front Reveal Card Back ### Activate Card Widget Allow customers to activate a physical card by entering their card number and security code. Activate Card ### Set PIN Widget Allow customers to set or change their card PIN with secure confirmation. Set PIN ### Reveal PIN Widget Securely display a cardholder's existing PIN, with an auto-hide countdown. The PIN is rendered inside an isolated iframe and never exposed to your page. Reveal PIN ## Getting Started Make sure you've got the necessary components in place before integrating widgets with your application. ### API Keys First, ensure you have your [Synctera API Keys](/v2/docs/dev-setup#sign-up-for-a-synctera-account-and-generate-api-keys) working for your business. ### Mobile Applications If you're integrating the widgets in a mobile application, you may need to use one of the following web views: ### Content Security Policy If your application sets a [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), you must allow the Synctera widget domains. The widgets load scripts and create iframes from Synctera-hosted origins, so a strict CSP that omits these domains will silently block the widgets from rendering. Add the following directives for your environment: ```text Sandbox theme={"system"} script-src https://assets-sandbox.synctera.com; frame-src https://assets-sandbox.synctera.com; connect-src https://assets-sandbox.synctera.com https://api-sandbox.synctera.com; ``` ```text Production theme={"system"} script-src https://assets.synctera.com; frame-src https://assets.synctera.com; connect-src https://assets.synctera.com https://api.synctera.com; ``` If you use `nonce`-based script policies, the widget's ` ``` ```javascript React theme={"system"} import { useEffect } from 'react'; function ActivateCardForm({ widgetToken }) { useEffect(() => { const script = document.createElement('script'); script.type = 'module'; script.src = 'https://assets.synctera.com/widgets/activate/v1.1.1/index.js'; document.head.appendChild(script); return () => { document.head.removeChild(script); }; }, []); return ( ); } ``` ## Step 2: Get a Widget Token Request a widget token from your backend using the Synctera API. The widget token is required for the widget to authenticate and submit data. ```bash curl theme={"system"} curl -X GET "https://api.synctera.com/v2/cards/{card_id}/widget_token?widget_type=ACTIVATE" \ -H "Authorization: Bearer {apiKey}" \ -H "Content-Type: application/json" ``` ```javascript Node.js theme={"system"} const response = await fetch( `https://api.synctera.com/v2/cards/${cardId}/widget_token?widget_type=ACTIVATE`, { method: 'GET', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } } ); const { widget_token } = await response.json(); ``` Widget tokens expire after **5 minutes** and are scoped to a specific card. Generate a new token on each page load or when the user initiates a new activation. ## Step 3: Add the Widget Component Add the `` web component to your page: ```html theme={"system"} ``` *** ## Configuration Options | Property | Type | Required | Default | Description | | --------------- | -------- | -------- | ----------- | -------------------------------------------------------------------------------------- | | `token` | `string` | Yes | - | Widget token obtained from the API | | `env` | `string` | Yes | - | Environment: `sandbox` or `production` | | `theme` | `string` | No | `"default"` | Theme preset: `"default"` or `"night-shift"` | | `styles` | `string` | No | `{}` | JSON string of [design tokens](/v2/docs/card-widgets-theming) for visual customization | | `custom-labels` | `string` | No | `{}` | JSON string of custom labels for form fields | *** ## Custom Labels Customize the labels displayed in the widget: ```html theme={"system"} ``` Available custom label keys: * `widgetTitle` - Widget header text * `cardNumberLabel` - Card number field label * `securityCodeLabel` - CVV field label * `cardPanPlaceholder` - Card number placeholder * `cardCvvPlaceholder` - CVV placeholder * `submitButtonText` - Submit button text * `submitLoadingText` - Loading state text *** ## Event Handling The widget dispatches lifecycle events across two phases: | Phase | Events | Description | | ------------------ | -------------------------------------- | -------------------------------------------------------------------------------------------- | | **Initialization** | `load` or `error` (mutually exclusive) | Fires once when the widget first renders and its secure input fields load (or fail to load). | | **Submission** | `success` or `failure` | Fires after the user submits the form. | * **`load`** — Widget initialized successfully, all fields are ready for user input. * **`error`** — Widget failed to initialize (field load failure, network error, or timeout). * **`success`** — Card activation completed successfully. * **`failure`** — Card activation failed (incorrect card number, wrong CVV, expired widget token, or API error). `error` fires only during widget initialization (e.g., a secure input field failed to load). If the widget loads successfully but the user's submission fails — incorrect PAN, wrong CVV, expired token — that triggers `failure`, not `error`. You can listen for events using either **`addEventListener`** or **callback properties**: | Event | addEventListener | Callback property | | ---------------------- | ---------------------------------------- | ----------------------- | | Initialization success | `widget.addEventListener('load', fn)` | `widget.onLoad = fn` | | Initialization failure | `widget.addEventListener('error', fn)` | `widget.onError = fn` | | Submission success | `widget.addEventListener('success', fn)` | `widget.onSuccess = fn` | | Submission failure | `widget.addEventListener('failure', fn)` | `widget.onFailure = fn` | ### Load Event Dispatched when all secure input fields have loaded and the widget is fully functional. Use it to hide loading UI or enable dependent controls. | Property | Type | Description | | ------------ | -------- | ---------------------------------- | | `instanceId` | `string` | Unique ID for this widget instance | ```html theme={"system"} ``` ### Error Event Dispatched when the widget fails to initialize. This means one or more secure input fields could not load, and the widget is not functional. Show an error message or retry UI to the user. | Property | Type | Description | | -------------- | ---------- | ---------------------------------------------- | | `instanceId` | `string` | Unique ID for this widget instance | | `error` | `string` | Human-readable error message (safe to display) | | `failedFields` | `string[]` | List of field types that failed to load | ```html theme={"system"} ``` The `load` and `error` events are mutually exclusive — exactly one will fire during widget initialization. Always listen for both to handle all scenarios. ### Success and Failure Events Dispatched after the user submits the activation form. Common `failure` reasons include incorrect card number, wrong CVV, and expired widget token. The `success` event exposes only non-sensitive status metadata: | Property | Type | Description | | ------------ | -------- | ---------------------------------------- | | `status` | `string` | Submission status returned by the widget | | `message` | `string` | Optional human-readable success message | | `instanceId` | `string` | Unique ID for this widget instance | PAN and CVV are never included in host-page event details. ```html addEventListener theme={"system"} ``` ```html Callback Properties theme={"system"} ``` *** ## Complete Example ```html Complete HTML Example theme={"system"} Activate Card

Activate Your Card

``` ```javascript React Example (Callback Properties) theme={"system"} import { useEffect, useState, useRef } from 'react'; function ActivateCardForm({ cardId }) { const [widgetToken, setWidgetToken] = useState(null); const [error, setError] = useState(null); const widgetRef = useRef(null); useEffect(() => { const script = document.createElement('script'); script.type = 'module'; script.src = 'https://assets.synctera.com/widgets/activate/v1.1.1/index.js'; document.head.appendChild(script); fetch('/api/card-widget-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ card_id: cardId, widget_type: 'ACTIVATE' }) }) .then(res => res.json()) .then(data => setWidgetToken(data.widget_token)) .catch(err => setError(err.message)); return () => { document.head.removeChild(script); }; }, [cardId]); useEffect(() => { if (!widgetToken || !widgetRef.current) return; const widget = widgetRef.current; widget.onLoad = (event) => { console.log('Widget ready:', event.detail.instanceId); }; widget.onError = (event) => { const { error, failedFields } = event.detail; console.error('Widget failed to initialize:', error, failedFields); setError(error); }; widget.onSuccess = (event) => { const { status, message } = event.detail; console.log('Card activated:', status, message); }; widget.onFailure = (event) => { setError(event.detail.error); }; return () => { widget.onLoad = null; widget.onError = null; widget.onSuccess = null; widget.onFailure = null; }; }, [widgetToken]); if (error) return
Error: {error}
; if (!widgetToken) return
Loading...
; return ( ); } export default ActivateCardForm; ```
# Legacy: Marqeta Widgets Source: https://docs.synctera.com/v2/docs/card-widgets-legacy Documentation for the deprecated Marqeta widget integrations. Marqeta is sunsetting their Marqeta.js widget library. We recommend migrating to [Synctera Widgets](/v2/docs/card-widgets#synctera-widgets-recommended) for new integrations. The Marqeta widgets documented in this section will continue to work during the transition period, but new integrations should use Synctera Widgets. ## Overview The legacy Marqeta widgets provide card functionality through two integration methods: 1. **Marqeta.js Library** - For displaying sensitive card data (PAN, CVV, EXP, PIN) 2. **Marqeta Widget URLs** - For card activation and PIN setting via iframes ## Documentation Step-by-step guide to migrate from Marqeta widgets to Synctera widgets Complete documentation for Marqeta.js and widget URL integrations ## Why Migrate? Synctera Widgets offer several advantages over the legacy Marqeta widgets: | Feature | Marqeta Widgets | Synctera Widgets | | -------------------- | --------------------------- | ---------------------------- | | **Integration** | iframe URLs or JS bootstrap | Web Components | | **Customization** | Limited CSS styling | Full theming + custom labels | | **Event Handling** | Callback functions | Standard DOM events | | **Token Management** | Multiple token types | Unified widget token | | **Future Support** | Being sunset | Actively maintained | ## Recommendation * **New integrations**: Use [Synctera Widgets](/v2/docs/card-widgets#synctera-widgets-recommended) * **Existing integrations**: Plan migration using the [Migration Guide](/v2/docs/card-widgets-legacy-migration) * **Reveal Card functionality**: Use [Synctera Reveal Card Widget](/v2/docs/card-widgets-reveal) # Marqeta Widgets (Deprecated) Source: https://docs.synctera.com/v2/docs/card-widgets-legacy-marqeta Legacy documentation for Marqeta.js widget integrations. Marqeta is sunsetting their Marqeta.js widget library. For new integrations, use [Synctera Widgets](/v2/docs/card-widgets#synctera-widgets-recommended). For migration guidance, see the [Migration Guide](/v2/docs/card-widgets-legacy-migration). Through the [marqeta.js client library](https://www.marqeta.com/docs/developer-guides/using-marqeta-js), you can display the following pieces of sensitive card information for a customer inside your application: * **PAN** (Primary Account Number) * **CVV** (Card Verification Value) * **EXP** (Expiration Date) * **PIN** (Personal Identification Number - *v2.0.0+*) Through the [Activate Card and Set PIN Widgets](https://www.marqeta.com/docs/developer-guides/using-activate-card-and-set-pin-widgets), you can interact with your card to activate it or to set card's PIN: * **Activate Card** (activates a physical card by entering in the card number and CVV) * **Set PIN** (sets the Card PIN for a newly activated card) *** ## Display Card PAN, CVV, and EXP Refer to Marqeta's guide [Using Marqeta.js](https://www.marqeta.com/docs/developer-guides/using-marqeta-js) for additional information on the widget configuration and styling. The steps below describe how the application uses a client access token to show PAN, CVV and Card EXP using the marqeta.js client library: ### Step 1: Load marqeta.js Load `marqeta.js` into the window object of the browser by adding the following script into the `` tag of the required page: ```html theme={"system"} ``` ### Step 2: Get a Client Access Token Request a client access token for a card from Synctera via the POST request for [/cards/\{card\_id}/client\_token](/v2/reference/getclientaccesstoken) endpoint. Pass `clientAccessToken` to your front-end via SSR or HTTP request. This token expires after five minutes and is only applicable to the given card, so it's a good idea to create a client access token on every page load: ```bash theme={"system"} curl -X POST "https://api-sandbox.synctera.com/v0/cards/{cardId}/client_token" \ -H "Content-Length: 0" \ -H "Authorization: Bearer {apiKey}" # Response: {"client_token": ... } ``` ### Step 3: Add HTML Elements Add a separate HTML `div` element to your client page per each piece of the sensitive card data (Card PAN, Card CVV, Card EXP). You can attach this information to any HTML container: ```html theme={"system"} Synctera
``` ### Step 4: Initialize marqeta.js Initialize `marqeta.js` via bootstrap with token by calling `window.marqeta.bootstrap`. It will create an HTML iframe element inside each HTML `div` element. You can style the `div` elements and inner contents for the *card PAN*, *card CVV*, *card EXP* containers. To do so, use the `showPan` object as described in [Using Marqeta.js > The showPan object](https://www.marqeta.com/docs/developer-guides/using-marqeta-js#_the_showpan_object): ```javascript theme={"system"} window.marqeta.bootstrap({ clientAccessToken: clientAccessToken, integrationType: "custom", component: { showPan: { cardPan: { domId: "display-card-pan", format: true }, cardExp: { domId: "display-card-exp", format: true }, cardCvv: { domId: "display-card-cvv" }, }, }, callbackEvents: { onSuccess: () => console.log("Widget loaded!"), onFailure: () => console.warn("Widget failed to load."), }, }); ``` ### Sequence Diagram ```mermaid theme={"system"} sequenceDiagram participant IFE as Integrator Frontend participant MFE as Marqeta.js participant IBE as Integrator Backend participant S as Synctera API participant M as Marqeta IFE ->> IBE: Request client access token IBE ->> S: POST /v0/cards/:card_id/client_token S ->> M: Get token M -->> S: Token S -->> IBE: Response with client_token IBE -->> IFE: Client access token IFE ->> MFE: Marqeta.js display card PAN, CVV, and EXP MFE ->> M: Request sensitive card data M -->> MFE: Response with sensitive card data MFE ->> MFE: Render sensitive card data ``` *** ## Display Card PIN For new integrations, use the [Synctera Reveal PIN Widget](/v2/docs/card-widgets-reveal-pin) instead. The steps below describe the deprecated Marqeta `pinReveal` flow. Loading the PIN must be done in its own call to `window.marqeta.bootstrap`, however you may call two instances simultaneously. ### Step 1: Load marqeta.js and Get Token Follow the first two steps from [Display Card PAN, CVV, and EXP](#display-card-pan-cvv-and-exp). ### Step 2: Add HTML Elements Add separate HTML elements to your client page for the card PIN. You can attach this information to any HTML container: ```html theme={"system"} Synctera
``` ### Step 3: Initialize marqeta.js for PIN Initialize `marqeta.js` via bootstrap with token by calling `window.marqeta.bootstrap`. It will create an HTML iframe element inside each HTML element. You can style the elements and inner contents for the *card PIN* containers. To do so, use the `pinReveal` object as described in [Using Marqeta.js > The pinReveal object](https://www.marqeta.com/docs/developer-guides/using-marqeta-js#_the_pinreveal_object): ```javascript theme={"system"} window.marqeta.bootstrap({ clientAccessToken: clientAccessToken, integrationType: "custom", component: { pinReveal: { cardPin: { domId: "display-card-pin" }, toggleCardPin: { domId: "toggle-card-pin", mode: "transparent" }, hidePinTimeout: { domId: "pin-timeout", hideTimeout: 10, // A value between 5 and 15 styles: {}, // Requires styles object, can be empty }, }, }, callbackEvents: { onSuccess: () => console.log("Widget loaded!"), onFailure: () => console.warn("Widget failed to load."), }, }); ``` *** ## Activate Card and Set PIN Widgets For new integrations, use the [Synctera Activate Card Widget](/v2/docs/card-widgets-activate) and [Synctera Set PIN Widget](/v2/docs/card-widgets-set-pin) instead. The **Activate Card** widget and **Set PIN** widget are displayed inside HTML iframe elements, with source URLs provided by the `/cards/card_widget_url` route. Refer to Marqeta's guide [Using Activate Card and Set PIN Widgets](https://www.marqeta.com/docs/developer-guides/using-activate-card-and-set-pin-widgets) for additional information. ### Step 1: Fetch the Widget URL On the server, make a request to `/cards/card_widget_url`. For the **Activate Card** widget (widget\_type === 'activate\_card'), you can omit the `card_id` param in the query: ```bash theme={"system"} curl -X GET "https://api-sandbox.synctera.com/v0/cards/card_widget_url?card_id={cardId}&customer_id={customerId}&account_id={accountId}&widget_type={widgetType}" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer {apiKey}" # Response: {"url": ... } ``` ### Step 2: Embed the Widget Pass the acquired URL to your front-end via SSR or HTTP request. Include the URL into an iframe on your client page. The desired widget will be rendered inside the iframe, allowing the user to input either *card PAN* or *card PIN* and press submit: ```html theme={"system"} Synctera ``` ### Retrieving the Retailer Map URL To get the URL for the retailer map, use the [GET /v2/cash/barcodes/retailer\_map\_url](/v2/reference/getretailermapurl) endpoint. You can customize the map's center using optional query parameters: * `lat`: Latitude of the map center * `lng`: Longitude of the map center # Sandbox Testing To test barcode-based cash deposits in the sandbox environment, you can use the **transaction simulation endpoints** provided. Please reach out to your Synctera Implementation Representative to get you set up in Sandbox. ## Retrieve Test Stores To get a list of stores available for testing, use the [GET /v2/cash/transaction\_simulations/barcodes/stores](/v2/reference/simulatebarcodesstores) endpoint. You can customize the response using query parameters to filter stores by location and radius. For example, retrieving stores outside the barcode's valid radius can help simulate invalid merchant locations. Supported query parameters: * `lat` *(required)*: Latitude coordinate to center the search * `lng` *(required)*: Longitude coordinate to center the search * `radius` *(optional)*: Search radius in miles * `limit` *(optional)*: Maximum number of stores to return ### Example Request ```sh Shell theme={"system"} curl \ -X GET \ $baseurl/v2/cash/transaction_simulations/barcodes/stores?lat=40.7128&lng=-74.0060&radius=15&limit=1 \ -H "Authorization: Bearer $apiKey" ``` ### Example Response ```json JSON theme={"system"} { "stores": [ { "address": { "address1": "1192 MYRTLE AVE", "city": "BROOKLYN", "country": "USA", "county": "KINGS", "state": "NY", "zip_code": "11221-2613" }, "business_name": "Dollar General", "coordinates": { "latitude": 40.697266, "longitude": -73.93116 }, "distance": 4.07, "id": "5897e7c84f3680b7934697656a12aa05" } ] } ``` ## Simulating Payments You can simulate test, apply, and void payments using the [POST /v2/cash/transaction\_simulations/barcodes/deposits](/v2/reference/simulatebarcodesdeposits) endpoint. Simulations must follow the same logical flow as real-world [point-of-sale interactions](/v2/docs/in-store-cash-deposits#point-of-sale-interaction). ### Parameters * **type** *(required)*: The payment action to simulate. Valid values are: * `TEST` — Authorizes the payment without applying it * `APPLY` — Applies the payment and posts funds to the account * **status** *(required)*: The status of the payment simulation. Valid values depend on the `type`: * For `TEST` type: * `PAID` — Authorize Payment * For `APPLY` type: * `PAID` — Apply Payment * `VOID` — Void Payment ### Example: Simulate a Test Payment ```sh Shell theme={"system"} curl \ -X POST \ $baseurl/v2/cash/transaction_simulations/barcodes/deposits \ -H "Authorization: Bearer $apiKey" \ --json '{ "amount": 100.00, "barcode_id": "01983364-ebd5-717b-9aaf-7cf91ced9ed8", "type": "TEST", "status": "PAID", "store_id": "5897e7c84f3680b7934697656a12aa05" }' ``` ### Reviewing Results After simulating a payment, review the customer account associated with the barcode to: * Verify the transaction outcome * Confirm correct fee application # Apple Pay Source: https://docs.synctera.com/v2/docs/instant-account-funding-apple-pay # Overview In addition to *Instant Account Funding* (`PULL` from card) with an external card-on-file or with Google Pay, Synctera offers *Instant Account Funding* with **Apple Pay** using an external card that the user has added to their Apple Wallet. Through this method, transactions are are securely processed with Apple Pay’s encryption and authentication features, such as Face ID or Touch ID. > 📘 > > Synctera currently only supports Apple Pay on iOS. Web based payments are planned for a future release. ## Prerequisites To perform Instant Account Funding with Apple Pay, you must first: * Create a [Customer](https://docs.synctera.com/v2/docs/create-a-personal-customer) * Create an [Account](https://docs.synctera.com/v2/docs/create-accounts-guide) for the customer * Have External Cards enabled with the help of your Synctera implementation representative * Perform the necessary steps to enable payments through Apple Pay: 1. Setup your Apple Pay environment 2. Integrate with Apple Pay to generate payment token: * Present the Apple Pay button in your app * Present the payment sheet to the customer * Receive payment token # Payment Flow 1. User selects the Apple Pay button 2. Apple Pay UI is displayed and user confirms payment 3. Apple Pay returns a payment token 4. Your application sends the token to your server 5. Your server requests a transaction with Synctera using the token 6. Synctera’s payment gateway processes the transaction 7. A response containing the transaction outcome is returned # Setup your Apple Pay environment ## Apple Pay for iOS ### 1. Register for An Apple Merchant ID 1. Log into your [Apple Developer account](https://developer.apple.com/) 2. Follow the Apple Developer Account instructions to [create a merchant identifier](https://developer.apple.com/help/account/configure-app-capabilities/configure-apple-pay#create-a-merchant-identifier). We recommend including the Synctera name and environment as a prefix when creating your identifier. For example `merchant.com.synctera-sandbox.mycompany` ### 2. Configure Your App for Apple Pay Follow the Apple Developer Account instructions to [enable apple pay](https://developer.apple.com/help/account/manage-identifiers/enable-app-capabilities#enable-apple-pay). ### 3. Create a Payment Processing Certificate 1. Call [Create an Apple Pay CSR](/v2/reference/createapplepaycsr) to create a CSR. ```bash theme={"system"} curl \ -X POST \ $baseurl/v1/certificates/applepay/csr \ -H "Authorization: Bearer $apiKey" \ --json ' { "merchant_id": "merchant.com.synctera-sandbox.mycompany", "organization_name": "My Company Inc" } ' -o ApplePay.csr ``` 2. Follow the Apple Developer Account instructions to [create a payment processing certificate](https://developer.apple.com/help/account/configure-app-capabilities/configure-apple-pay#create-a-payment-processing-certificate). When prompted to choose a file, select the CSR you created. ### 4. Renewing your Payment Processing Certificate Apple Pay requires you to renew your Payment Processing Certificate every 25 months. In order to renew your certificate, create a new Apple Pay CSR and Payment Processing certificate. Apple requires up to 4 hours to start using your new Payment Processing Certificate, during which time transactions will still continue to process successfully with your old Payment Processing Certificate. # Integrate with Apple Pay to generate payment token ## iOS ### Start a Payment ```python theme={"system"} private func startPayment() { let paymentNetworks: [PKPaymentNetwork] = [.visa, .masterCard, .amex, .discover] guard PKPaymentAuthorizationController.canMakePayments(), PKPaymentAuthorizationController.canMakePayments(usingNetworks: paymentNetworks) else { statusMessage = "Apple Pay is not available" statusColor = .red responseText = "Apple Pay is not available on this device" isCopyButtonEnabled = false return } // Create payment request let request = PKPaymentRequest() request.merchantIdentifier = merchantIdentifier request.supportedNetworks = paymentNetworks request.merchantCapabilities = [.capability3DS, .capabilityCredit, .capabilityDebit] request.countryCode = "US" request.currencyCode = "USD" // Configure for shipping and billing contact request.requiredShippingContactFields = [.postalAddress, .emailAddress, .phoneNumber, .name] request.requiredBillingContactFields = [.postalAddress, .name] // Add payment summary items let amount = NSDecimalNumber(decimal: paymentAmount) let subtotal = PKPaymentSummaryItem(label: "Subtotal", amount: amount) // Add tax (for demonstration) let taxAmount = NSDecimalNumber(decimal: paymentAmount * 0.08) // 8% tax let tax = PKPaymentSummaryItem(label: "Tax", amount: taxAmount) // Total amount let totalAmount = amount.adding(taxAmount) let total = PKPaymentSummaryItem(label: "Your Company Name", amount: totalAmount) request.paymentSummaryItems = [subtotal, tax, total] // Present Apple Pay sheet let controller = PKPaymentAuthorizationController(paymentRequest: request) controller.delegate = PaymentHandler.shared PaymentHandler.shared.completionHandler = { success, response in if success { if let jsonResponse = response { // Log to console print("=== APPLE PAY RESPONSE ===") print(jsonResponse) print("=========================") DispatchQueue.main.async { // Update status message self.statusMessage = "Payment Authorized Successfully" self.statusColor = .green // Show only the raw JSON in the text view self.responseText = jsonResponse // Enable copy button self.isCopyButtonEnabled = true } } } else { DispatchQueue.main.async { self.statusMessage = "Payment failed or was cancelled" self.statusColor = .red self.responseText = "Payment failed or was cancelled" self.isCopyButtonEnabled = false } } } controller.present { presented in if !presented { self.statusMessage = "Failed to present Apple Pay" self.statusColor = .red self.responseText = "Failed to present Apple Pay authorization controller" self.isCopyButtonEnabled = false } } } ``` ### Handle a Payment ```python theme={"system"} // Payment Handler to manage Apple Pay delegate methods class PaymentHandler: NSObject, PKPaymentAuthorizationControllerDelegate { static let shared = PaymentHandler() var completionHandler: ((Bool, String?) -> Void)? private var paymentSucceeded = false func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { // Process the payment by sending the token to your payment processor processPayment(payment) { (success, error) in if success { // Payment was processed successfully let paymentInfo = self.createPaymentInfoJSON(from: payment) completion(PKPaymentAuthorizationResult(status: .success, errors: nil)) self.paymentSucceeded = true self.completionHandler?(true, paymentInfo) } else { // Payment processing failed let errors = [error].compactMap { $0 }.map { NSError(domain: "PaymentError", code: 0, userInfo: [NSLocalizedDescriptionKey: $0]) } completion(PKPaymentAuthorizationResult(status: .failure, errors: errors)) self.paymentSucceeded = false self.completionHandler?(false, error) } } } private func processPayment(_ payment: PKPayment, completion: @escaping (Bool, String?) -> Void) { // TODO - process payment with Synctera } ``` # Use the Apple Pay payment token to initiate payment ## Server Now that you have generated an Apple Pay payment token through your app, your server may request an instant `PULL` payment using the token. Synctera’s payment gateway will then process the payment, and return the outcome to your app. Call [Create Apple Pay External Card Transfer](/v2/reference/createapplepayexternalcardtransfer) **Example request:** ```bash theme={"system"} curl \ -X POST \ $baseurl/v1/external_cards/transfers/applepay \ -H "Authorization: Bearer $apiKey" \ --json ' { "apple_pay_payment": { "token": { "payment_data": { "data": "1+aL4iT83Z7fLVZ71En6L+D1oMVNMYMBoiHPGA1Ex87WZx5ULbh/pqAVxZZCp2ePVazFRkVju8I0j73lW+lb1NINm5ZMt/WncA+0GlN4B3Wvc4YLsO4TzelEAie4OjsL0VNsTR6C383LGA2c5LQATXbqeg4Llq2wsaWMp5hDcuc8NsJ5jCLvyFDHkAFJtHdZ3k0w8s2JdY71ezgmwDnRiXSipcYCp98KRZ0GDV4T2R8NCk2nZEXixy18sy7j5mKfXSJMhcLhNBJsD8/vIugzEX7FINRidtxS9A3vyuLYeNu6rmaEL2P7XfXEa8yf0XNjWwjB8x3M2vh+JX1+ZyGFzHLHoCB8N3mpsWCeSGwNC7+y/ND0uNNN/ugprpb8cubjF5kDeJETIEw1v0XsE0180bkc8lcwO9KecczsibEXu3A=", "signature": "MIAGCSqGSIb3DQEHAqCAMIACAQExDTALBglghkgBZQMEAgEwgAYJKoZIhvcNAQcBAACggDCCA+QwggOLoAMCAQICCFnYobyq9OPNMAoGCCqGSM49BAMCMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yMTA0MjAxOTM3MDBaFw0yNjA0MTkxOTM2NTlaMGIxKDAmBgNVBAMMH2VjYy1zbXAtYnJva2VyLXNpZ25fVUM0LVNBTkRCT1gxFDASBgNVBAsMC2lPUyBTeXN0ZW1zMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIIw/avDnPdeICxQ2ZtFEuY34qkB3Wyz4LHNS1JnmPjPTr3oGiWowh5MM93OjiqWwvavoZMDRcToekQmzpUbEpWjggIRMIICDTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFCPyScRPk+TvJ+bE9ihsP6K7/S5LMEUGCCsGAQUFBwEBBDkwNzA1BggrBgEFBQcwAYYpaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwNC1hcHBsZWFpY2EzMDIwggEdBgNVHSAEggEUMIIBEDCCAQwGCSqGSIb3Y2QFATCB/jCBwwYIKwYBBQUHAgIwgbYMgbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBhbmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA2BggrBgEFBQcCARYqaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkvMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlYWljYTMuY3JsMB0GA1UdDgQWBBQCJDALmu7tRjGXpKZaKZ5CcYIcRTAOBgNVHQ8BAf8EBAMCB4AwDwYJKoZIhvdjZAYdBAIFADAKBggqhkjOPQQDAgNHADBEAiB0obMk20JJQw3TJ0xQdMSAjZofSA46hcXBNiVmMl+8owIgaTaQU6v1C1pS+fYATcWKrWxQp9YIaDeQ4Kc60B5K2YEwggLuMIICdaADAgECAghJbS+/OpjalzAKBggqhkjOPQQDAjBnMRswGQYDVQQDDBJBcHBsZSBSb290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0xNDA1MDYyMzQ2MzBaFw0yOTA1MDYyMzQ2MzBaMHoxLjAsBgNVBAMMJUFwcGxlIEFwcGxpY2F0aW9uIEludGVncmF0aW9uIENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPAXEYQZ12SF1RpeJYEHduiAou/ee65N4I38S5PhM1bVZls1riLQl3YNIk57ugj9dhfOiMt2u2ZwvsjoKYT/VEWjgfcwgfQwRgYIKwYBBQUHAQEEOjA4MDYGCCsGAQUFBzABhipodHRwOi8vb2NzcC5hcHBsZS5jb20vb2NzcDA0LWFwcGxlcm9vdGNhZzMwHQYDVR0OBBYEFCPyScRPk+TvJ+bE9ihsP6K7/S5LMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUu7DeoVgziJqkipnevr3rr9rLJKswNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5hcHBsZS5jb20vYXBwbGVyb290Y2FnMy5jcmwwDgYDVR0PAQH/BAQDAgEGMBAGCiqGSIb3Y2QGAg4EAgUAMAoGCCqGSM49BAMCA2cAMGQCMDrPcoNRFpmxhvs1w1bKYr/0F+3ZD3VNoo6+8ZyBXkK3ifiY95tZn5jVQQ2PnenC/gIwMi3VRCGwowV3bF3zODuQZ/0XfCwhbZZPxnJpghJvVPh6fRuZy5sJiSFhBpkPCZIdAAAxggGIMIIBhAIBATCBhjB6MS4wLAYDVQQDDCVBcHBsZSBBcHBsaWNhdGlvbiBJbnRlZ3JhdGlvbiBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMCCFnYobyq9OPNMAsGCWCGSAFlAwQCAaCBkzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNTAzMTQyMTIzNTVaMCgGCSqGSIb3DQEJNDEbMBkwCwYJYIZIAWUDBAIBoQoGCCqGSM49BAMCMC8GCSqGSIb3DQEJBDEiBCAJJVC4rYEf7EP+BNcN/fHsCcyQn5dNROOg3k1g3Ko4KDAKBggqhkjOPQQDAgRHMEUCIQDqv3/LJxrl3sPYbX3cJNXwiFg6F3yoX8amQpioPayoqgIgDRbhb1oM1ebJQM4mYN4chQvYX0ex0k9h8YhsLrd4mdAAAAAAAAA=", "header": { "public_key_hash": "dwXh9g8mdIhEFW8Fou4AsxiZK2weLfWX+ejRw1wNNbw=", "ephemeral_public_key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh6XRGF+UAjnlpVjeyU0EAUuZKDLPYehmokRjK4umV2zFp+w2l5rI7TnXk9x02i7NYQwVvk2M4Pj39vBjyWamOw==", "transaction_id": "90fe8430e36fb9b50d1f9aaacdd2a0227fc31e03a5342d34f460bd56b94cf50d" }, "version": "EC_v1" }, "payment_method": { "network": "Visa", "display_name": "Visa 0121", "type": "credit" }, "transaction_identifier": "90fe8430e36fb9b50d1f9aaacdd2a0227fc31e03a5342d34f460bd56b94cf50d" } }, "originating_account_id": "0195a5cf-e6b7-7827-bf59-b613dc55e6d3", "customer_id": "0195a5d0-4bed-77a3-a279-48221ca200da", "amount": 1080 } ' ``` **Example response:** ```json theme={"system"} { "account_id": "0195a5cf-e6b7-7827-bf59-b613dc55e6d3", "amount": 1080, "creation_time": "2025-03-14T21:26:02.83391Z", "currency": "USD", "customer_id": "0195a5d0-4bed-77a3-a279-48221ca200da", "id": "0195a5d0-834d-7ea1-b85f-cf20a13fd54e", "last_updated_time": "2025-03-14T21:26:04.614801Z", "merchant": { "address": { "address_line_1": "47 Simpson Avenue", "city": "Shippensberg", "country_code": "US", "postal_code": "17257", "state": "PA" }, "email": "funtech@email.com", "name": "FunTech", "phone_number": "+18013570346" }, "status": "SUCCEEDED", "tenant": "kepkep_pgnwwy", "transaction_id": "0195a5d1-63fe-76f9-81a9-71374e1d30e3", "card_details": { "address_verification_result": "VERIFIED", "cvv2_result": "NOT_SUPPORTED", "name_verification_result": "NOT_VERIFIED", "pull_details": { "network": "Visa" }, "pull_enabled": true, "push_enabled": false, "bin": "481852", "issuer": "", "last_four": "6602", "payment_account_reference": "V0010013022073812195104906324" }, "type": "APPLE_PAY_PULL" } ``` The `status` field of the response indicates the outcome of the transaction: * `SUCCEEDED`: The transaction was successful and funds are available - *terminal* status * `DECLINED`: The transaction could not be completed due to a specific rule (e.g. low balance or velocity control) - *terminal* status * `CANCELED`: The transaction could not be completed due to error (e.g. upstream processing error) - *terminal* status * `UNKNOWN`: The transaction status is indeterminate - *non-terminal* status * `PENDING`: The transaction has been initialized - *non-terminal* status ## Sandbox Testing The following Apple [sandbox test cards](https://developer.apple.com/apple-pay/sandbox-testing/) are supported for transaction testing. | Card Type | Card number | Success | Notes | | ----------- | ------------------- | ------- | -------- | | Visa Credit | 4051 0693 0220 0121 | Y | | | Visa Credit | 4761 2297 0015 0465 | Y | | | Mastercard | 5204 2452 5046 0049 | N | Fail AVS | | Mastercard | 5204 2452 5052 2095 | N | Fail AVS | # Google Pay Source: https://docs.synctera.com/v2/docs/instant-account-funding-google-pay # Overview In addition to *Instant Account Funding* (`PULL` from card) with an external card-on-file or with Apple Pay, Synctera offers *Instant Account Funding* with **Google Pay** using an external card that the user has added to their Google Wallet. Through this method, transactions are are securely processed with Google Pay’s encryption and authentication features, such as Face ID or Touch ID. > 📘 > > While this guide focuses on web implementation, the conceptual framework applies similarly to Android. ## Prerequisites To perform Instant Account Funding with Google Pay, you must first: * Create a [Customer](https://docs.synctera.com/v2/docs/create-a-personal-customer) * Create an [Account](https://docs.synctera.com/v2/docs/create-accounts-guide) for the customer * Have External Cards enabled with the help of your Synctera implementation representative * Perform the necessary steps to enable payments through Google Pay: 1. Setup your Google Pay environment 2. Integrate with Google Pay to generate payment token: * Present the Google Pay button in your app * Present the payment sheet to the customer * Receive payment token # Payment Flow 1. User selects the Google Pay button 2. Google Pay UI is displayed and user confirms payment 3. Google Pay returns a payment token 4. Your application sends the token to your server 5. Your server requests a transaction with Synctera using the token 6. Synctera’s payment gateway processes the transaction 7. A response containing the transaction outcome is returned See: * [Google Pay on the web](https://developers.google.com/pay/api/web/overview) * [Google Pay on Android](https://developers.google.com/pay/api/android/overview) # Set up your Google Pay environment ### 1. Set up a Google Pay merchant account To enable account funding through Google Pay, you need to set up Google Pay for Business. Please follow [these instructions](https://support.google.com/pay/business/answer/7530745?hl=en\&sjid=4969552680814067223-NC\&visit_id=638906316360409915-1561160066\&ref_topic=7684388\&rd=1). > 📘 > > A Google Pay merchant account is not required for `TEST` environment # Integrate with Google Pay to generate payment token ### 1. Include the Google Pay API JavaScript ```javascript theme={"system"} ``` ### 2. Define payment configuration ```java theme={"system"} const baseRequest = { apiVersion: 2, apiVersionMinor: 0 }; const allowedCardNetworks = [ "MASTERCARD", "VISA" ]; const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"]; const tokenizationSpecification = { type: 'PAYMENT_GATEWAY', parameters: { 'gateway': 'tabapay', 'gatewayMerchantId': '{{gateway merchant ID}}' } }; const baseCardPaymentMethod = { type: 'CARD', parameters: { allowedAuthMethods: allowedCardAuthMethods, allowedCardNetworks: allowedCardNetworks } }; const cardPaymentMethod = Object.assign( {tokenizationSpecification: tokenizationSpecification}, baseCardPaymentMethod ); const paymentRequest = Object.assign({}, baseRequest); paymentRequest.allowedPaymentMethods = [cardPaymentMethod]; paymentRequest.transactionInfo = { totalPriceStatus: 'FINAL', totalPrice: '123.45', currencyCode: 'USD', countryCode: 'US' }; paymentRequest.merchantInfo = { merchantName: 'Example Merchant', // your merchant Name merchantId: '12345678901234567890' // your Google merchant ID }; ``` `allowedCardNetworks`: Specify `VISA` and `MASTERCARD` `allowedCardAuthMethods`: Specify both `PAN_ONLY` and `CRYPTOGRAM_3DS` `tokenizationSpecification`: * `gateway`: Specify `tabapay` * `gatewayMerchantID`: Obtain from your Synctera Implementation representative ### 3. Display the Google Pay button ```java theme={"system"} const paymentsClient = new google.payments.api.PaymentsClient({ environment: 'TEST' // Use 'PRODUCTION' when going live }); function checkGooglePayAvailability() { const isReadyToPayRequest = Object.assign({}, baseRequest); isReadyToPayRequest.allowedPaymentMethods = [baseCardPaymentMethod]; paymentsClient.isReadyToPay(isReadyToPayRequest) .then(function(response) { if (response.result) { // Google Pay is available - display the button createAndAddButton(); } }) .catch(function(err) { console.error("Google Pay availability check error:", err); }); } function createAndAddButton() { const button = paymentsClient.createButton({ onClick: onGooglePayButtonClicked, buttonColor: 'black', // 'black' or 'white' buttonType: 'buy' }); document.getElementById('googlePayButtonContainer').appendChild(button); } function onGooglePayButtonClicked() { paymentsClient.loadPaymentData(paymentRequest) .then(function(paymentData) { // Process payment data processPayment(paymentData); }) .catch(function(err) { console.error("Payment processing error:", err); }); } ``` ### 4. Process the Payment ```java theme={"system"} function processPayment(paymentData) { // Send the payment token to your server // The payment token is in paymentData.paymentMethodData.tokenizationData.token fetch('/your-payment-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ paymentToken: paymentData.paymentMethodData.tokenizationData.token }) }) .then(response => response.json()) .then(data => { // Handle successful payment console.log('Payment successful:', data); displayPaymentSuccess(); }) .catch(error => { // Handle payment errors console.error('Payment failed:', error); displayPaymentError(); }); } ``` When a user confirms payment through the Google Pay interface, your application receives an encrypted payment token containing the user's payment credentials. Your client-side code must transmit this token to your server, which then communicates to Synctera’s payment gateway. See next step. # Use the Google Pay payment token to initiate payment Now that you have generated an Google Pay payment token through your app, your server may request an instant `PULL` payment using the token. Synctera’s payment gateway will then process the payment, and return the outcome to your app. Call [Create Google Pay External Card Transfer](/v2/reference/creategooglepayexternalcardtransfer) **Example request:** ```bash theme={"system"} curl \\ $baseurl/v1/external_cards/transfers/googlepay \\ -H "Authorization: Bearer $apikey" \\ -H 'Content-Type: application/json' \\ -d ' { "type": "GOOGLE_PAY_PULL", "originating_account_id": "{{account_id}}", "customer_id": "{{customer_id}}", "amount": 100, "google_pay_payment_data": { "api_version": 2, "api_version_minor": 0, "payment_method_data": { "payment_type": "CARD", "description": "Visa **** 1234", "info": { "card_details": "1234", "assurance_details": { "account_verified": true, "cardholder_authenticated": true }, "card_network": "VISA", "billing_address": { "name": "Name", "postal_code": "12345", "country_code": "US", "phone_number": "555-555-5555", "address_1": "123 Main St", "address_2": "Apt 4B", "address_3": "", "locality": "Anytown", "administrative_area": "CA", "sorting_code": "12345" } }, "tokenization_data": { "tokenization_type": "PAYMENT_GATEWAY", "token": "{\\"signature\\":\\"MEUCIExS6cx4CagjV......" } } } }' ``` `google_pay_payment_data` is populated from `paymentData` received from Google. Note that the encrypted payment token (`paymentData.paymentMethodData.tokenizationData.token`) must not be altered and passed exactly as is. **Example response:** ```json theme={"system"} { "account_id": "41762865-46a8-4b02-a6c4-40f909ae5847", "amount": 11, "creation_time": "2025-02-26T21:41:21.163735Z", "currency": "USD", "customer_id": "453101fc-2f42-4aa6-bb84-2acdba064e5c", "id": "16980c03-022b-4cf9-90f6-742271132a2a", "last_updated_time": "2025-02-26T21:41:22.612429Z", "merchant": { "address": { "address_line_1": "123 Elm St", "city": "San Diego", "country_code": "US", "postal_code": "92101", "state": "CA" }, "email": "operations@myfintech.com", "name": "My Fintech", "phone_number": "+18582281234" }, "status": "SUCCEEDED", "tenant": "lxpzvp_doyjzy", "transaction_id": "0edc0511-ed8d-4bef-83dd-aea8901aa51f", "card_details": { "address_verification_result": "VERIFIED", "cvv2_result": "NOT_SUPPORTED", "name_verification_result": "NOT_VERIFIED", "pull_details": { "country": "US", "currency": "USD", "network": "Visa", "product_type": "CREDIT", "regulated": true }, "pull_enabled": true, "push_details": { "country": "US", "currency": "USD", "funds_availability": "NOW", "network": "Visa", "product_type": "CREDIT", "regulated": true }, "push_enabled": true, "bin": "411111", "issuer": "FORD Instiution", "last_four": "1111", "payment_account_reference": "V0010013022073812195104907179" }, "type": "GOOGLE_PAY_PULL" } ``` The `status` field of the response indicates the outcome of the transaction: * `SUCCEEDED`: The transaction was successful and funds are available - *terminal* status * `DECLINED`: The transaction could not be completed due to a specific rule (e.g. low balance or velocity control) - *terminal* status * `CANCELED`: The transaction could not be completed due to error (e.g. upstream processing error) - *terminal* status * `UNKNOWN`: The transaction status is indeterminate - *non-terminal* status * `PENDING`: The transaction has been initialized - *non-terminal* status # Sandbox Testing * Use the `TEST` environment for development * Google provides [test cards](https://developers.google.com/pay/api/android/guides/resources/test-card-suite) for different scenarios # Card-On-File Source: https://docs.synctera.com/v2/docs/instant-payments-card-on-file # Overview For External Cards-On-File, Synctera supports **Instant Payments**. An instant payment can be either: * a `PULL` from an external card to fund an account on the Synctera platform or * a `PUSH` or a payout from an account on the Synctera platform to an external card For more details on supported scenarios, see External Cards. ## Prerequisites To create an external card-on-file payment, you must first: * Create a [Customer](https://docs.synctera.com/v2/docs/create-a-personal-customer) * Create an [Account](https://docs.synctera.com/v2/docs/create-accounts-guide) for the customer * Have External Cards enabled with the help of your Synctera implementation representative * Tokenize card * Add card-on-file using card token * Enable 3-D Secure (3DS) authentication (`PULL` payments only) # Enable 3-D Secure (3DS) Authentication For additional security, Synctera External Cards supports 3-D Secure (3DS) authentication, a globally accepted authentication solution designed to increase security, reduce fraud and reduce chargebacks for e-commerce payments. 3DS operates at the per transaction level in real time at time of payment. Additional information about 3DS can be found [here](https://www.emvco.com/emv-technologies/3-d-secure/). Synctera's 3DS provider is [Cardinal Commerce](https://www.cardinalcommerce.com/), facilitated through [TabaPay](https://tabapay.com/). 3DS is only required for `PULL` transactions. ## Implementation An implemention of External Cards 3DS authentication consists of **frontend** and **backend** components. The **backend** is responsible for interacting with Synctera's three 3DS endpoints: [Initialize 3DS](/v2/reference/initialize3ds), [Lookup 3DS](/v2/reference/lookup3ds) and [Authenticate 3DS](/v2/reference/authenticate3ds). The **frontend** is responsible for performing **Device Data Collection (DDC)** and (if necessary) presenting the cardholder with the **3DS Challenge**. **Device Data Collection (DDC)**: A process which collects and sends details about the cardholder's physical device being used to complete the payment. It is sometimes the case that DDC is all that is required for a successful authentication. This is called a *frictionless* authentication. **3DS Challenge**: If DDC is not enough to authenticate the cardholder, the card issuer may require a *challenge*, also known as a *step up*. This is a dynamic prompt which the cardholder must interact with to complete successfully in order to help prove they are the true card owner. The content and structure of the challenge varies and is determined by the issuer. For example, the cardholder may be required to provide a one time password (OTP) obtained through a separate channel. ### Frontend Implementation This guide contains information about how to implement and execute the necessary 3DS frontend components, including code snippets for a *browser* implementation: `BROWSER` passed for `device_channel` of [Lookup 3DS](/v2/reference/lookup3ds) ([step 3](#3-lookup-3ds)). For a *mobile app* (`SDK`) implementation, please refer to our vendor's [documentation](https://developers.tabapay.com/reference/how-to-use-the-3ds-sdk-starter-guide) for how to obtain and implement the 3DS SDK, provided by [JFrog](https://jfrog.com/). Your Synctera implementation and onboarding will provide you with JFrog credentials. In order to perform the frontend processes, the Cardinal script must be loaded into the browser document according to environment: * Production: [https://songbird.cardinalcommerce.com/edge/v1/songbird.js](https://songbird.cardinalcommerce.com/edge/v1/songbird.js) * Staging: [https://songbirdstag.cardinalcommerce.com/edge/v1/songbird.js](https://songbirdstag.cardinalcommerce.com/edge/v1/songbird.js) Code snippet: ```javascript theme={"system"} // Ensure any previous Cardinal instance is removed from the document. // After being used once, the Cardinal library cannot be reused. delete window.Cardinal; ​ const headElement = document.getElementsByTagName('head')[0]; const songbirdScriptElement = document.createElement('script'); songbirdScriptElement.async = true; songbirdScriptElement.type = 'text/javascript'; songbirdScriptElement.onload = () => { if (window.Cardinal) { // SUCCESS } else { // FAILURE } }; songbirdScriptElement.onerror = () => undefined; // FAILURE songbirdScriptElement.src = SONGBIRD_LIBRARY_URL; ​ setTimeout(() => undefined, 5000); // FAILURE ``` If you would like debug information output by the Cardinal library, you can add this: ```javascript theme={"system"} window.Cardinal.configure({ logging: { level: 'on' }, }); ``` ## Flow The entire flow of a 3DS authentication looks like this: 1. (**backend**) Initialize the 3DS authentication with [Initialize 3DS](/v2/reference/initialize3ds) 2. (**frontend**) Perform [Device Data Collection (DDC)](#2-device-data-collection-ddc) 3. (**backend**) Call [Lookup 3DS](/v2/reference/lookup3ds) 4. (**frontend**) Depending on Lookup 3DS results, present [3DS Challenge](#4-3ds-challenge) to cardholder 5. (**backend**) Validate 3DS Challenge results with [Authenticate 3DS](/v2/reference/authenticate3ds) 6. (**backend**) Attach successful 3DS authentication to External Card transaction Note that results of [step 3](#3-lookup-3ds) dictate whether [step 4](#4-3ds-challenge) and [step 5](#5-authenticate-3ds) are necessary, or if you may proceed directly to [step 6](#6-attach-to-external-card-transaction). Continue reading for complete details about each step. ## 1. Initialize 3DS To begin a 3DS authentication, first call [Initialize 3DS](/v2/reference/initialize3ds), specifying the `external_card_id`, `amount`, and `currency`. If successful, `device_data_collection_jwt` and `device_data_collection_url` will be returned (used in [step 2](#2-device-data-collection-ddc)), and `id`, used in all subsequent 3DS calls. The JWT will expire in 2 hours, so DDC must be used before then. **Example request:** ```shell theme={"system"} curl \ $baseurl/v0/external_cards/initialize_3ds \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "external_card_id": "{EXTERNAL_CARD_ID}", "amount": 1500, "currency": "USD" }' ``` **Example response:** ```json theme={"system"} { "device_data_collection_jwt": "{DDC_JWT}", "device_data_collection_url": "{DDC_URL}", "id": "{3DS_ID}" } ``` ## 2. Device Data Collection (DDC) Using `{DDC_JWT}`, obtained from the previous step, perform DDC with the Cardinal library. This is a background process that does not require any user interaction. Only proceed to the next step once the process completes successfully. Code snippet: ```javascript theme={"system"} // listen for DDC Process completion window.Cardinal.on('payments.setupComplete', (setupCompleteData) => { // finished - ready to proceed }); ​ // initialize Cardinal DDC process window.Cardinal.setup('init', { jwt: '{DDC_JWT}' }); ​ setTimeout(() => undefined, 5000); // FAILURE ``` For additional information, please refer to our vendor's [documentation](https://developers.tabapay.com/reference/device-data-collection). ## 3. Lookup 3DS Upon completion of DDC, the next step is to call [Lookup 3DS](/v2/reference/lookup3ds). `device_channel` must be set according to your 3DS [frontend implementation](#frontend-implementation): `SDK` for *mobile app*, or `BROWSER` for mobile or desktop internet *browser*. If the device channel is `BROWSER`, you can optionally provide `device_details`. This is a set of device data (collected separately by you) to be used as a fallback in case there is an issue with DDC. For `authentication_indicator`, select the options that best reflect the type of transaction being performed. For `transaction_mode`, select the correct device type. > 📘 > > To detect the `transaction_mode`, you can use [UAParser.js](https://www.npmjs.com/package/ua-parser-js): > > ```javascript theme={"system"} > import UAParser from 'ua-parser-js'; > const ua = new UAParser(); > const { type: deviceType } = ua.getDevice(); > const transactionMode = deviceType === 'mobile' > ? "MOBILE_DEVICE" > : deviceType === 'tablet' > ? "TABLET_DEVICE" > : "COMPUTER_DEVICE"; > ``` `status` from the response indicates the outcome: * `SUCCESS`: The cardholder was successfully authenticated - proceed to [step 6](#6-attach-to-external-card-transaction) * `FAILED`: The cardholder failed authentication * `CHALLENGE_REQUIRED`: A challenge is required to complete authentication - proceed to [step 4](#4-3ds-challenge) * `NOT_ENROLLED`: The card provider does not support 3DS, so authentication cannot be completed * `UNKNOWN`: An indiscriminate error occured with the 3DS authentication and it cannot be completed If `CHALLENGE_REQUIRED` status is returned, `processor_transaction_id`, `challenge_url` and `challenge_payload` will also be returned, which are needed to perform the 3DS challenge in the next step. **Example request:** ```shell theme={"system"} curl \ $baseurl/v0/external_cards/lookup_3ds \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "id": "{3DS_ID}", "authentication_indicator": "PAYMENT", "transaction_mode": "COMPUTER_DEVICE", "device_channel": "BROWSER" }' ``` **Example response (success):** ```json theme={"system"} { "id": "{3DS_ID}", "status": "SUCCESS" } ``` **Example response (challenge):** ```json theme={"system"} { "challenge_payload": "{CHALLENGE_PAYLOAD}", "challenge_url": "{CHALLENGE_URL}", "id": "{3DS_ID}", "processor_transaction_id": "{PROCESSOR_TRANSACTION_ID}", "status": "CHALLENGE_REQUIRED" } ``` ## 4. 3DS Challenge To trigger the challenge, `{CHALLENGE_URL}`, `{CHALLENGE_PAYLOAD}` and `{PROCESSOR_TRANSACTION_ID}` are required, obtained from the previous step. Once triggered, a modal window will be displayed containing the challenge for the user to complete. They have 10 minutes to complete the challenge before timing out. Use an event listener to handle the various challenge results upon completion: | Result | Description | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SUCCESS` | The challenge was completed successfully. | | `NOACTION` | There was no service level error, but authentication was not applicable. If `challengeJwt` is returned, you may proceed to [step 5](#5-authenticate-3ds), but note that it may still result in a failure. | | `FAILURE` | The user failed the challenge. | | `CANCEL` | The challenge was canceled by the user. | | `ERROR` | An error was encountered while completing the challenge. | | `TIMEOUT` | The challenged timed out. | Any result except `SUCCESS` or `NOACTION` should be treated as a failure. Assuming a successful outcome, retain `challengeJwt` for performing [Authenticate 3DS](/v2/reference/authenticate3ds) ([step 5](#5-authenticate-3ds)). This must be performed within 2 hours or else the JWT will expire. Code snippet: ```javascript theme={"system"} // event listener, triggered once the challenged is complete/cancelled (or error) window.Cardinal.on('payments.validated', (data, challengeJwt) => { switch (data.ActionCode) { case 'SUCCESS': return challengeJwt // SUCCESS case 'NOACTION': return challengeJwt || undefined // SUCCESS OR FAILURE case 'FAILURE': return // FAILURE case 'CANCEL': return // FAILURE case 'ERROR': return // FAILURE case 'TIMEOUT': return // FAILURE default: return // FAILURE } return undefined; }); ​ // trigger the challenge window.Cardinal.continue( 'cca', { AcsUrl: "{CHALLENGE_URL}", Payload: "{CHALLENGE_PAYLOAD}" }, { OrderDetails: { TransactionId: "{PROCESSOR_TRANSACTION_ID}" }, }, ); ``` ## 5. Authenticate 3DS Assuming a positive result from the challenge, the last thing to do before the 3DS authentication is complete is to call [Authenticate 3DS](/v2/reference/authenticate3ds). You must provide `challenge_jwt`, obtained from the challenge. **Example request:** ```shell theme={"system"} curl \ $baseurl/v0/external_cards/authenticate_3ds \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "id": "{3DS_ID}", "challenge_jwt": "{CHALLENGE_JWT}" }' ``` **Example respons**e: ```json theme={"system"} { "id": "{3DS_ID}", "status": "SUCCESS" }' ``` ## 6. Attach to External Card Transaction Finally, once you have a successful 3DS authentication, you must provide the `id_3ds` in the transaction request. A successful authentication must be used within 90 days before expiring. **Example request:** ```bash theme={"system"} curl \ $baseurl/v0/external_cards/transfers \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "external_card_id": "{EXTERNAL_CARD_ID}", "originating_account_id": "{ACCOUNT_ID}", "currency": "USD", "type": "PULL", "amount": 1500, "3ds_id": "{3DS_ID}", }' ``` ## Sandbox Testing - 3DS For testing purposes, refer to this [list of test PANs](https://developers.tabapay.com/reference/3ds-test-cases-and-cards) from our vendor that can be used to test various 3DS scenarios in the sandbox environment. See [External Cards guide](/v2/docs/external-cards) for information about how to create an External Card. # Create External Card-On-File Payment Once an External Card has been tokenized and added on file, it may be used to perform transactions. An `account_id` must be provided, which refers to the Synctera Account that the funds will flow into or out from, depending on the type of transaction. The `merchant` object contains merchant descriptor information that will be shown on financial statements and transaction details. If not provided, default information, defined during onboarding, is used. **Example request:** ```bash theme={"system"} curl \ $baseurl/v0/external_cards/transfers \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "external_card_id": "{EXTERNAL_CARD_ID}", "originating_account_id": "{ACCOUNT_ID}", "currency": "USD", "type": "PULL", "amount": 2500, "merchant": { "name": "Jane Taylor’s Pub", "address": { "address_line_1": "4455 Vine Street", "city": "Lake Forest", "state": "IL", "postal_code": "60045", "country_code": "US" }, "email": "janetaylorspub@email.com" } }' ``` **Example response:** ```json theme={"system"} { "account_id": "{ACCOUNT_ID}", "amount": 2500, "country_code": "US", "created_time": "2023-01-18T17:37:59.449877-05:00", "currency": "USD", "customer_id": "{CUSTOMER_ID}", "external_card_id": "{EXTERNAL_CARD_ID}", "id": "{EXTERNAL_CARD_TRANSFER_ID}", "last_modified_time": "2023-01-18T17:37:59.449877-05:00", "merchant": { "name": "Jane Taylor’s Pub", "address": { "address_line_1": "4455 Vine Street", "city": "Lake Forest", "state": "IL", "postal_code": "60045", "country_code": "US" }, "email": "janetaylorspub@email.com" }, "status": "SUCCEEDED", "transaction_id": "{TRANSACTION_ID}", "type": "PULL" } ``` The `status` field of the response indicates the outcome of the transaction: * `SUCCEEDED`: The transaction was successful and funds are available - *terminal* status * `DECLINED`: The transaction could not be completed due to a specific rule, e.g. low balance or velocity control - *terminal* status * `CANCELED`: The transaction could not be completed due to error, e.g. upstream processing error - *terminal* status * `UNKNOWN`: The transaction status is indeterminate - *non-terminal* status * `PENDING`: The transaction has been initialized - *non-terminal* status For the *non-terminal* status, you can subscribe to the `EXTERNAL_CARD_TRANSFER.UPDATED` webhook to be notified of status change, or simply [Get External Card Transfer](/v2/reference/getexternalcardtransfer) at a later time. Once a transaction is in a *terminal* status, it will not change. `transaction_id` can be used to look up the transaction using the [Transactions API](/v2/reference/listpostedtransactions). **3DS Response:** If you receive the following response, it means 3-D Secure is required for this transaction and `three_ds_id` must be provided. See the previous section for more information. Note that this is only applicable to `PULL` transactions. ```json theme={"system"} { "code": "EXTERNAL_CARD_TRANSFER_3DS_REQUIRED", "detail": "3-D Secure authorization required for this external card transfer", "status": 422, "title": "Rule Violation", "type": "https://dev.synctera.com/errors/rule-violation" } ``` ## Me-to-You PUSH Transactions In the typical case, the originating Account and the External Card are assumed to be owned by the same Person (**me-to-me** transaction). However, it's also possible to initiate a (`PUSH` only) transaction to an External Card owned by Person who is not the originating Account owner (**me-to-you** transaction). In this scenario, `originating_customer_id` is supplied with the Person who owns the originating Account. Note that an approval is required for this use case as it requires an MSB licence - see here. **Example request:** ```bash theme={"system"} curl \ $baseurl/v0/external_cards/transfers \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "external_card_id": "{EXTERNAL_CARD_ID}", "originating_customer_id": "{CUSTOMER_ID}": "originating_account_id": "{ACCOUNT_ID}", "currency": "USD", "type": "PULL", "amount": 1000, }' ``` # Reverse External Card Transaction Reversals can only be applied to `PULL` transactions. The full or partial amount may be reversed. However, only one partial reversal may be applied to a single transaction. **Example request:** ```shell theme={"system"} curl \ $baseurl/v0/external_cards/transfers/{EXTERNAL_CARD_TRANSFER_ID}/reversals \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "currency": "USD", "amount": 2500 }' ``` **Example response:** ```json theme={"system"} { "account_id": "{ACCOUNT_ID}", "amount": 2500, "country_code": "US", "created_time": "2023-01-18T17:53:12.52114-05:00", "currency": "USD", "customer_id": "{CUSTOMER_ID}", "external_card_id": "{EXTERNAL_CARD_ID}", "id": "{EXTERNAL_CARD_TRANSFER_REVERSAL_ID}", "last_modified_time": "2023-01-18T17:53:12.52114-05:00", "merchant": { "name": "Jane Taylor’s Pub", "address": { "address_line_1": "4455 Vine Street", "city": "Lake Forest", "state": "IL", "postal_code": "60045", "country_code": "US" }, "email": "janetaylorspub@email.com" }, "status": "SUCCEEDED", "transaction_id": "{TRANSACTION_ID}", "type": "PULL_REVERSAL" } ``` # Sandbox Testing The following card PANs can be used in sandbox environment for testing various scenarios: | Network | PAN | Push Enabled | Pull Enabled | Type | | ---------- | ---------------- | ------------ | ------------ | ------- | | Visa | 4005519200000004 | Y | Y | Debit | | Visa | 4217651111111119 | Y | N | Debit | | Visa | 4111111111111111 | Y | Y | Credit | | Mastercard | 2223000048400011 | N | Y | Debit | | Mastercard | 5105105105105100 | N | N | PrePaid | > ⚠️ > > Be aware that while testing in the sandbox environment, `amount` values `1`, `1100`, `2`, `1200`, `3`, `1300`, `4` and `1400` are special values reserved for generating upstream processor errors. They can be used in any [Create External Card Transfer](/v2/reference/createexternalcardtransfer) request to force an error to occur. # Interest Source: https://docs.synctera.com/v2/docs/interest-guide Interest accruing accounts are configured using the `interest_product_id` set on the account or account template. This Guide expands on: * Daily interest accrual for **deposit accounts** (for example, high‑yield savings). * How to create an **INTEREST account product** (interest product). * How and when interest is **paid out** (deposits) or **charged** (credit). ## Interest Calculation Using Account Product You can use the [Accounts Guide](/v2/docs/create-accounts-guide) to create and manage accounts. This guide will expand on details of daily interest accrual for savings accounts, show how to create an account product and how payouts occur. Throughout this guide, all units of money will be in cents and interest rate will be expressed in Basis points or BPS. 1% equals a 100 BPS. * **Interest products** are defined via the **Accounts Products** API (`product_type = "INTEREST"`). * **Account templates** can reference an `interest_product_id`; any account created from that template inherits the interest configuration. * Only **interest‑bearing accounts** need an `interest_product_id`. If omitted, **no interest is calculated** for that account. ### Create Account Product An account product is a set of attributes that define how interest is calculate for accounts and how often it is posted to the accounts. The account product resource acts as a profile that can apply to multiple accounts. Changes to the account product affects all accounts that reference it. Only interest-bearing accounts need to reference an account product. Using an account product is optional. If no account product is specified when creating the account, no interest will be calculated. To create an interest product\_type, use [POST /v2/accounts/products](/v2/reference/createaccountresourceproduct). Specify how you want the interest calculated (e.g. `COMPOUNDED_MONTHLY`), accrued (e.g. `DAILY`) and paid (e.g. `MONTHLY`). You can specify that the interest rate varies over time by including multiple periods with different rates. The rate is specified using basis points (bps), i.e. `125` represents 1.25%. #### Accrual Payout Schedule This parameter configures the frequency at which Interest is paid out to a savings account. It can be set to Monthly. The API allows you to set the schedule to "None". Obviously, interest is not paid to the account holder. The "None" value is mostly used for "scenario analysis" or calculating "projected" interest. For Line of Credit, please configure this value to "Monthly" #### Calculation\_Method This parameter allows you to specify the frequency of compounding the interest. COMPOUNDED\_MONTHLY, COMPOUNDED\_DAILY. Monthly compounding would enable the interest to be calculated on the account-balance as-of the last day of the monthly billing cycle. Daily compounding enables interest to added to the end-of-day balance. Line of Credit mostly charge interest with Daily compounding. #### Description Please enter a `description` that makes it easier to identify this interest rate. ### Rates This sub-object allows you to add rates for various durations. The configuration it needs are ##### **Accrual Period** Please select "Daily" for this field. ##### **Rate** Interest rate on an annual basis, expressed in basis points or BPS. 425 would reflect 4.25% and 1699 would reflect 16.99% ##### **Valid From & Valid To** These are dates during which this interest rate would apply. Please note that date ranges must be continuous, and that gaps and overlapping dates are not permitted. #### Example ```shell Shell theme={"system"} curl \ -X POST \ $baseurl/v0/accounts/products \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ --data-binary ' { "product_type": "INTEREST", "description": "Sample interest request body", "calculation_method": "COMPOUNDED_MONTHLY", "accrual_payout_schedule": "MONTHLY", "rates": [ { "valid_from": "2021-06-15", "rate": 100, "accrual_period": "DAILY" }, { "valid_from": "2021-06-01", "valid_to": "2021-06-15", "rate": 100, "accrual_period": "DAILY" } ] }' ``` This will return a response with the created account product, e.g.: ```json JSON theme={"system"} { "accrual_payout_schedule": "MONTHLY", "calculation_method": "COMPOUNDED_MONTHLY", "description": "Sample interest request body", "id": "52c80838-90b3-4afb-b3ff-98a97b5df96b", "product_type": "INTEREST", "rates": [ { "accrual_period": "DAILY", "rate": 100, "valid_from": "2021-06-01", "valid_to": "2021-06-15" }, { "accrual_period": "DAILY", "rate": 100, "valid_from": "2021-06-15" } ] } ``` ### Calculation method settings The `calculation_method` property determines how interest will be calculated against the account balance. There are currently two options available: * `COMPOUNDED_MONTHLY`: Interest is summed up once per month, at the end of the billing period. At no point during the billing period is the accrued interest factored into the account balance when calculating interest under this setting. * `COMPOUNDED_DAILY`: Interest is summed up every day of the billing period. The previous day's sum is applied to the next day's balance for the purpose of interest calculation. The following matrix outlines which options are currently available for each account type: | | `COMPOUNDED_MONTHLY` | `COMPOUNDED_DAILY` | | ---------------- | --------------------- | --------------------- | | `CHECKING` | | | | `SAVING` | | | | `LINE_OF_CREDIT` | | | | `CHARGE_SECURED` | | | ### Interest Calculation Interest is calculated daily for every account configured with an interest product id at the end of the banking day specific to every bank and is based on the rate (in basis points) configured on the interest account product associated with the account. For example: For account A, the interest rate is 125 basis points (1.25%); the end of day balance on the account is \$50,000 and the date is 2022-06-02. We use 365, the number of days in a calendar year to calculate the daily rate (use 366 days for leap years) daily interest rate = (125 / 100) / 365 interest accrued = 50000 \* daily interest rate Each day's interest accrual would be truncated to 8 decimal places ## Monthly Payout On the last calendar day of the end of every month (special rules are explained further down), when the daily interest calculation is done, the entire month's interest accruals are summed up and paid out to the customer's account, if `MONTHLY` is selected in the interest product for `accrual_payout_schedule`. If `NONE` is selected, the interest will be summed but not paid out into the customer's account, this is used if a fintech wants to have book keeping on the interest accued each day through the daily reports but want to handle the actual payout themselves or just show the potential in interest earnings. Monthly payout is rounded to the nearest cent (2 decimal places - no rounding up). Fractional cents are carried forward into the the next period's compounding. ## Backdated transactions Transactions which have an effective date in the past will trigger a recalculation of interest on the day it's posted. **For example:** On June 2, 2022, the interest accrual is 5, however, a transaction came in which was effective May 31 for 500 which means May 31 and June 1 should have had an additional balance of 500. This will trigger interest calculations based on May 31 and June 1's new balance, the new interest calculated will be compared against the old interest and changes will be applied on June 2. If the backdated transaction happens > 90 days in the past, we will raise a Case and not calculate the interest adjustment for this account. ### Payout (DDA Accounts) And Charging Interest (Lending Accounts) If the last day of the billing period happens to fall on a holiday/weekend, the interest payout/charge will occur on the previous business day. Any transactions which happen during this time will have their interest applied on the following business day and count towards the next billing period. ### Other Key Notes: * For deposits, interest accrual stops when the account `status` moves to `IN_CLOSING`. * An Account's APY as it appears in the statement data is computed using Average Daily Balance (by effective balances and paid interest in whole cents). # Internal Transfers Source: https://docs.synctera.com/v2/docs/internal-transfer-guide The [Internal Transfer API](/v2/reference/createinternaltransfer) allows you to transfer funds between two Synctera accounts, in real-time. ### Overview Common use cases include: * Moving funds between two accounts owned by the same customer. * Moving funds between two accounts owned by different customers. * Moving funds between two internal accounts. * Between a customer account and an internal account. This guide will show you how to accomplish a few different use cases using the internal transfers API. ### Prerequisites This guide assumes that you are already familiar with the customer and account creation APIs and have one or more accounts already created and in the appropriate status to be able to move funds. If not, go through the following guides before continue: To allow internal transfers between customer accounts, both accounts must be created using an an account template with `is_p2p_enabled` set to `true`. ### Internal transfers and transaction types All transactions in the Synctera platform have both a `type` and a `subtype` which are used to categorize transactions. The Internal Transfers API always create a transaction with type `internal_transfer`, but allows you to specify the subtype of the transaction via the Internal Transfer `type` field in the request payload. The full set of supported internal transfer types are documented in the [Internal Transfer API Reference](/v2/reference/createinternaltransfer). For more details about transaction types, and transactions in general, see the [Transaction Guide](/v2/docs/transactions-guide). ## Internal account permissions It's worth noting that certain internal accounts are special and are reserved exclusively for internal use by the Synctera platform. These are distinguished from normal internal accounts by the `is_system_acc` attribute on resource. When this field is `true`, it means that any internal transfers to or from these internal accounts will be declined. See the [Internal Transfers API](/v2/reference/listinternalaccounts) for more details. ### Example: Moving money between accounts To move funds between two customer accounts: ```shell Shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ https://api.synctera.com/v0/transactions/internal_transfer \ --data-binary ' { "amount": 1025, "currency": "USD", "originating_account_id": "35c1a55e-4510-458d-9345-fe08121b5654", "receiving_account_id": "c8ddc14b-33be-447a-820d-3fe59ad49028", "type": "PEER_TO_PEER" }' ``` This will create a transaction that credits 10.25 from customer account `35c1a55e-4510-458d-9345-fe08121b5654` and debits 10.25 to customer account `c8ddc14b-33be-447a-820d-3fe59ad49028` It's also worth highlighting that the `amount` in this example in cents, *not* dollars. The Synctera payment APIs always use the smallest denomination for the given currency. The response on an successful internal transfer will include the same information in the request payload, with the addition of an `id` field that represents the unique transaction id created to represent the transfer: ```json JSON theme={"system"} { "amount": 1025, "currency": "USD", "originating_account_id": "35c1a55e-4510-458d-9345-fe08121b5654", "receiving_account_id": "c8ddc14b-33be-447a-820d-3fe59ad49028", "type": "ACCOUNT_TO_ACCOUNT", "id": "e7ec7e47-0a97-40b8-8477-2fa80ae680f7" } ``` You can use the `id` with the [GET Posted Transaction API](/v2/reference/getpostedtransactionbyid) API to retrieve additional details about the transaction. ### Example: Charging a fee Charging a fee can be achieved by initiating an internal transfer that debits a customer and credits an internal account that has been allocated for that purpose (for example, a "profits and losses" operating account). This example will charge a \$5.00 account fee against a customer account (`0b4e28a7-65fd-4ae0-bbb8-d744ded639a5`), crediting our **PnL** internal account (`a5c2604b-7758-4732-b264-b0ea0a1403d1`): ```shell Shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ https://api.synctera.com/v0/transactions/internal_transfer \ --data-binary ' { "amount": 500, "currency": "USD", "originating_account_id": "0b4e28a7-65fd-4ae0-bbb8-d744ded639a5", "receiving_account_id": "a5c2604b-7758-4732-b264-b0ea0a1403d1", "type": "FEE" }' ``` The main difference between this example and the previous one is: 1. We are using a different transaction type (`FEE`) in order to more easily distinguish it from other transactions against the account. 2. `originating_account_id` now represents an internal account (fetched from the `/v0/internal_accounts` API) ## Example: Moving money between internal accounts Operations teams may need to perform periodic "sweeps" to move funds from one internal account to another as part of regular end-of-day operations. This example will move \$25,000 from an **ACH Settlement** internal account (`0b4e28a7-65fd-4ae0-bbb8-d744ded639a5`), to a **Money in and out** internal account (`3dff4ee6-057a-4b29-bedc-f8de8b838780`): ```shell Shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ https://api.synctera.com/v0/transactions/internal_transfer \ --data-binary ' { "amount": 2500000, "currency": "USD", "originating_account_id": "0b4e28a7-65fd-4ae0-bbb8-d744ded639a5", "receiving_account_id": "3dff4ee6-057a-4b29-bedc-f8de8b838780", "type": "ACH_CREDIT_SWEEP" }' ``` # KYC/KYB Verification Source: https://docs.synctera.com/v2/docs/kyc-kyb-verification US banking regulations require financial institutions to collect and verify information about their customers. Synctera's verification solution provides identity and watchlist checks for personal and business customers. ## Overview US banking regulations require a Customer Identification Program (CIP) — commonly known as *know your customer* (KYC) and *know your business* (KYB). Synctera's verification solution runs identity and watchlist checks for personal and business customers and records the results as `verification` objects. **A verification** represents a category of checks performed on a customer. The combined outcome of all verifications sets the customer's `verification_status`, which gates money movement — a customer must reach `ACCEPTED` to transact. A CIP program requires: * **Data collection** — name, date of birth, address, and government-issued ID. * **Disclosures** — notifying customers about the collection and retention of data. * **Verification** — confirming the collected information is current, valid, and accurate. * **Ongoing monitoring** — checking the customer against known watchlists over time. Key characteristics: * **Categorized** — each verification has a `verification_type` (`IDENTITY`, `WATCHLIST`, `DOCUMENT_VERIFICATION`, `RELATED_ENTITIES`, `MANUAL_REVIEW`). * **Detailed** — a `details` array records the individual attribute-level checks and their outcomes. * **Status-driven** — the customer's `verification_status` reflects all verifications; only `ACCEPTED` customers can move money. * **Recursive for businesses** — verifying a business also verifies its beneficial owners, owning businesses, and officers. To move money, all customers must undergo KYC or KYB verification. ## Prerequisites This guide assumes you have: * Created a [personal customer](/v2/docs/create-a-personal-customer) or [business customer](/v2/docs/create-a-business) * Recorded a [disclosure](/v2/docs/record-disclosure-acceptance) You should also be familiar with: * [Need to Know — Environments](/v2/reference/need-to-know#environments) * [Need to Know — Authentication](/v2/reference/need-to-know#authentication) ## The verification object A verification represents one category of checks on a customer. The `details` array holds the individual checks that make up that category. | Field | Description | | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | Unique identifier (read-only). | | `person_id` / `business_id` | The customer the verification applies to. | | `verification_type` | The category of check: `IDENTITY`, `WATCHLIST`, `DOCUMENT_VERIFICATION`, `RELATED_ENTITIES`, or `MANUAL_REVIEW`. | | `result` | The outcome of this verification (e.g. `ACCEPTED`, `REVIEW`, `REJECTED`). | | `details` | Attribute-level checks, each with a `label`, `description`, and `result` (`PASS`, `WARN`, `FAIL`). | | `required_documents` | Documents you must collect from the customer to advance the case review (e.g. `ID_DOCUMENT`, `ADDRESS_VERIFICATION`, `SSN_VERIFICATION`). Populated when the outcome requires documentary evidence to proceed. | | `verification_time` | When the verification ran. | | `creation_time` / `last_updated_time` | Timestamps (read-only). | An `IDENTITY` verification bundles the checks pertaining to a customer's identity — here, name, address, SSN, and email were all verified: ```json theme={"system"} { "id": "05e2ddf3-d172-450e-9cf3-7a34f76a414f", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "verification_type": "IDENTITY", "result": "ACCEPTED", "details": [ { "label": "Customer Identification Program (CIP)", "description": "Full name, address, and SSN/ITIN can be resolved to the individual", "result": "PASS" }, { "label": "Address", "description": "Address can be resolved to the individual", "result": "PASS" }, { "label": "Email", "description": "Email address is more than 2 years old", "result": "PASS" } ], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" } ``` Watchlist checks are represented by the `WATCHLIST` verification type: ```json theme={"system"} { "id": "a24a16a2-4711-4486-8049-787462c61ffc", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "verification_type": "WATCHLIST", "result": "ACCEPTED", "details": [ { "label": "Watchlist", "description": "Global Watchlist sources selected are not correlated with the input identifiers", "result": "PASS" } ], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" } ``` ## Verification status A customer's `verification_status` is the outcome of all verifications performed on them. New customers start as `UNVERIFIED`; the field lives on the [person](/v2/reference/createperson) and [business](/v2/reference/createbusiness) resources. A successful verify request moves the customer out of `UNVERIFIED` into one of: | Status | Meaning | | ------------- | ----------------------------------------------------------------------------------------------- | | `PENDING` | Verification is in progress (common for businesses). | | `PROVISIONAL` | Partially verified or verified with restrictions. | | `ACCEPTED` | The customer is verified and can move money. | | `REVIEW` | Verification ran and identified issues requiring review. | | `REJECTED` | The customer was rejected and should be blocked from certain actions (e.g. opening an account). | Any status other than `ACCEPTED` opens a case in the [Synctera Case Manager](/docs/kyc-cases-fintechs) for a compliance officer to review. **Suggested handling by outcome:** | Outcome | Recommended action | | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ACCEPTED` | Continue onboarding (e.g. [create an account](/v2/docs/create-accounts-guide)). | | `REVIEW` | Tell the user their application is under manual review. Continue onboarding but do not open an account until the case resolves to `ACCEPTED` (or inform them if `REJECTED`). | | `REJECTED` | Notify the applicant they were turned down and stop the flow. | | `VENDOR_ERROR` | Retry via API; if unresolved, follow the `REVIEW` path. | If a customer is not initially accepted: * Offer them a chance to review and correct the information they entered. * After corrections, call `POST /v2/verifications/verify` again to re-verify. * You may also verify using the customer's government ID via [document verification](/v2/docs/document-verification). * If they make **no** changes, do not re-run KYC/KYB — let the case be reviewed instead. * If they make changes and are still not accepted, stop and route to manual review. * Re-verifications triggered by the end-user (`customer_initiated: true`) count against any [customer-initiated verification limit](#limiting-customer-initiated-verifications). Two statuses fall outside the typical path: * `PENDING` — business results may not be immediately available. Subscribe to the `BUSINESS.VERIFICATION_OUTCOME.UPDATED` webhook. * `PROVISIONAL` — indicates an entity has been partially verified. ### Collecting required documents When a verification cannot be resolved from the submitted data alone, the verification object's `required_documents` array tells you exactly which documents to collect from the end customer to advance the case. Read this field and prompt the customer for the corresponding documents. | `required_document` | What to collect | Accepted documents | | ---------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `ID_DOCUMENT` | Proof of identity | Government-issued driver's license, state ID, or passport | | `ADDRESS_VERIFICATION` | Proof of legal address | Driver's license or state ID with address, or a utility bill, bank statement, or pay stub issued within 60 days, or a lease agreement | | `SSN_VERIFICATION` | Proof of Social Security Number | Social Security card, recent tax return (e.g. 1040), or a W-2 or 1099 | Where you submit the collected documents depends on the value: * **`ID_DOCUMENT`** — complete the [document verification](/v2/docs/document-verification) flow, which validates the customer's government-issued ID and steps them up for review. * **`ADDRESS_VERIFICATION` and `SSN_VERIFICATION`** — upload the supporting documents to the [documents API](/v2/docs/document-storage-guide). For example, if a verification returns `"required_documents": ["SSN_VERIFICATION"]`, collect an SSN document (such as a Social Security card or W-2) from your end customer and upload it via the [documents API](/v2/docs/document-storage-guide). If multiple values are present, collect a document for each and submit it to the appropriate destination above. ```json theme={"system"} { "id": "05e2ddf3-d172-450e-9cf3-7a34f76a414f", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "verification_type": "IDENTITY", "result": "REVIEW", "required_documents": ["SSN_VERIFICATION"], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" } ``` Collect only the documents named in `required_documents`. Submitting unrelated documents will not advance the case. ### Limiting customer-initiated verifications Banks and FinTechs can configure a maximum number of customer-initiated `IDENTITY` verifications per person over a rolling 3-month window, reducing synthetic-identity risk, stolen-identity abuse, and excessive vendor costs. A verification counts against the limit **only** when the request includes `customer_initiated: true` — i.e. the end-user themselves triggered it (for example, by tapping a "Verify my identity" button). Verifications triggered by the bank, FinTech, or Synctera are not counted. When the limit is reached, further `customer_initiated: true` requests are rejected; route those customers to manual review or support. To enable this protection, contact Synctera to configure `max_customer_initiated_verifications` for your tenant. ## Verifying a customer Once the required information is collected, initiate verification with [POST /v2/verifications/verify](/v2/reference/verify) and the customer's ID: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/verifications/verify \ --data-binary ' { "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "customer_ip_address": "184.233.47.237", "customer_consent": true, "customer_initiated": true }' ``` To verify a business, specify `business_id` instead of `person_id`: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/verifications/verify \ --data-binary ' { "business_id": "eaa9807f-8cda-4308-8244-90c11b1b43a5", "customer_ip_address": "184.233.47.237", "customer_consent": true }' ``` Set `customer_initiated` to `true` when the end-user triggers the request (e.g. a "Verify my identity" button). This enforces any tenant-configured limit on how many times a customer can re-verify. See [Limiting customer-initiated verifications](#limiting-customer-initiated-verifications). Consent must come directly from the customer. ## Example: verify a personal customer Create the customer record with [POST /v2/persons](/v2/reference/createperson): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/persons \ --data-binary ' { "first_name": "Christopher", "middle_name": "James", "last_name": "Albertson", "dob": "1985-06-14", "email": "chris@example.com", "phone_number": "+16045551212", "ssn": "456-78-9999", "legal_address": { "address_line_1": "123 Main St.", "city": "Beverly Hills", "state": "CA", "postal_code": "90210", "country_code": "US" }, "is_customer": true, "status": "ACTIVE" }' ``` See the [Create a Personal Customer](/v2/docs/create-a-personal-customer) guide for details. Display and record a disclosure informing the customer that their data will be shared with a third party for identity verification, using [POST /v2/disclosures](/v2/reference/createdisclosure): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/disclosures \ --data-binary ' { "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "type": "KYC_DATA_COLLECTION", "version": "1.0", "event_type": "ACKNOWLEDGED", "disclosure_date": "2022-03-17T17:04:34Z" }' ``` See the [Record Disclosure Acceptance](/v2/docs/record-disclosure-acceptance) guide for details. With consent captured, verify the customer with [POST /v2/verifications/verify](/v2/reference/verify): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/verifications/verify \ --data-binary ' { "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "customer_ip_address": "184.233.47.237", "customer_consent": true }' ``` The response contains an overall `verification_status` and an array of the verifications performed: ```json theme={"system"} { "verification_status": "ACCEPTED", "verifications": [ { "id": "05e2ddf3-d172-450e-9cf3-7a34f76a414f", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "verification_type": "IDENTITY", "result": "ACCEPTED", "details": [ { "label": "Customer Identification Program (CIP)", "description": "Full name, address, and SSN/ITIN can be resolved to the individual", "result": "PASS" }, { "label": "Address", "description": "Address can be resolved to the individual", "result": "PASS" }, { "label": "Email", "description": "Email address is more than 2 years old", "result": "PASS" } ], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" }, { "id": "a24a16a2-4711-4486-8049-787462c61ffc", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "verification_type": "WATCHLIST", "result": "ACCEPTED", "details": [ { "label": "Watchlist", "description": "Global Watchlist sources selected are not correlated with the input identifiers", "result": "PASS" } ], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" } ] } ``` The customer is now `ACCEPTED` and ready for the [account creation guide](/v2/docs/create-accounts-guide). ## Example: verify a business customer Complete due diligence on the business before opening an account. This example models a business with a single beneficial owner: ```mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% graph TD A[Beneficial Owner] --> B(Your New Business) ``` Create the business with [POST /v2/businesses](/v2/reference/createbusiness): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/businesses \ --data-binary ' { "entity_name": "Your New Business", "website": "https://example.com", "phone_number": "+16045551212", "legal_address": { "address_line_1": "123 Main St.", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country_code": "US" }, "structure": "CORPORATION", "formation_date": "2000-01-01", "formation_state": "DE", "ein": "99-9999999", "is_customer": true, "status": "ACTIVE" }' ``` Create the [beneficial owner](https://en.wikipedia.org/wiki/Beneficial_ownership) as a person with [POST /v2/persons](/v2/reference/createperson): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/persons \ --data-binary ' { "first_name": "Christopher", "middle_name": "James", "last_name": "Albertson", "dob": "1985-06-14", "email": "chris@example.com", "phone_number": "+16045551212", "ssn": "456-78-9999", "legal_address": { "address_line_1": "456 Main St.", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country_code": "US" }, "is_customer": false, "status": "ACTIVE" }' ``` Use the returned person `id` to [create a relationship](/v2/reference/createrelationship) with the business via `BENEFICIAL_OWNER_OF`: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/relationships \ --data-binary ' { "from_person_id": "{BENEFICIAL_OWNER_ID}", "relationship_type": "BENEFICIAL_OWNER_OF", "to_business_id": "{BUSINESS_ID}", "additional_data": { "percent_ownership": 50 } }' ``` Create KYC data collection disclosures for each owner before verifying. See the [Record Disclosure Acceptance](/v2/docs/record-disclosure-acceptance) guide. Verify the business — and all related entities — with [POST /v2/verifications/verify](/v2/reference/verify): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/verifications/verify \ --data-binary ' { "business_id": "{BUSINESS_ID}", "customer_consent": true }' ``` Verifying a business initiates KYC and KYB for **all** entities: the business and its beneficial owner. The business is now verified and ready for the [account creation guide](/v2/docs/create-accounts-guide). ## Example: verify a business with a complex ownership structure To satisfy regulatory requirements you must model the full ownership structure — beneficial owners, holding corporations, officers, and directors. This example adds a holding company (which owns the business) and an officer of that holding company: ```mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% graph TD D[Owner] --> C A[Officer] --> B(Holding Company) B --> C(Your New Business) ``` Create the primary business with [POST /v2/businesses](/v2/reference/createbusiness) (see [Create a Business Customer](/v2/docs/create-a-business) for details). Set `is_customer` to `true` to indicate it will be a customer: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/businesses \ --data-binary ' { "entity_name": "Your New Business", "website": "https://example.com", "phone_number": "+16045551212", "legal_address": { "address_line_1": "123 Main St.", "city": "San Francisco", "state": "CA", "postal_code": "94105", "country_code": "US" }, "structure": "CORPORATION", "formation_date": "2000-01-01", "formation_state": "DE", "ein": "99-9999999", "is_customer": true, "status": "ACTIVE" }' ``` Create the beneficial owner with [POST /v2/persons](/v2/reference/createperson), then link them via a `BENEFICIAL_OWNER_OF` [relationship](/v2/reference/createrelationship): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/relationships \ --data-binary ' { "from_person_id": "{BENEFICIAL_OWNER_ID}", "relationship_type": "BENEFICIAL_OWNER_OF", "to_business_id": "{BUSINESS_ID}", "additional_data": { "percent_ownership": 50 } }' ``` Represent the owning business by creating another business (not a customer) with [POST /v2/businesses](/v2/reference/createbusiness), then link it with an `OWNER_OF` relationship: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/relationships \ --data-binary ' { "from_business_id": "{HOLDING_COMPANY_ID}", "relationship_type": "OWNER_OF", "to_business_id": "{BUSINESS_ID}", "additional_data": { "percent_ownership": 50 } }' ``` Because the holding company controls a portion of the business, model its officers. Create the officer as a person, then link them to the holding company with a `MANAGING_PERSON_OF` relationship: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/relationships \ --data-binary ' { "from_person_id": "{OFFICER_ID}", "relationship_type": "MANAGING_PERSON_OF", "to_business_id": "{HOLDING_COMPANY_ID}", "additional_data": { "title": "OFFICER" } }' ``` Create KYC data collection disclosures for each owner before verifying. See the [Record Disclosure Acceptance](/v2/docs/record-disclosure-acceptance) guide. Verify the business and all related entities with [POST /v2/verifications/verify](/v2/reference/verify): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/verifications/verify \ --data-binary ' { "business_id": "{BUSINESS_ID}", "customer_consent": true }' ``` Verifying the business initiates KYC and KYB for **all** entities: the business, the holding company, its officers, and the beneficial owners. The response includes an overall `verification_status`, the verifications performed, and a `RELATED_ENTITIES` verification summarizing the outcomes for the beneficial owner, holding company, and officer: ```json theme={"system"} { "verification_status": "ACCEPTED", "verifications": [ { "id": "598dd41e-733c-4fee-b8e7-a71de41881ef", "business_id": "eaa9807f-8cda-4308-8244-90c11b1b43a5", "verification_type": "RELATED_ENTITIES", "result": "ACCEPTED", "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" }, { "id": "05e2ddf3-d172-450e-9cf3-7a34f76a414f", "business_id": "eaa9807f-8cda-4308-8244-90c11b1b43a5", "verification_type": "IDENTITY", "result": "ACCEPTED", "details": [ { "label": "Business Name", "description": "Match identified to the submitted Business Name", "result": "PASS" }, { "label": "Office Address", "description": "Match identified to the submitted Office Address", "result": "PASS" } ], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" }, { "id": "a24a16a2-4711-4486-8049-787462c61ffc", "business_id": "eaa9807f-8cda-4308-8244-90c11b1b43a5", "verification_type": "WATCHLIST", "result": "ACCEPTED", "details": [ { "label": "Watchlist", "description": "No Watchlist hits were identified", "result": "PASS" } ], "verification_time": "2022-03-14T18:34:59.91272Z", "creation_time": "2022-03-14T18:34:59.918188Z", "last_updated_time": "2022-03-14T18:34:59.918188Z" } ] } ``` ## Best practices A customer cannot move money until their `verification_status` is `ACCEPTED`. Do not open accounts or enable transactions for customers in `REVIEW`, `PENDING`, or `REJECTED`. * **Collect and disclose first** — gather all required fields and record the KYC data collection disclosure before verifying. * **Model the full ownership tree** — link every beneficial owner, owning business, and officer before verifying a business; one call verifies them all. * **Handle each outcome deliberately** — follow the suggested actions per status; open a review case rather than blindly re-running KYC. * **Guard re-verification** — send `customer_initiated: true` for user-triggered retries and respect the configured limit. * **Subscribe to webhooks** — watch `BUSINESS.VERIFICATION_OUTCOME.UPDATED` for asynchronous `PENDING` business results. ## Related guides Onboard a person before verifying them. Model business ownership before running KYB. Capture the KYC data collection disclosure. Step up customers flagged for review. Submit results from your own KYC/KYB vendor. Continuously screen verified customers. ## API reference * [Run a verification](/v2/reference/verify) * [List verifications](/v2/reference/listverifications1) * [Create a person](/v2/reference/createperson) * [Create a business](/v2/reference/createbusiness) * [Create a relationship](/v2/reference/createrelationship) * [Create a disclosure](/v2/reference/createdisclosure) # Line of Credit accounts Source: https://docs.synctera.com/v2/docs/line-of-credit-accounts-guide ## Account Product For Line of Credit, setting up an Account Product is mandatory. Even if the interest rate is 0%, the interest rate should be defined in the Account Product. Please see the Account Product section of the [Accounts Guide](/v2/docs/create-accounts-guide) for more details ## Line of Credit Account Template Account Templates contain predefined values for creating an account. When creating an account with an account template ID, the Accounts object inherits all values from the Account Template object first, before applying passed-in values. The Account Template API spec can be found [here](/v2/reference/createaccounttemplate) Some specific points regarding Account Template configuration for Line of Credit: * `grace_period` - The number of days past the billing period to allow for payment before it is considered overdue. This directly infers the payment due date. This is a required field. * `interest_product_id` - Refers to the Account Product Object. This configuration defines the interest rate(s) that is associated with the Account Template. This is a required field. * `minimum_payment` - Calculating the minimum payment due on the account for a billing period. This is a required field. 1. `minimum_payment.min_amount` - This configuration sets the minimum payment due for a billing period if the account balance greater than this amount. This value is set in cents. For example, to set the `min_amount` to \$30, the value will be 3000. 2. `minimum_payment.rate` - the percentage of the balance used for calculating the minimum payment. If the value is set at 10%, then 10% of the outstanding balance is the required minimum payment. The value is use is expressed in basis points. For example, to set 12.50% of the balance, set this value to 1250. 3. `minimum_payment.type` - Set this to `RATE_OR_AMOUNT`. The calculated minimum payment is greater of (1) rate times statement balance when the billing period closes and (2) min\_amount. But obviously, not greater than the statement balance. ```bash Bash theme={"system"} curl -X POST \ -H 'Authorization: Bearer $apikey' \ -H 'Content-Type: application/json' \ -d ' { "name": "Line of Credit Template", "description": "An account template for Line of Credit accounts", "is_enabled": true, "template": { "account_type": "LINE_OF_CREDIT", "currency": "USD", "bank_country": "US", "minimum_payment": { "type": "RATE_OR_AMOUNT", "amount": 2500, "rate": 125 }, "grace_period": 21 } }' $baseurl/v0/accounts/templates ``` ## Line of Credit Account ### API fields The Account API has certain fields that are specific to Line of Credit. These fields are: | Field Name | Description | Example | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | | account\_type | For Line of Credit, please set this field as `LINE_OF_CREDIT` | `LINE_OF_CREDIT` | | `application_id` | LoCs require the customer application to be approved and accepted by the applicant ([details](/v2/docs/credit-applications-guide)). `application_id` is required for creating an LoC account. | | | `credit_limit` | Defined in cents, the credit limit for this account. | 10000 (\$100) | | `grace_period` | The number of days past the billing period to allow for payment before it is considered due. This directly infers the due date for the minimum payment. For LOCs, please treat this as a required field. | 25 | | `interest_product_id` | Refers to the AccountProduct Object. This configuration defines the interest rate(s) that is associated with the AccountTemplate. Please treat this as s a required field for LoCs | | | **`minimum_payment`** | | | | `min_amount` | Defined in cents, the minimum amount to charge as a minimum payment. Note: The **minimum payment will never be greater than the statement balance despite setting this value.** | 3000 | | `rate` | The percentage of the balance used for calculating the minimum payment. If the value is set at 10%, then 10% of the outstanding balance will be the minimum payment. The value is expressed in basis points. For example, to set the value at 12.75% the input should be 1275 | 1275 | | `type` | The calculated minimum payment is greater of (1) rate times statement balance and (2) min\_amount. But obviously, not greater than the statement balance. | | Example Create an account of type `LINE_OF_CREDIT` [Accounts API](/v2/reference/createaccount) or refer to the [Accounts Guide](/v2/docs/create-accounts-guide) ```bash Bash theme={"system"} curl -X POST \ -H 'Authorization: Bearer $apikey' \ -H 'Content-Type: application/json' \ -d ' { "account_template_id": "{ACCOUNT_TEMPLATE_UUID}", "account_purpose": "LOC Account", "credit_limit": 100000, "application_id": "{APPLICATION_UUID}", "relationships": [ { "relationship_type": "PRIMARY_ACCOUNT_HOLDER", "customer_id": "{CUSTOMER_UUID}" } ] }' $baseurl/v0/accounts ``` Sample response body ```json JSON theme={"system"} { "access_status": "ACTIVE", "account_number": "790586668526", "account_purpose": "LOC Account", "account_type": "LINE_OF_CREDIT", "balance_ceiling": { "balance": 100000 }, "balance_floor": { "balance": 0 }, "balances": [ { "balance": 20000, "type": "ACCOUNT_BALANCE" }, { "balance": 80000, "type": "AVAILABLE_BALANCE" } ], "bank_routing": "112233445", "creation_time": "2022-04-07T20:37:46.356692Z", "currency": "USD", "customer_ids": ["{CUSTOMER_UUID}"], "customer_type": "PERSONAL", "id": "3389aeac-0163-4479-8702-ff8572d39fe8", "is_account_pool": false, "last_updated_time": "2022-04-07T20:37:46.356692Z", "status": "ACTIVE", "is_ach_enabled": true, "is_card_enabled": false, "is_p2p_enabled": true, "minimum_payment": { "type": "RATE_OR_AMOUNT", "amount": 2500, "rate": 125 }, "application_id": "{APPLICATION_UUID}", "metadata": {}, "grace_period": 21 } ``` # Line of Credit Statements Source: https://docs.synctera.com/v2/docs/line-of-credit-statements-guide Synctera APIs provide all the raw data necessary to create a periodic account statement. The contents of a line of credit account statement may be governed by various regulations, therefore it is essential to add the necessary fields when creating a periodic statement. Please consult with your compliance officer further. ## Statement content In order to produce regulatory-compliant, human-readable statements, this API provides the following information: | Section | Field(s) | Description | | --------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | `statement_type` | The type of the statement, i.e. `LINE_OF_CREDIT` | | | `start_date` and `end_date` | The date interval covered by the statement, inclusive. | | | `issue_date` | The date the statement was issued. | | | `opening_balance` and `closing_balance` | The final posted balances recorded at the beginning of `start_date` and at the end of `end_date`. | | | `disclosure` | A suggested disclosure statement to display. | | | `total_transactions` | The number of transactions posted during this statement period. See [this section](/v2/docs/statements-guide#step-3-list-the-transactions-for-a-statement) for guidance on how to access the full list of transactions. | | `account_summary` | - | Information about the account. | | `account_summary` | `financial_institution` | Information about the financial institution managing the account. | | `customer_service_details` | - | Contact information for use by the customer if they wish to dispute the information in this statement. | | `primary_account_holder_personal` | - | When `account_summary.customer_type` is `PERSONAL` then `primary_account_holder_personal` contains information about the person acting as primary account holder. | | `primary_account_holder_business` | - | When `account_summary.customer_type` is `BUSINESS` then `primary_account_holder_business` contains information about the company holding this account. | | `joint_account_holders` | - | A list of all individuals designated as joint account holders for this account. | | `authorized_signer` | - | A list of all individuals designated as authorized signers for this account. | | `credit_summary` | `apr` | Describes the annual percentage rate in effect. | | `credit_summary` | `balance_for_interest` | The balance used to calculate the interest accrued on the account. | | `credit_summary` | `credit_limit` | The credit limit set on the account. | | `credit_summary` | `interest` and `interest_ytd` | The total interest accrued at the end of this statement, both for this statement period and for the calendar year so far. | | `credit_summary` | `fees` and `fees_ytd` | The total fees accrued at the end of this statement, both for this statement period and for the calendar year so far. | | `credit_summary` | `minimum_payment_due` | The minimum payment amount expected by the payment due date. | | `credit_summary` | `payment_due_date` | The date by which payment is expected. | | `credit_summary` | `last_payment_date` | The date on which the last payment is received. | | `credit_summary` | `payments_received` | The total payment amount received during the current billing priod. | | `credit_summary` | `is_past_due` and `amount_past_due` | The indicator of an account which is past due and its past due amount. | | `credit_summary` | `amount_over_limit` | The portion of the statement balance that exceeds the account's credit limit. | # Link External Cards Source: https://docs.synctera.com/v2/docs/link-external-cards # Overview To enable an instant payment (`PULL`/`PUSH`) with an external **card-on-file**, the following steps are required: 1. Add card-on-file * [Using the External Card Creation Widget](#add-card-on-file-using-the-external-card-creation-widget) * This step is required if you are not [PCI certified](https://www.pcisecuritystandards.org/standards/) * [Using API](#add-card-on-file-using-api) * You can use this option if you are PCI certified 2. [For `PULL` payments, enable 3-D Secure (3DS) authentication](#enable-3ds-and-create-payment) 3. [Initiate external card-on-file payment](/v2/docs/instant-payments-card-on-file) # Add card-on-file using the External Card Creation Widget This step is required if you are not PCI certified. The External Card Creation Widget allows your customers to securely enter payment card information directly in your application. Since the widget communicates directly between the client and Synctera, it removes the need for you to be PCI certified. The information is stored securely and can be retrieved via Synctera API. The External Card Creation Widget provides a complete, secure payment form that includes: * **Card Number (PAN)** - Primary account number with automatic formatting * **Cardholder Name** - Name on the card * **Expiration Date** - Card expiry with MM/YY format * **CVV/CVC** - Security code (3-4 digits) * **Billing Address** - Optional billing address fields All sensitive card data is handled in isolated iframes, ensuring PCI compliance while giving you full control over the user experience. *** ## Getting Started ### Prerequisites Before integrating the widget, ensure you have: * **Synctera API Keys** - Working API keys for your business * **Widget Token** - A widget token for tokenizing cards (obtained from the API) * **Environment Configuration** - Know which environment you're using (`sandbox`, or `production`) ### API Keys First, ensure you have your Synctera API Keys working for your business. You'll need these to obtain widget tokens. ### Mobile Applications If you're integrating the widgets in a mobile application, you may need to use one of the following web views: * **WKWebView** in an iOS application * **WebView** in an Android application * **WebView** in React Native *** ## Basic Integration ### Step 1: Load the Widget Script Load the External Card Creation widget script into your page by adding the following script tag to the bottom of the `body` of your HTML: ```html HTML theme={"system"} ``` ```javascript React theme={"system"} import { useEffect } from 'react'; function CardForm() { useEffect(() => { // Load the widget script const script = document.createElement('script'); script.type = 'module'; script.src = 'https://assets.synctera.com/widgets/external-card-creation/v1.1.1/index.js'; document.head.appendChild(script); return () => { document.head.removeChild(script); }; }, []); return ( ); } ``` ### Step 2: Get a Widget Token Request a widget token for tokenizing cards from your backend using the Synctera API. The widget token is required for the widget to authenticate and submit card data. ```bash curl theme={"system"} curl -X POST "https://api-sandbox.synctera.com/v1/external_cards/widget_token?widget_type=TOKENIZE&customer_id={customerId}" \ -H "Authorization: Bearer {apiKey}" \ -H "Content-Type: application/json" ``` ```javascript Node.js theme={"system"} const response = await fetch( 'https://api-sandbox.synctera.com/v1/external_cards/widget_token?widget_type=TOKENIZE&customer_id=' + customerId, { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } } ); const { widget_token } = await response.json(); ``` Widget tokens expire after a set period and are scoped to a specific customer. Generate a new token on each page load or when needed. Widget tokens are one use only, so if a user submits and gets an error that invalidates the token and the widget will be to be supplied a new token. ### Step 3: Add the Widget Component Add the `` web component to your page where you want the card form to appear: ```html HTML theme={"system"} ``` ```html HTML with Address theme={"system"} ``` *** ## Configuration Options The `` component supports the following configuration options: | Property | Type | Required | Default | Description | | ----------------- | --------- | -------- | ----------- | -------------------------------------------- | | `token` | `string` | Yes | - | Widget token obtained from the API | | `env` | `string` | Yes | - | Environment: `sandbox` or `production` | | `theme` | `string` | No | `"default"` | Theme style: `"default"` or `"night-shift"` | | `include-address` | `boolean` | No | `false` | Show/hide billing address fields section | | `custom-labels` | `string` | No | `{}` | JSON string of custom labels for form fields | ### Environment Configuration The `env` property determines which API endpoint the widget uses: * **`sandbox`** - Sandbox/test environment (recommended for testing) * **`production`** - Production environment Always use `sandbox` for testing and development. Only use `production` for live integrations. ### Theme Options The widget supports two themes: ```html Default Theme theme={"system"} ``` ```html Night Shift Theme theme={"system"} ``` ### Custom Labels Customize the labels and text displayed in the widget by passing a JSON string to the `custom-labels` attribute: ```html theme={"system"} ``` Available custom label keys: * `widgetTitle` - Widget header text * `cardNameLabel` - Name on card label * `cardNamePlaceholder` - Name on card placeholder * `cardNumberLabel` - Card number label * `cardPanPlaceholder` - Card number placeholder * `expirationDateLabel` - Expiration date label * `cardExpPlaceholder` - Expiration date placeholder * `securityCodeLabel` - CVV/CVC label * `cardCvvPlaceholder` - CVV placeholder * `streetAddressLabel` - Street address label * `addressLine1Placeholder` - Street address placeholder * `addressLine2Label` - Address line 2 label * `addressLine2Placeholder` - Address line 2 placeholder * `cityLabel` - City label * `addressCityPlaceholder` - City placeholder * `stateLabel` - State label * `addressStatePlaceholder` - State placeholder * `zipCodeLabel` - ZIP code label * `addressZipPlaceholder` - ZIP code placeholder * `submitButtonText` - Submit button text * `submitLoadingText` - Loading state text * `useAddressOnFileLabel` - Address checkbox label * `billingAddressTitle` - Billing address section title *** ## Event Handling The widget dispatches lifecycle events for initialization and action outcomes: * **`load`** — Widget initialized successfully, all fields are ready for user input. * **`error`** — Widget failed to initialize (field load failure, network error, or timeout). * **`success`** — Card tokenization completed successfully. * **`failure`** — Card tokenization failed (API error, validation error, etc.). ### Load Event Dispatched when all secure input fields have loaded and the widget is fully functional. Use it to hide loading UI or enable dependent controls. | Property | Type | Description | | ------------ | -------- | ---------------------------------- | | `instanceId` | `string` | Unique ID for this widget instance | ```html theme={"system"} ``` ### Error Event Dispatched when the widget fails to initialize. This means one or more secure input fields could not load, and the widget is not functional. Show an error message or retry UI to the user. | Property | Type | Description | | -------------- | ---------- | ---------------------------------------------- | | `instanceId` | `string` | Unique ID for this widget instance | | `error` | `string` | Human-readable error message (safe to display) | | `failedFields` | `string[]` | List of field types that failed to load | ```html theme={"system"} ``` The `load` and `error` events are mutually exclusive — exactly one will fire during widget initialization. Always listen for both to handle all scenarios. ### Success Event The widget dispatches a `success` event when card tokenization is successful. The event confirms that the card was added and includes the external card ID when the API response provides it. PAN and CVV are never exposed to the host page. The `success` event exposes only allowlisted, non-sensitive metadata: | Property | Type | Description | | ---------------- | -------- | ---------------------------------------- | | `status` | `string` | Submission status returned by the widget | | `message` | `string` | Optional human-readable success message | | `externalCardId` | `string` | Optional ID of the created external card | | `instanceId` | `string` | Unique ID for this widget instance | ```html HTML Event Listeners theme={"system"} ``` ```javascript Vanilla JavaScript theme={"system"} const widget = document.querySelector('external-card-creation'); widget.addEventListener('success', (event) => { const { status, message, externalCardId } = event.detail; console.log('Card tokenized successfully:', status, message, externalCardId); // Proceed with payment or store reference if (externalCardId) { handlePayment(externalCardId); } }); widget.addEventListener('failure', (event) => { const { error } = event.detail; console.error('Tokenization failed:', error); showError(error); }); ``` ```javascript React theme={"system"} function CardForm() { const [widgetToken, setWidgetToken] = useState(''); useEffect(() => { const widget = document.querySelector('external-card-creation'); const handleSuccess = (event) => { const { status, message, externalCardId } = event.detail; console.log('Card tokenized successfully:', status, message, externalCardId); // Handle successful tokenization }; const handleFailure = (event) => { console.error('Error:', event.detail.error); // Handle error }; if (widget) { widget.addEventListener('success', handleSuccess); widget.addEventListener('failure', handleFailure); } return () => { if (widget) { widget.removeEventListener('success', handleSuccess); widget.removeEventListener('failure', handleFailure); } }; }, []); return ( ); } ``` ### Failure Event The widget dispatches a `failure` event when card tokenization fails: ```javascript theme={"system"} widget.addEventListener('failure', (event) => { const { error } = event.detail; console.error('Tokenization failed:', error); // Display error message to user }); ``` ### Callback Properties (JavaScript Only) As an alternative to `addEventListener`, you can set callback functions directly on the element via JavaScript. These are JS-only properties and cannot be set as HTML attributes. ```javascript theme={"system"} const widget = document.getElementById('card-widget'); widget.onLoad = (event) => { console.log('Widget ready:', event.detail.instanceId); }; widget.onError = (event) => { console.error('Widget failed:', event.detail.error); }; widget.onSuccess = (event) => { const { status, message, externalCardId } = event.detail; console.log('Card tokenized successfully:', status, message, externalCardId); }; widget.onFailure = (event) => { console.error('Tokenization failed:', event.detail.error); }; ``` *** ## Complete Example Here's a complete example showing a full integration with widget token fetching and error handling: ```html Complete HTML Example theme={"system"} External Card Creation Widget Example

Add Payment Card

``` ```javascript React Example theme={"system"} import { useEffect, useState } from 'react'; function PaymentCardForm({ customerId }) { const [widgetToken, setWidgetToken] = useState(null); const [error, setError] = useState(null); useEffect(() => { // Load widget script const script = document.createElement('script'); script.type = 'module'; script.src = 'https://assets.synctera.com/widgets/external-card-creation/v1.1.1/index.js'; document.head.appendChild(script); // Fetch widget token fetch('/api/widget-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ customer_id: customerId }) }) .then(res => res.json()) .then(data => setWidgetToken(data.widget_token)) .catch(err => setError(err.message)); return () => { document.head.removeChild(script); }; }, [customerId]); useEffect(() => { if (!widgetToken) return; const widget = document.querySelector('external-card-creation'); const handleLoad = (event) => { console.log('Widget ready:', event.detail.instanceId); }; const handleError = (event) => { const { error, failedFields } = event.detail; console.error('Widget failed to initialize:', error, failedFields); setError(error); }; const handleSuccess = (event) => { const { status, message, externalCardId } = event.detail; console.log('Card tokenized successfully:', status, message, externalCardId); }; const handleFailure = (event) => { setError(event.detail.error); }; widget?.addEventListener('load', handleLoad); widget?.addEventListener('error', handleError); widget?.addEventListener('success', handleSuccess); widget?.addEventListener('failure', handleFailure); return () => { widget?.removeEventListener('load', handleLoad); widget?.removeEventListener('error', handleError); widget?.removeEventListener('success', handleSuccess); widget?.removeEventListener('failure', handleFailure); }; }, [widgetToken]); if (error) { return
Error: {error}
; } if (!widgetToken) { return
Loading payment form...
; } return (

Add Payment Card

); } export default PaymentCardForm; ```
*** ## Address Fields The widget supports optional billing address collection. Enable address fields by setting `include-address="true"`: ```html theme={"system"} ``` When address fields are enabled, the widget includes: * **Street Address** (Address Line 1) * **Address Line 2** (optional) * **City** * **State** * **ZIP Code** The widget also provides a checkbox option to "Use address on file" which will hide the address fields if checked. *** ## Field Validation The widget automatically validates all card fields in real-time: * **Card Number (PAN)**: Validates card number format and runs Luhn algorithm check * **Cardholder Name**: Validates alphabetical characters and proper formatting * **Expiration Date**: Validates MM/YY format and ensures date is not expired * **CVV/CVC**: Validates 3-4 digit security code * **Address Fields**: Validates address format, state codes, and ZIP codes The submit button is automatically disabled until all required fields are valid. *** ## Card verifications For security purposes, a number of verifications are performed when the card is added. For details, see the [Verifications section](#verifications). ## Security & PCI Compliance All sensitive card data is handled in isolated iframes, ensuring that your application never touches PCI-sensitive information. ### Security Features * **Iframe Isolation**: Each field runs in its own sandboxed iframe * **No Data Exposure**: Sensitive data never touches the parent page * **Token-based Authentication**: Secure API communication using widget tokens * **Origin Validation**: All messages validated against expected origins * **XSS Protection**: All input is sanitized and validated ### PCI Compliance The widget is designed to help you maintain PCI compliance: * Sensitive card data is isolated in secure iframes * Your application never handles raw card data * All communication uses secure, tokenized endpoints * The widget handles PCI compliance requirements on your behalf *** ## Troubleshooting ### Widget Not Loading If the widget doesn't appear on your page: 1. **Check Script Loading**: Ensure the widget script is loaded before the component is used 2. **Check Token**: Verify the widget token is valid and not expired 3. **Check Environment**: Ensure the `env` attribute matches your API environment 4. **Check Console**: Look for JavaScript errors in the browser console ### Tokenization Failing If card submission fails: 1. **Verify Token**: Ensure the widget token is valid and not expired 2. **Check Environment**: Ensure the `env` matches your API endpoint 3. **Check Network**: Inspect network requests in browser DevTools 4. **Review Error Events**: Listen to the `failure` event for detailed error messages *** ## Additional Information ### Supported Browsers The widget supports all modern browsers: * Chrome (latest) * Firefox (latest) * Safari (latest) * Edge (latest) ### Responsive Design The widget is fully responsive and adapts to mobile and desktop screens automatically. ### Custom Styling The widget comes with a theme option and labels can be passed in as attributes # Add card-on-file using API If you are PCI certified, you have the option to create the External Card directly using the card credentials by calling POST [/v1/external\_cards](https://dev.synctera.com/v1/reference/createexternalcard). In addition to the card credentials (`pan` and `expiration_month`/`expiration_year`), you must provide the `customer_id` and cardholder `name` (`business_id` may optionally be provided if applicable). `cvv` is optional (for migration purposes), but should be provided for adding new cards as it provides an additional layer of security and reduces the risk of fraud. A `billing_address` can be added optionally, if it is different from the cardholder's address-on-file on the Synctera platform. For more details on CVV and address verification, see the [Verifications section](#verifications). ### Example request/response **Example request:** ```bash theme={"system"} curl \ $baseurl/v1/external_cards \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ -d ' { "pan": "4005519200000004", "cvv": "123", "expiration_month": "04", "expiration_year": "26", "name": "Jane Taylor", "customer_id": "{CUSTOMER_ID}" }' ``` **Example response:** ```json theme={"system"} { "created_time": "2023-01-18T12:03:46.892809-05:00", "currency": "USD", "customer_id": "{CUSTOMER_ID}", "expiration_month": "4", "expiration_year": "2026", "id": "{EXTERNAL_CARD_ID}", "last_four": "0004", "last_modified_time": "2023-01-18T12:03:46.892809-05:00", "name": "Jane Taylor", "verifications": { "address_verification_result": "VERIFIED", "cvv2_result": "VERIFIED", "pull_enabled": true, "push_enabled": true, "state": "SUCCEEDED" } } ``` # Verifications When an External Card is created, the following verifications are performed: * CVV2 verification: * CVV2 provided in the widget or in the API is validated against the CVV2 on file with the issuer * Address verification: * Unless billing address is specified in the widget/API, the address stored on the customer's record on Synctera is validated against the address-on-file with the issuer * Note that if `business_id` is provided, address verification is performed on the Business's legal address, otherwise, it is performed on the Person's legal address. However, cardholder `name` matching is performed on the Person's name regardless. * Name verification: * Name provided in the widget is validated against the name on file with the issuer The verification results are displayed in the `verifications` object. In addition to CVV2, address and name, the `verifications` object contains information about the card, as well as the type of transactions the card supports. If either `pull_enabled` or `push_enabled` are `false`, that type of transaction may not be performed using the card. # Enable 3DS and create payment Once a card has been added on file, a `PULL` or a `PUSH` payment can be initiated with the card. For `PULL` payments, 3-D Secure (3DS) authentication is required. For details on how to enable 3DS, and how to iniate a payment with a card-on-file, see the [Instant Payments - Card-On-File](/v2/docs/instant-payments-card-on-file) section. # Ongoing Monitoring Source: https://docs.synctera.com/v2/docs/monitoring-guide Ongoing monitoring keeps customers enrolled in continuous screening against sanctions and enforcement watchlists, PEP sources, and adverse media after their initial verification. ## Overview Beyond the initial Customer Identification Program (CIP) checks covered in the [KYC/KYB guide](/v2/docs/kyc-kyb-verification), financial service providers are required to conduct **ongoing monitoring** of their customers. Synctera's monitoring offering continuously screens enrolled customers against a global list of sanctions and enforcement watchlists, Politically Exposed Person (PEP) sources, and adverse media. **A monitoring subscription** enrolls a customer with one of Synctera's monitoring vendors. When new information surfaces (a watchlist hit, a Secretary of State filing, a bankruptcy, etc.), a **monitoring alert** is created and a case is opened in the Synctera Case Manager for a compliance officer to review. Key characteristics: * **Continuous** — screening runs on an ongoing basis after the customer is verified, not just at onboarding. * **Vendor-backed** — each subscription represents enrollment with a monitoring vendor (e.g. Socure, Middesk). * **Alert-driven** — incoming signals create monitoring alerts, each of which opens a review case. * **On by default** — all customers are automatically enrolled unless the feature is disabled. Monitoring enrollment for personal customers is currently available only in the Synctera **Production** environment. By default, all customers are enrolled in ongoing monitoring — contact your Synctera sales representative to disable this. This guide showcases a **manual** implementation of ongoing monitoring. ## Prerequisites This guide assumes you have: * Created a [personal customer](/v2/docs/create-a-personal-customer) * Recorded a [disclosure](/v2/docs/record-disclosure-acceptance) * [Verified the customer](/v2/docs/kyc-kyb-verification) You should also be familiar with: * [Need to Know — Environments](/v2/reference/need-to-know#environments) * [Need to Know — Authentication](/v2/reference/need-to-know#authentication) ## The monitoring objects ### Monitoring subscription A subscription represents a customer's enrollment with a monitoring vendor. It contains a unique identifier, the customer identifier, and any additional metadata. ```json theme={"system"} { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "creation_time": "2021-06-14T14:15:22Z", "last_updated_time": "2021-12-14T07:15:34Z", "metadata": {} } ``` See the [API reference](/v2/reference/createsubscription) for the full schema. ### Monitoring alert An alert is created when a signal is received for a customer. It contains a unique identifier, the customer identifier, the alert `type`, a `status`, a list of `urls` with more information, and a vendor-specific representation of the alert. ```json theme={"system"} { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "type": "WATCHLIST", "status": "ACTIVE", "vendor_info": { "vendor": "SOCURE", "content_type": "application/json", "json": {} }, "urls": [ "https://example.com/alert-document-1", "https://example.com/alert-document-2" ], "creation_time": "2021-06-14T14:15:22Z", "last_updated_time": "2021-12-14T07:15:34Z", "metadata": {} } ``` Every incoming customer monitoring alert triggers a case in the Synctera Case Manager so the customer's profile can be manually reviewed by a compliance officer. See the [API reference](/v2/reference/getalert) for the full schema. ## Enrolling a customer in monitoring Create a record for the customer with [POST /v2/persons](/v2/reference/createperson): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/persons \ --data-binary ' { "first_name": "Christopher", "middle_name": "James", "last_name": "Albertson", "dob": "1985-06-14", "email": "chris@example.com", "phone_number": "+16045551212", "ssn": "456-78-9999", "legal_address": { "address_line_1": "123 Main St.", "city": "Beverly Hills", "state": "CA", "postal_code": "90210", "country_code": "US" }, "is_customer": true, "status": "ACTIVE" }' ``` See the [Create a Personal Customer](/v2/docs/create-a-personal-customer) guide for details. Display a disclosure informing the customer that you are collecting personal data to be shared with a third party for identity verification, then record it with [POST /v2/disclosures](/v2/reference/createdisclosure): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/disclosures \ --data-binary ' { "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "type": "KYC_DATA_COLLECTION", "version": "1.0", "event_type": "ACKNOWLEDGED", "disclosure_date": "2022-03-17T17:04:34Z" }' ``` See the [Record Disclosure Acceptance](/v2/docs/record-disclosure-acceptance) guide for details. With the customer created and consent captured, run verification with [POST /v2/verifications/verify](/v2/reference/verify): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/verifications/verify \ --data-binary ' { "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9", "customer_ip_address": "184.233.47.237", "customer_consent": true }' ``` Consent must come directly from the customer. Once the customer is verified, create a monitoring subscription with [POST /v2/monitoring/subscriptions](/v2/reference/createsubscription): ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/monitoring/subscriptions \ --data-binary ' { "person_id": "7ef75751-e372-4c12-9b02-b9e4b1faaac9" }' ``` ## Best practices Monitoring alerts require timely human review. Every alert opens a case in the Synctera Case Manager — ensure a compliance officer triages these promptly to stay within regulatory timelines. * **Verify before enrolling** — a subscription is meaningful only for a verified customer; complete KYC first. * **Rely on default enrollment** — customers are enrolled automatically; only implement manual enrollment if you have disabled the default. * **Handle alerts programmatically** — subscribe to alert notifications and route them into your review workflow rather than polling. * **Preserve alert `urls`** — capture the supporting documents referenced by each alert for your audit trail. ## Related guides Onboard the customer you want to monitor. Verify a customer before enrolling them in monitoring. Capture the KYC data collection disclosure. Respond to alerts and high-risk ratings with additional information. ## API reference * [Create a monitoring subscription](/v2/reference/createsubscription) * [Get a monitoring alert](/v2/reference/getalert) * [Run a verification](/v2/reference/verify) # Offline PIN Source: https://docs.synctera.com/v2/docs/offline-pin ## PIN Issuance Policy Card products have a PIN issuance policy that enables creating physical cards with the PIN programmed into the card's chip prior to shipment. This allows merchants to verify the PIN at the point of sale even in an offline scenario. The way that the PIN is set prior to shipment is determined by the card product's `pin_issuance_policy` field. The `pin_issuance_policy` field has three possible values: `NOT_REQUIRED`, `RANDOM` and `REQUIRED`. Your physical card product may require offline PIN support. See the `offline_pin` flag in the card product response. If this flag is set then the PIN issuance policy must be something other than `NOT_REQUIRED`. Virtual cards do not have a PIN issuance policy. ### Not Required If the `pin_issuance_policy` of your card product is `NOT_REQUIRED` (or there is no `pin_issuance_policy`) then the card will ship without a PIN. The PIN must still be set but this can happen after the customer receives their card. ### Random If the `pin_issuance_policy` of your card product is `RANDOM` then the system will assign a random PIN to the user's card prior to shipment. When you issue a card with this card product, the card will have `PENDING` status. Within a few minutes the card will transition to `UNACTIVATED` status. If you have the appropriate webhook subscription set up you will get a `CARD.UPDATED` webhook when this happens. After the customer receives and activates their card, they can then reveal the PIN using the Reveal PIN widget. ### Required If the `pin_issuance_policy` of your card product is `REQUIRED` then the card will be created having `PENDING` status. While in this state, the physical card will not be created. The card will not transition out of this status until the user sets a PIN for the card using the Set PIN widget. Within a few minutes of the user setting the PIN, the card will transition to `UNACTIVATED` status. If you have the appropriate webhook subscription set up you will get a `CARD.UPDATED` webhook when this happens. Once the card is `UNACTIVATED`, the physical card creation and shipping process will proceed. # Payment Schedules Source: https://docs.synctera.com/v2/docs/payment-schedules Customers may want to set up scheduled payments for their mortgage or to move money into savings. Synctera enables you to easily create and manage scheduled payments for your customers. Synctera will manage updating the payment date if the payment is scheduled to occur on a date the payment method is not available such as weekends for ACH. ## Payment Schedule Resource The payment schedule resource consists of two primary fields: `schedule` and `payment_instruction`. `schedule` is a schedule configuration to define the frequency and number of recurring payments. `payment_instruction` defines how the payments are executed. There are two fields: `type` defines the supported payment types like `ACH` and `INTERNAL_TRANSFER`, and `request` will be the same request body for the corresponding payments. The resource also has the fields `description` and `metadata`, so the users can provide additional information for the resources. ```json JSON theme={"system"} { "description": "example schedule", "schedule": { "start_date": "2022-04-26", "frequency": "DAILY", "interval": 2, "count": 2 }, "payment_instruction": { "type": "INTERNAL_TRANSFER", "request": { "amount": 10, "currency": "USD", "originating_account_id": "{ACCOUNT_ID}", "receiving_account_id": "{ACCOUNT_ID}", "type": "ACCOUNT_TO_ACCOUNT" } } } ``` ### Schedule Configuration The schedule has several fields to define the recurrence. Refer to [`POST /v0/payment_schedules`](/v2/reference/createpaymentschedule) * `start_date`: The scheduled date of the first recurrence to be executed. Please note that the scheduled date and execution date (details below) cannot be earlier than today's date, depends on the underlying bank's timezone. * `frequency`: The recurrence could be executed on a `DAILY`, `WEEKLY`, or `MONTHLY` basis. * `interval`: Interval describes the number of frequency between the recurrence. For example, you have `interval` set to 2 with `frequency` set to `DAILY`, then this recurrence will be executed every other day. * `count`: Total number of the recurrence. * `end_date`: The last date of the recurrence could be executed. The date is exclusive. Important: `count` and `end_date` are optional fields, but you have to provide exactly one of them to avoid the infinite recurrence. * `execution_time`: The local time of day in the banks configured timezone at which the payments in the given schedule should execute. This is an optional field that can be omitted; system behavior will default to `11:00:00` if not applied. Note that execution times cannot be changed after creation. ### Scheduled Date vs Execution Date Once the payment schedule is created, or the current scheduled one has been executed, it will calculate the next scheduled date and execution date. The next scheduled date will simply be calculated based on the schedule configuration for the next recurrence. Please note that if `frequency` is set to `MONTHLY`, but the next scheduled date does not have the day of the month, then it will be the last day of the month, e.g. `start_date` is Jan 31 with `interval` is 1, then the next recurrence will be Feb 28/29. Execution date is based on the underlying bank's business dates. If a scheduled date falls on the bank's holiday or weekend, then the execution date will be the last business day of the scheduled date. Otherwise, it will be the same as the scheduled date. ### Execution Timing The payment executions starts to happen on the execution date, 11:00 AM on the underlying bank's timezone. Please note that the payment could be delayed depends on the volume of the payment schedules needs to be processed at the time. ### Status Status is the enumeration value * `ACTIVE`: The payment schedule has the next scheduled date and execution date determined and will be executed at the execution time. * `CANCELLED`: The payment schedule has been cancelled. This status can be set via the payment schedule update endpoint. Once the status is set, the next scheduled date and execution date will be set to null, so no future payments will be executed. * `EXPIRED`: The payment schedule has completed all the recurrence based on the `schedule`, so no future payments will be executed. ## Examples ### A customer wants to set up scheduled payments save \$100 bi-weekly for a year starting on April 26, 2022. ```shell Shell theme={"system"} curl \ -X POST \ https://api.synctera.com/v0/payment_schedules \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ --data-binary '{ "description": "example schedule", "metadata": { "foo": "bar" }, "schedule": { "start_date": "2022-04-26", "frequency": "WEEKLY", "interval": 2, "count": 26 }, "payment_instruction": { "type": "INTERNAL_TRANSFER", "request": { "amount": 10000, "currency": "USD", "originating_account_id": "{ACCOUNT_ID}", "receiving_account_id": "{ACCOUNT_ID}", "type": "ACCOUNT_TO_ACCOUNT" } } }' ``` You will have the response like below. ```json JSON theme={"system"} { "description": "payola testing", "id": "{PAYMENT_SCHEDULE_ID}", "metadata": { "key": "value" }, "next_payment_date": { "execution_date": "2022-04-26", "scheduled_date": "2022-04-26" }, "payment_instruction": { "request": { "amount": 10, "currency": "USD", "originating_account_id": "{ACCOUNT_ID}", "receiving_account_id": "{ACCOUNT_ID}", "type": "ACCOUNT_TO_ACCOUNT" }, "type": "INTERNAL_TRANSFER" }, "schedule": { "count": 2, "frequency": "DAILY", "interval": 2, "start_date": "2022-04-26" }, "status": "ACTIVE" } ``` Note that `next_payment_date` and `status` are the new fields. This means the next execution will be on `2022-04-26`, it will call `POST /v0/internal_transfers` with the `request` as the request body. Once it is completed, both `execution_date` and `schedule_date` will be set to `2022-04-28` ### A customer wants to see all the payments from the schedule Refer to [`GET /v0/payment_schedules/payments`](/v2/reference/listpayments) ```shell Shell theme={"system"} curl \ -X GET \ https://api.synctera.com/v0/payment_schedules/payments?schedule_id={PAYMENT_SCHEDULE_ID} \ -H "Authorization: Bearer $apikey" { "payments": [ { "description": "example schedule", "id": "{PAYMENT_SCHEDULE_ID}", "metadata": { "foo": "bar" }, "payment_date": { "execution_date": "2022-04-26", "scheduled_date": "2022-04-26" }, "payment_instruction": { "request": { "amount": 10, "currency": "USD", "originating_account_id": "{ACCOUNT_ID}", "receiving_account_id": "{ACCOUNT_ID}", "type": "ACCOUNT_TO_ACCOUNT" }, "type": "INTERNAL_TRANSFER" }, "payment_schedule_id": "{PAYMENT_SCHEDULE_ID}", "status": "COMPLETED", "transaction_id": "{TRANSACTION_ID}" } ] }' ``` There are a few keys are worth to note: * `description`, `metadata`, and `payment_instruction` are identical as payment schedule at the time of payment is executed. * `payment_date` is the date of the payment is executed * `status` is the enumeration value * `COMPLETED`: The payment is executed successfully, you can use `transaction_id` to retrieve further information via internal transfer endpoint `GET /v0/transactions/posted/{TRANSACTION_ID}` * `ERROR`: The payment execution failed. You should look into `error_details` for further information and make the manual payment. Schedule will NOT retry on any failed payments. ### A customer wants to cancel the future payments of the schedule ```shell Shell theme={"system"} curl \ -X PATCH \ https://api.synctera.com/v0/payment_schedules/{PAYMENT_SCHEDULE_ID} \ -H "Authorization: Bearer $apikey" { "status": "CANCELLED" }' ``` ## Webhook Events There are several events you can subscribe from webhook endpoints * PAYMENT\_SCHEDULE.CREATED: A payment schedule is created. * PAYMENT\_SCHEDULE.UPDATED: A payment schedule is updated. Note that payment execution triggers this event as well because `next_payment_date` will be updated. * PAYMENT\_SCHEDULE.PAYMENT.CREATED: A payment has been executed. # Personal Cards Source: https://docs.synctera.com/v2/docs/personal-cards Cards are an important part of many FinTechs’ business with their customers. They come in many varieties: physical or virtual, debit or credit, and in multiple different products that define the card’s use: transaction limits, when fees are charged, rewards programs, and so on. The Cards API creates and manages cards for your customers over the entire life of a card, from issuing a card through card activation, management, and termination. ## A Card’s Life A card handled in the Synctera platform has many parts of its life: * **Requesting card issuance**, when a FinTech presents a card issuance request for a customer who’s passed Know Your Customer (KYC), an account belonging to the customer, and a card type the customer has asked for. This request goes to Synctera’s card vendor, who will issue the specified card. Note that each account is limited to a single physical card and up to nine active virtual cards. Refer to [Issue Card](/v2/reference/issuecard) * **Presenting the card to the customer**, when the customer gets a physical card delivered to them, or information about the card is digitally presented to the customer through a secure channel. * **Activating the card**, which happens automatically for a virtual card. A physical card requires the customer to give the FinTech information to show that they received the card. The FinTech passes that information through Synctera to our card vendor to activate the card so the customer can start using the card. The customer also sets a personal identification number (PIN) for the card to complete activation. * **Monitoring the card**, when the FinTech is alerted for any irregularities in card use. * **Managing the card**, when the FinTech responds to customer activity, requests, and inquiries, and to any security alerts that come back through monitoring. The Fintech makes changes to the card data and status when appropriate. * **Reissuing the card**, when a new card is issued due to expiration, card damage, loss, card theft, or other situation, and the FinTech requests a new card to replace it. The existing card is either immediately terminated or terminated when the new card is activated, depending on the reissuance reason. * **Suspending the card**, when suspicious activity has been identified, but not confirmed as fraud; when the customer reports their card as lost but requests additional time to attempt to locate their card; or other situations that warrant temporarily blocking use of the card. * **Terminating the card**, when the customer asks to close the card account or when card misuse or theft mandates account termination with no replacement request. The FinTech disables the card. The Cards API endpoints handle the card as it moves through these stages. ```mermaid mermaid theme={"system"} stateDiagram-v2 request : Request card physical : Physical card virtual : Virtual card deliver : Deliver to customer present : Present digitally
to customer activate : Activate card monitor : Monitor card manage : Manage card reissue : Reissue card suspend : Suspend card terminate : Terminate card request --> physical request --> virtual virtual --> present physical --> deliver deliver --> activate present --> monitor activate --> monitor monitor --> manage manage --> reissue manage --> suspend manage --> terminate ``` ## Card Activation Methods There are 3 methods for activating cards: * Activation widget. * `POST /cards/activate` request with a barcode. Refer to [Activate Card](/v2/reference/activatecard) * `PATCH /cards/{card_id}` request . Refer to [Update Card](/v2/reference/updatecard) Typically upon activating a card the user should be prompted to set a PIN on the card. Even virtual cards when used with digital wallets can be prompted for a PIN at a merchant POS. If no PIN is set on a card and a merchant POS requests a PIN, the purchase will be impossible to complete successfully. ### Activation Widget For cards that have the full PAN and CVV printed on them, the customer who receives the card logs into the FinTech app (which uses our widgets described below), selects the option to activate a card, and enters those values to prove that they received the card. These values go to Synctera’s card vendor for card activation. ### Barcode Activation For cards that don’t have the PAN and CVV printed on them (or just have a partial PAN), the card issuer generates a unique barcode value for the card and gives that value to the card fulfillment vendor printing the card. The card printer encodes the barcode string into a code 128 barcode printed on the card or card carrier. The customer receiving the card uses the FinTech app’s section for card activation and scans the barcode. The FinTech converts the barcode back into the string and sends that to the POST /cards/activate endpoint which authenticates card activation through our card vendor. ### PATCH Request Depending on the risk appetite and alternative means of verifying the cardholder has the card in hand, integrators can optionally choose to activate cards using the PATCH /cards/\{card\_id} endpoint. This doesn't require any proof that the customer has the card in hand, so it's up to the integrator to perform any required due diligence to verify and authenticate the user. ## Handling Sensitive Card Information Some card data such as the PAN, CVV, expiration date (EXP) and PIN are sensitive and should be guarded from exposure to anyone except the authorized card holder. This data is exposed not only during card activation, but over the life of the card when the card customer wants to view their card data. To secure sensitive card information, the Payment Card Industry (PCI) Data Security Standard defines steps that must be followed when sending and receiving sensitive information. Your sponsor bank and credit card network require PCI compliance in your application when you handle card business with customers. Getting PCI compliance certification is an involved and expensive process. To provide PCI compliance without you having to go through the compliance process, we provide pre-built widgets and a library that are certified PCI-compliant. These widgets and the library are created by our card vendor, adapted by Synctera to work in our platform, and run within your application to send and receive sensitive data directly between your application and our card vendor. If you are PCI-certified, we also provide direct API access to manage your customers PIN. When your fintech onboards with Synctera, access to the API will be granted upon confirmation of your PCI-certification. ### Initial Card Setup– Synctera provides two PCI-compliant widgets that let your customers activate cards and set up an initial PIN: * The **Activate Card Widget** collects the PAN and CVV from your customer when they activate a card and then securely sends those values to our card vendor. The widget then asks the customer to set a PIN, which it also sends to the card vendor. * The **Set PIN Widget** lets a customer set a card’s PIN and then securely transmits it to our card vendor. This is useful for a barcode-activated card or when a customer wants to reset a PIN. These widgets each display within an HTML iframe element and connect to the card vendor using a single-use token granted for each transaction. If you are PCI-certified the [Card PIN API](/v2/reference/setcardpin) can be used to manage your customer PIN directly. ### Displaying Sensitive Card Data Once a card is active, your customers will want to view information about their cards that includes sensitive card data such as the PAN and CVV. See the [Card Widgets](/v2/docs/card-widgets) guide for more details. ## Resetting PIN Tries If someone incorrectly enters a card’s PIN too many times in a short time period (typically at an ATM or point-of-sale device), our card vendor suspends the card. The card status is set to SUSPENDED, and the card owner will most likely contact your FinTech for assistance. There are several courses of action to take if this occurs: * If you determine that fraud occurred on the card, you should reissue the card. This resets the PIN tries on the new card. * If the customer has forgotten their PIN, they can reset it using the PIN widget in your app. You must update the status of the card from SUSPENDED to ACTIVE so your customer can use the card again. * If the customer remembers their PIN correctly, then you update the status of the card from SUSPENDED to ACTIVE so the customer can use the card again. Note that you can handle status update and card reissuance through the Synctera dashboard if a customer service rep is working with the customer, or you can handle it through the Cards API endpoints if you have your own customer service mechanisms. ## Card Reissuance Scenarios A card may be reissued for many reasons. The card may have expired, the name on the card may need to be changed, or a physical card may be lost or stolen. Each of these scenarios is handled a bit differently to provide the best transition from the existing card to its replacement. These reissuance reasons are defined in the Cards API when you request issuing a replacement card: * **EXPIRATION**: A card is going to expire soon. A new expiration date and CVV are assigned to the replacement card while the PAN remains the same. The old card remains active until the new card is activated or until the expiration date arrives. An expiration reissuance must be requested prior to the actual expiration date. To retrieve cards that are about to expire, you can use the [List Cards](/v2/reference/listcards) endpoint - you can sort cards by expiration date with the `expiration_date` sort argument or filter cards with the `expires_before` filter. From there, you can choose how you want to automate the reissuance. You could, for example, create a background job that reissues cards without any user interaction, or prompt the user to go through a reissuance flow, where they confirm the card shipping address, etc. * **LOST**: The customer has reported the card as lost. The lost card is immediately terminated. The replacement card has a new PAN, CVV, and expiration date, but keeps the same PIN. * **STOLEN**: The customer has reported the card as stolen. The stolen card is immediately terminated. The replacement card has a new PAN, CVV, and expiration date, but keeps the same PIN. * **DAMAGED**: The customer requests a new card to replace a damaged card. A new expiration date and CVV are assigned to the replacement card while the PAN remains the same. The old card remains active until the new card is activated or until the expiration date arrives. * **APPEARANCE**: The customer requests a new card with a different appearance, for example changing the name printed on the card or changing the card's custom image. A new expiration date and CVV are assigned to the replacement card while the PAN remains the same. The old card remains active until the new card is activated or until the expiration date arrives. * **PRODUCT\_CHANGE**: The customer requests converting a card to a different program, specifically debit card to a smart card. A new expiration date and CVV are assigned to the replacement card while the PAN will change since it will be on a new BIN. The old card remains active until the new card is activated or until the expiration date arrives. * **PROGRAM\_CHANGE**: The customer requests converting a card to a different program, specifically debit card to a smart card. A new expiration date and CVV are assigned to the replacement card while the PAN remains the same. The old card remains active until the new card is activated or until the expiration date arrives. In all of these cases, the Synctera platform automatically terminates the old card when it is time for termination. Also, where relevant, Digital wallet tokens are updated automatically, i.e. cardholders to not need to add the new card to the wallet. If the card is already on-file with merchants, cardholders do not need to worry about updating their card-on-file as it is automatically updated. ## Cards API Objects The Cards API works with two primary objects. ### The Card Product Object A card product is a defined set of card features that you can offer to your customers. A card product may define charge limits, foreign transaction fees, reward programs, and other important agreements between you and a customer for card use. When your FinTech onboards with Synctera and works out an agreement with a sponsor bank, if you’re going to use cards, your agreement includes a set of defined card products you can offer to your customers. When we set you up in the Synctera platform, we create a set of Cards API objects, one for each of your card products. Each card product object contains: * The **card product ID**, unique to the card product * The **card product name**. * The **card product form**: whether it’s physical or virtual * **Active/inactive status**, whether the card product is still active or not. Inactive card products can’t be used to request card issuance. When you request a card issuance, you specify a card product by ID so that you and the card issuer know the terms under which the card is issued. ### The Card Object The card object is the Card API’s principal object. Each object defines and tracks a card from issuance request through activation, management, and eventual end of life. A card object has a set of attributes that vary depending on whether the card is virtual or physical. A physical card has to contain information about shipping such as address and shipping status, and for activation of a physical card such as the barcode used for validation. #### Common Attributes Physical and virtual card objects both have these common attributes: * **Card ID** specifies this card object. * **Creation time** specifies the date and time when this card was requested to be issued. * **Last modified time** specifies the date and time when this card object was last modified, whether modified by the integrator or the Synctera platform. * **Form** specifies whether the card is physical or virtual. * **Account, customer, and card product IDs** specify the customer, their account, and the card product associated with the card. * **Embossed name** is the exact name on the card: embossed in the card if physical, just associated with the card if virtual. * **Last four** provides the last four digits of the card’s PAN. * **Expiration month, year, and time** specify at least the standard month and year of expiration and may optionally specify a specific day and time. * **Network** specifies the credit card network that handles the card’s transactions, currently Mastercard. * **Reissue from, to, and reason** provide card reissue information if this is a reissued card: the ID of the card being reissued, the card ID of the replacement (this card), and a reason for the reissuance. * **Metadata** is an optional array of key-value pairs providing additional information about the card. * **Type** specifies whether this is a credit or debit card. It may currently only specify a debit card. * **Status** specifies multiple aspects of a card’s current status: * **Card status** specifies the card’s current stage of life. The platform may set this value as it detects card changes, such as when a card becomes activated. You may also set this status when you find it appropriate. * **Active**: The card is available for full use. * **Unactivated**: The card hasn’t been activated yet and can’t be used. * **Suspended**: The card is suspended and can’t be used again until returned to active status. * **Terminated**: The card may no longer be used. * **Status reason** specifies a code for a defined set of reasons why a card’s status changed. * **Memo** provides your FinTech the option to enter additional details about status change. #### Physical Card Attributes A physical card object has some additional attributes: * **Card fulfillment status** reports whether the card has been issued, ordered, rejected, reordered, or shipped. * **Shipping** provides information about how and where the card should be shipped: * **Address** provides the address to which the card was mailed. If not specified on the issuance request, this defaults to the customer’s shipping address. * **Care of line** is the name of the person who will receive the package on behalf of the recipient. This value is generally used when mailing the card to a location other than the customer’s shipping address. * **Is expedited fulfillment** requests expedited printing of the card by the card fulfillment vendor. Additional fees apply. * **Method** specifies the shipping method and whether or not it’s expedited. If this value is not provided, it defaults to LOCAL\_MAIL. Additional fees apply for all other methods. * **Recipient name** specifies who should receive the card, often used for signature purposes. If not provided, it defaults to the customer’s name. This isn’t the same as the entity specified as “care of,” which is just used as part of the address. * **Tracking number** provides a number used to track a card’s shipment through the carrier. * **Is PIN set** specifies whether the PIN has been set for the card or not. The Synctera platform receives information from the card issuer about shipping status and fills in attributes with received information so you can check on a card’s shipping status by looking at the card object. ## Endpoints The Cards API offers endpoints that handle different aspects of card creation and management. ### Card Products These endpoints provide card product information: * **List Card Products** returns an array of card product objects set up for you when your FinTech onboarded with Synctera. Each object provides a card product ID and card form with optional active/inactive status and card product name. * **Get Details About a Card Product** returns a card product object for a single card product. ### Card Creation These endpoints create an active card for a customer: * **Issue a Card** requests a card for a customer using one of the customer’s accounts and specifying a card product. If a request to this endpoint specifies that this is a card reissuance, the endpoint handles terminating the replaced card. * **Activate a Card** requests the card vendor to activate a physical card using the activation barcode provided by the customer. ### Card Management These endpoints manage a card once it’s issued: * **List Cards** returns an array of card objects representing cards you’ve issued. You can specify query parameters that include customer, account, embossed name, last four digits of the PAN, expiration date, card type, brand, form, card product, and the postal code of the user. Refer to [List Cards](/v2/reference/listcards) * **Get Card** returns a single card object specified by card ID so that you can examine card attributes. Refer to [Get Card](/v2/reference/getcard) * **Update Card** revises a card object’s attributes, limited to attributes that can change over the life of a card. This includes card status, status reason, and metadata stored in the memo attribute. Refer to [Update Card](/v2/reference/updatecard) * **List Card Changes** returns an array of any changes made to a card object’s card status or fulfillment status made either by you or by the Synctera platform. Each change in the array reports the type of change (card or fulfillment), how the change was submitted, optional memo metadata, both the old and new status (card or fulfillment), and the ID of the admin who made the change (if made in the Synctera admin system) and the time the change occurred. Refer to List Card Changes ### Data Security Through Widgets These endpoints provide tokens and connection information for Synctera’s PCI-compliant widgets: * **Get Card Widget URL** returns a URL used by the Synctera Activate Card and Set PIN widgets. * **Get a Client Token** returns a short-term token for use by the syntera.js client library to retrieve sensitive data for display. ## A Typical Card Workflow This workflow is an example of steps covering a card’s life from creation to deactivation. For this example, the card we work with is a physical debit card that activates through a barcode activation value. **Setup:** To create a card, you need a customer that has passed KYC verification and an account that belongs to the customer. ### Requesting Card Issuance 1. You offer a card product to a customer who you think is a promising card candidate. To review the card products available through your FinTech, request a list of them through a request to [List Card Products](/v2/reference/listcardproducts) and note the card product ID of the product you want to offer. 2. The customer signs up for your card product and accepts the card disclosure. Disclosure to the customer is generally handled as part of your account onboarding process, but in some cases may be a separate process. 3. You request a card issuance through [Issue a Card](/v2/reference/issuecard). You specify the customer, the account, the card product, a name to emboss on the card, and optionally provide shipping information for the new card. The endpoint returns the card object, including the card object ID. 4. To check on card issuance status, you regularly request [List Card Changes](/v2/reference/listchanges) to return the card change history of the card object where you can look for new changes. Each change reports shipping and card status changes, so you know when a card was ordered, issued, shipped, or even rejected so you can take action if necessary. ### For customers who have specified a chosen name, you can overwrite the default embossed first and last name by explicitly setting embossed\_name with your customer's chosen and last name. ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram FinTech->>Customer: Offer card product Customer->>FinTech: Sign me up FinTech->>Synctera Platform: "Issue a Card" FinTech->>Synctera Platform: Check card status: "List Card Changes" ``` ### Activating a Card 1. Your customer receives the card, logs into your app to activate the card, and uses their cell phone camera to scan the QR code. 2. Your app translates the QR code into a barcode value. 3. You use [Activate Card](/v2/reference/activatecard) to supply the barcode value and request card activation. 4. The Cards API requests card activation through the card vendor.. 5. You use the Set PIN widget in your app to ask the customer to set a PIN for the card, which they do. 6. The Set PIN widget sends the PIN value to the card vendor. 7. The card vendor activates the card and notifies the Synctera platform. 8. The Synctera platform sets the corresponding card object’s status to ACTIVE. ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram Customer->>FinTech: Scan QR code on card FinTech->>FinTech: Translate QR code to barcode value FinTech->>Synctera Platform: Send barcode value:
"Activate Card" Synctera Platform->>Card Vendor: Activate card Customer->>FinTech: Set PIN through widget FinTech->>Card Vendor: Widget sends PIN setting Card Vendor->>Card Vendor: Activate card Card Vendor->>Synctera Platform: Card is active Synctera Platform->>Synctera Platform: Card status: ACTIVE ``` ### Reissuing a Card 1. Your customer reports that they lost the card. 2. You request a card reissuance through [Issue a Card](/v2/reference/issuecard). You provide all the information you did when you issued the lost card, and also specify a reason for reissuance and the card ID of the lost card as the card being replaced. (Note that you can also use the Synctera dashboard to perform this task.) 3. The Synctera platform immediately terminates the lost card with the card vendor and sets the card’s status to TERMINATED. 4. The new card is issued and activated just as the lost card was, except for the PIN which is retained from the lost card. ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram Customer->>FinTech: I lost my card FinTech->>Synctera Platform: "Issue a Card"
to replace lost card Synctera Platform->>Card Vendor: Terminate card Card Vendor->>Card Vendor: Terminate card Synctera Platform->>Synctera Platform: Set card to "TERMINATED" Synctera Platform->>Card Vendor: Issue new card Card Vendor->>Customer: Issue new card with old PIN ``` ### Cancelling a Card 1. The customer cancels the card. 2. You use [Update Card](/v2/reference/updatecard) to change the card’s status to TERMINATED. (Note that you can also use the Synctera dashboard to perform this task.) 3. The Synctera platform notifies the card vendor of termination. 4. The card vendor terminates the card. ```mermaid mermaid theme={"system"} %%{init: {"fontFamily": "sans-serif"}}%% sequenceDiagram Customer->>FinTech: Cancel my card FinTech->>Synctera Platform: "Update Card" to
TERMINATED status Synctera Platform->>Card Vendor: Terminate card Card Vendor->>Card Vendor: Terminate card ``` # Plaid Core Exchange Source: https://docs.synctera.com/v2/docs/plaid-exchange-guide ## Plaid Core Exchange with Synctera Synctera has integrated with Plaid Core Exchange in our v1 API. Please refer to the [v1 guide](/v1/docs/plaid-exchange-guide) for details. # Synctera Platform Source: https://docs.synctera.com/v2/docs/platform-overview You’re a developer about to integrate the Synctera platform with your application. ## A Synctera Platform Overview for FinTechs Before you start, what is the Synctera platform anyway? What does it offer, and how do you work with it? ### The Synctera Platform in a Nutshell The Synctera platform is a comprehensive set of cloud-based financial services that brings three types of businesses together: * **FinTechs** that provide unique financial services to their customers * **Sponsor banks** that provide the necessary legal framework and financial resources to FinTechs to carry out FinTech business * **Service vendors** that team up with Synctera to provide fundamental financial services to FinTechs and sponsor banks. The basic architecture of the Synctera platform. Synctera provides a unified platform that manages interactions between FinTechs and sponsor banks. It consolidates a variety of essential services such as accounts and ledger, card issuance and management, money movement, and risk management under central control through a family of APIs and the Synctera Dashboard. #### FinTechs and Sponsor Banks The first step in a FinTech’s relationship with Synctera is onboarding to Synctera. During the onboarding process, Synctera helps determine the banking resources the FinTech requires, find a sponsor bank that can provide those resources, and works to establish a business relationship between both parties. Once a FinTech has connected with a sponsor bank, the Synctera platform provides services that help the FinTech and sponsor bank communicate essential information to each other as they carry out business together. The FinTech can, for example, reconcile the transactions its customers carry out with the customers’ accounts held by the sponsor bank so that the FinTech and the bank’s records agree. Or the FinTech can communicate actions it takes to ensure compliance with banking laws so the sponsor bank knows that their mutual business doesn’t risk breaking those laws. #### Synctera Services In addition to the connection between a sponsor bank and a Fintech, the Synctera platform services are implemented and provided by Synctera and our vendor partners. Synctera’s native services include setting up customers and accounts, reconciling FinTech transactions with a sponsor bank, reporting compliance activities, and so on. Synctera depends on vendor partners to provide more specialized services that include creating debit cards, performing know-your-customer (KYC) checks on potential customers before signup, performing debit card transactions, and more. These vendor services are all available through the Synctera platform without requiring external setup, contract negotiation, or connections. #### Synctera Products To use Synctera services, a FinTech subscribes to one or more Synctera products via the sponsor bank. Each product provides access to services that address a particular business case. FinTechs can pick and choose products to fit their requirements. A FinTech that carries out its own KYC may, for example, opt not to use Synctera KYC products, but may decide to use Synctera ledger and card products to issue and manage debit cards. Synctera offers products that provide, among other things: * Basic financial services such as ledger and customer views * Card services such as debit card issuance and processing * Money movement services such as ACH transactions and mobile Remote Deposit Capture (mRDC) * Risk services such as KYC, Document Verification, and Transaction Fraud monitoring ### Platform Interfaces The Synctera Platform provides two main interfaces to a FinTech: * The [Synctera APIs](/v2/reference) for direct application access to the platform * The Synctera dashboard for human access to the platform Use the Synctera APIs to integrate Synctera services with your applications, then use the Synctera dashboard for executives, administrators, operators, and your customer care staff to work with those services. The dashboard lets you oversee and gain insights into your business. #### Synctera APIs The Synctera APIs are RESTful APIs. They include a set of basic service APIs: * The [**Customers API**](/v2/reference/listcustomers), which creates and manages records for many types of customers that include information about customer employment and risk ratings. * The [**Accounts API**](/v2/reference/listaccounts), which creates and manages customer accounts and relationships between customers and accounts. A set of risk management APIs: * The [**KYC Verification API**](/v2/reference/listverifications1), which can create and manage documentation for a customer and run verification checks through a vendor service to ensure that a customer is valid. * The [**Disclosures API**](/v2/reference/listdisclosures), which handles legally required disclosures to customers. * The [**Watchlist API**](/v2/reference/createsubscription), which subscribes customers to security watchlists and handles watchlist alerts. A set of money movement APIs: * The [**Transactions API**](/v2/reference/gettransactionsbatchpayments), which creates, manages, and lists Automated Clearing House (ACH) transfers between internal and external accounts. * The **Remote Check Deposit API**, which handles remote check deposit transactions, including working with the captured images for deposits. A set of card management APIs: * The [**Cards API**](/v2/reference/listcards), which issues, activates, and manages cards for customers. * The [**Card Transaction Simulations API**](/v2/reference/simulateauthorization), only available in the sandbox, which simulates various card transactions so you can generate transaction events to test your application features such as customer alerts and balance updates (if your application provides the account ledger). Access to these APIs in production depends on the Synctera products to which you’re subscribed. #### The Synctera Dashboard The Synctera dashboard is a browser-based user interface that humans in both a FinTech and its sponsor bank can use to work with integrated Synctera features. The dashboard has three views: * The **platform view** provides displays and controls that allow operators such as customer service staff to handle actions like updating customer information, viewing customer risk assessments, requesting card reissuance, and so on. * The **administrator view** provides displays and controls that FinTech and sponsor bank administrators can use to set up and manage operators and to manage Synctera service operations. Developers can also use the admin page to manage their API integration and API keys, review error logs, check API performance, manage webhooks, and so on. ### Development and Deployment Synctera provides two environments for successful integration: * The **Synctera sandbox** provides a place to test integration without real world consequences. It offers full access to all Synctera APIs where requests are fulfilled without incurring expenses for underlying vendor services or communications with outside entities such as the sponsor bank. It connects to underlying vendor sandboxes to test services involving their services. * The **production environment** where a successfully tested integration moves to conduct business with the real world with real financial and legal consequences. We also provide an SDK, full API documentation, and developer support through our Synctera Community Slack account that you can join at [https://launchpass.com/synctera-community](https://launchpass.com/synctera-community). ### Getting Started It’s easy to give our platform a try. [Sign up for a Synctera account](https://app.synctera.com) and learn how to play in our sandbox. # Add POD Beneficiaries to an Account Source: https://docs.synctera.com/v2/docs/pod-beneficiaries Designate one or more payable-on-death (POD) beneficiaries on an account. A beneficiary is a person linked to the account by a relationship, each entitled to an allocated percentage of the account funds. ## Overview Subject to bank approval, a customer can designate beneficiaries of their account. This is commonly known as a **payable-on-death (POD)** designation: on the account holder's death, the balance passes to the named beneficiaries in the allocated proportions. In the Synctera platform a beneficiary is modeled as: * A **person** holding the beneficiary's identification (name, date of birth, SSN, contact information). Beneficiaries are not customers of the bank, so they are stored as `PROSPECT`s and are not run through KYC. * An **account relationship** of type `BENEFICIARY` linking that person to the account and carrying the `ownership_percentage` the beneficiary is entitled to. Key characteristics: * Reuses the existing [Persons](/v2/docs/create-a-personal-customer) and account [Relationships](/v2/reference/createaccountrelationship) APIs; no special endpoint. * Each `BENEFICIARY` relationship carries an `ownership_percentage`. An account can have multiple beneficiaries whose percentages represent the share of funds each is entitled to receive. ## Prerequisites This guide assumes you are familiar with: * [Need to Know — Environments](/v2/reference/need-to-know#environments) * [Need to Know — Authentication](/v2/reference/need-to-know#authentication) It also assumes you have already created a [personal](/v2/docs/create-a-personal-customer) or [business](/v2/docs/create-a-business) customer and [opened an account](/v2/docs/create-accounts-guide) for them. The curl examples authenticate with an `apikey` environment variable. Some examples depend on identifiers generated by previous steps; these are shown as placeholders like `{ACCOUNT_ID}`. ## The account relationship object A `BENEFICIARY` designation is an account relationship with the following key fields: | Field | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------- | | `id` | Unique identifier of the relationship (read-only, assigned on creation). Used for `GET`, `PUT`, and `DELETE`. | | `relationship_type` | The kind of relationship. Set to `BENEFICIARY` for a POD designation. | | `customer_id` | The person linked to the account as the beneficiary. | | `ownership_percentage` | The share of funds the beneficiary is entitled to receive (0–100). | | `created_at` | Date and time the relationship was created (read-only). | ```json theme={"system"} { "id": "5f4ff599-7c29-4f69-a3d9-e103e151afbd", "relationship_type": "BENEFICIARY", "customer_id": "3b1e...", "ownership_percentage": 50, "created_at": "2026-08-26T18:09:12.881517Z" } ``` See the [API reference](/v2/reference/createaccountrelationship) for the full request and response schemas. ## Adding a beneficiary Collect at a minimum the beneficiary's name and contact information, and create a person with [POST /v2/persons](/v2/reference/createperson). ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/persons \ --data-binary ' { "status": "PROSPECT", "is_customer": false, "first_name": "Jordan", "last_name": "Rivera", "dob": "1990-08-21", "ssn": "123-45-6789", "email": "jordan@example.com", "phone_number": "+12124567890", "legal_address": { "address_line_1": "50 Main St", "city": "New York", "state": "NY", "postal_code": "12345", "country_code": "US" } }' ``` The response includes the system-generated `id`, used to link the beneficiary to the account: ```json theme={"system"} { "id": "{BENEFICIARY_PERSON_ID}", "status": "PROSPECT", "verification_status": "UNVERIFIED", "is_customer": false, "first_name": "Jordan", "last_name": "Rivera" } ``` Beneficiaries are prospects, not customers. They do not need to pass KYC, so there is no verification step. Create an account relationship of type `BENEFICIARY` with [POST /v2/accounts/\{ACCOUNT\_ID}/relationships](/v2/reference/createaccountrelationship). Provide the beneficiary's person ID in `customer_id`, and use `ownership_percentage` to record the share of funds they are entitled to. ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/accounts/{ACCOUNT_ID}/relationships \ --data-binary ' { "relationship_type": "BENEFICIARY", "customer_id": "{BENEFICIARY_PERSON_ID}", "ownership_percentage": 50 }' ``` The response returns the created relationship: ```json theme={"system"} { "id": "{RELATIONSHIP_ID}", "relationship_type": "BENEFICIARY", "customer_id": "{BENEFICIARY_PERSON_ID}", "ownership_percentage": 50, "created_at": "2026-08-26T18:09:12.881517Z" } ``` Repeat both steps for each additional beneficiary. For example, a second beneficiary with `"ownership_percentage": 50` splits the account evenly between the two. ## Managing beneficiaries ### List beneficiaries on an account Use [GET /v2/accounts/\{ACCOUNT\_ID}/relationships](/v2/reference/listaccountrelationship) to retrieve all relationships for an account, then filter for a `relationship_type` of `BENEFICIARY`: ```shell theme={"system"} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.synctera.com/v2/accounts/{ACCOUNT_ID}/relationships ``` ### Edit a beneficiary's details Beneficiary identification lives on the person resource. Patch it with [PATCH /v2/persons/\{PERSON\_ID}](/v2/reference/updateperson): ```shell theme={"system"} curl \ -X PATCH \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/persons/{BENEFICIARY_PERSON_ID} \ --data-binary ' { "phone_number": "+13105550000" }' ``` ### Change a beneficiary's percentage Update the `ownership_percentage` on the account relationship with [PUT /v2/accounts/\{ACCOUNT\_ID}/relationships/\{RELATIONSHIP\_ID}](/v2/reference/updateaccountrelationship): ```shell theme={"system"} curl \ -X PUT \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/accounts/{ACCOUNT_ID}/relationships/{RELATIONSHIP_ID} \ --data-binary ' { "relationship_type": "BENEFICIARY", "customer_id": "{BENEFICIARY_PERSON_ID}", "ownership_percentage": 75 }' ``` ### Remove a beneficiary Delete the account relationship with [DELETE /v2/accounts/\{ACCOUNT\_ID}/relationships/\{RELATIONSHIP\_ID}](/v2/reference/deleteaccountrelationship). This removes the POD designation; the person resource is unaffected. ```shell theme={"system"} curl \ -X DELETE \ -H "Authorization: Bearer $apikey" \ https://api.synctera.com/v2/accounts/{ACCOUNT_ID}/relationships/{RELATIONSHIP_ID} ``` ## Best practices Beneficiary designations are subject to bank approval. Confirm your program supports POD designations before exposing the flow to customers. * **Collect full identification** — capture name, date of birth, SSN, and contact information so the beneficiary can be identified when funds are disbursed. * **Keep allocations consistent** — track each beneficiary's `ownership_percentage` so totals reflect your program's rules for splitting funds. * **Reuse people where possible** — if a beneficiary already exists as a person, link the existing `id` instead of creating a duplicate. * **Treat PII carefully** — expect vaulted fields like `ssn` to be returned masked, and never log full values. ## Related guides Create the person resource used to represent a beneficiary. Open the account that beneficiaries are designated on. ## API reference * [Create an account relationship](/v2/reference/createaccountrelationship) * [List account relationships](/v2/reference/listaccountrelationship) * [Update an account relationship](/v2/reference/updateaccountrelationship) * [Delete an account relationship](/v2/reference/deleteaccountrelationship) * [Create a person](/v2/reference/createperson) * [Update a person](/v2/reference/updateperson) # Record Disclosure Acceptance Source: https://docs.synctera.com/v2/docs/record-disclosure-acceptance Disclosures record that you told a customer about the laws and regulations that affect them — the auditable proof that required regulatory information was disclosed. ## Overview An important part of onboarding a customer is *disclosing* regulatory information to them, such as terms of service or privacy notices. Banks and regulators need to verify these disclosures were made, so Synctera keeps a **disclosure record** (usually just called a *disclosure*) for every disclosure you make to every customer. **A disclosure record** captures which customer was told what, and how they interacted with it. It links a customer to a specific *disclosure document* — identified by a `type` and `version` — at a point in time. Key characteristics: * **Scoped** — each disclosure is tied to a customer via `person_id` or `business_id`. * **Documented** — `type` and `version` together identify the exact disclosure document that was presented. * **Interaction-aware** — `event_type` records the customer's level of interaction (e.g. `DISPLAYED`, `ACKNOWLEDGED`). * **Auditable** — each record is timestamped with a `disclosure_date` and retained for compliance review. A disclosure record is metadata — it captures *that* a disclosure was made, not the document text itself. To store the text the customer agreed to, upload it to [Document Storage](/v2/docs/document-storage-guide) and reference it from the disclosure with `document_id`. See [Linking to the document text](#linking-to-the-document-text). ### When to use disclosures * **During onboarding** — record that a customer acknowledged terms of service, privacy notices, or e-sign consent before they transact. * **Beneficial ownership certification** — record an `OWNER_CERTIFICATION` when an agent certifies a business's ownership information. See [Create a Business Customer](/v2/docs/create-a-business). * **Ongoing regulatory disclosures** — record `REG_E`, `REG_CC`, and similar disclosures as your product requires them. ## Prerequisites This guide assumes you have: * Created a [personal customer](/v2/docs/create-a-personal-customer) or [business customer](/v2/docs/create-a-business) You should also be familiar with: * [Need to Know — Environments](/v2/reference/need-to-know#environments) * [Need to Know — Authentication](/v2/reference/need-to-know#authentication) ## The disclosure object A disclosure contains the following key fields: | Field | Description | | ------------------------- | -------------------------------------------------------------------------------------------------------------------- | | `id` | Unique identifier (read-only, assigned on creation). | | `person_id` | The personal customer the disclosure applies to. Provide this **or** `business_id`. | | `business_id` | The business customer the disclosure applies to. Provide this **or** `person_id`. | | `acknowledging_person_id` | The person who acknowledged the disclosure (used for business disclosures, e.g. an agent certifying ownership). | | `type` | **Required.** The regulatory requirement that triggered the disclosure (e.g. `REG_DD`). | | `version` | **Required.** The revision of the disclosed document. Together with `type`, identifies the disclosure document. | | `event_type` | The customer's level of interaction (e.g. `DISPLAYED`, `ACKNOWLEDGED`). | | `disclosure_date` | When the disclosure was made to the customer. | | `document_id` | Reference to the document the customer agreed to. See [Linking to the document text](#linking-to-the-document-text). | ```json theme={"system"} { "id": "08a27c6b-b55f-42c3-8805-f5ad442b0312", "person_id": "e72f1f20-7a95-4b19-aafc-c73f868183e7", "type": "REG_DD", "version": "1.0", "event_type": "ACKNOWLEDGED", "disclosure_date": "2022-03-17T17:04:34Z", "creation_time": "2022-04-05T23:29:42.436824Z", "last_updated_time": "2022-04-05T23:29:42.436824Z" } ``` ### Available disclosure documents Together, `type` and `version` uniquely specify a disclosure document. If the combination does not already exist in Synctera's system, the request returns an error. You should have a default set of documents available: | Disclosure type | Document version | | ---------------------- | ---------------- | | `REG_DD` | 1.0 | | `KYC_DATA_COLLECTION` | 1.0 | | `REG_E` | 1.0 | | `REG_CC` | 1.0 | | `E_SIGN` | 1.0 | | `PRIVACY_NOTICE` | 1.0 | | `TERMS_AND_CONDITIONS` | 1.0 | You may not need every disclosure type — Synctera's compliance team can advise. The `type` and `event_type` fields are fully described in the [API reference](/v2/reference/createdisclosure). ## Managing disclosures After you present a document to a customer for them to read and accept, record it with [POST /v2/disclosures](/v2/reference/createdisclosure), passing the `person_id`: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/disclosures \ --data-binary ' { "person_id": "e72f1f20-7a95-4b19-aafc-c73f868183e7", "type": "REG_DD", "version": "1.0", "event_type": "ACKNOWLEDGED", "disclosure_date": "2022-03-17T17:04:34Z" }' ``` On success the endpoint returns `201 Created` with the new record, including its unique `id`: ```json theme={"system"} { "id": "08a27c6b-b55f-42c3-8805-f5ad442b0312", "person_id": "e72f1f20-7a95-4b19-aafc-c73f868183e7", "type": "REG_DD", "version": "1.0", "event_type": "ACKNOWLEDGED", "disclosure_date": "2022-03-17T17:04:34Z", "creation_time": "2022-04-05T23:29:42.436824Z", "last_updated_time": "2022-04-05T23:29:42.436824Z" } ``` For a business, specify `business_id` instead of `person_id`. Use `acknowledging_person_id` to record which person acknowledged it on the business's behalf: ```shell theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ https://api.synctera.com/v2/disclosures \ --data-binary ' { "business_id": "d894d64b-d513-42f2-9b3a-2cd5989b6ef8", "type": "REG_E", "version": "1.1", "event_type": "DISPLAYED", "disclosure_date": "2022-04-03T10:43:12Z" }' ``` Retrieve a paginated list of all disclosure records across your customer base with [GET /v2/disclosures](/v2/reference/listdisclosures): ```shell theme={"system"} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.synctera.com/v2/disclosures ``` Filter by `person_id` or `business_id` to limit the results to a single customer: ```shell theme={"system"} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ "https://api.synctera.com/v2/disclosures?person_id={person_id}" ``` Fetch a single record by ID with [GET /v2/disclosures/\{disclosure\_id}](/v2/reference/getdisclosure): ```shell theme={"system"} curl \ -X GET \ -H "Authorization: Bearer $apikey" \ https://api.synctera.com/v2/disclosures/{disclosure_id} ``` ### Linking to the document text Use the [`document_id`](/v2/reference/createdisclosure#body-document-id) field to reference the exact document text the customer agreed to. Upload that text to [Document Storage](/v2/docs/document-storage-guide), then set `document_id` to the `id` returned by the upload. Because the document lives in Synctera's document storage, the disclosure record can always be traced back to the exact text the customer saw — retrieve it later with [GET /v2/documents/\{document\_id}/contents](/v2/reference/getdocument). ## Best practices A disclosure record is your evidence that a required disclosure was made. Create the record as soon as the customer interacts with the document, and never back-date `disclosure_date`. * **Match `type` and `version` to a real document** — mismatched combinations are rejected; keep your document versions in sync with Synctera's available documents. * **Link the document text** — upload the disclosure text to [Document Storage](/v2/docs/document-storage-guide) and set [`document_id`](/v2/reference/createdisclosure#body-document-id) so the record ties directly to what the customer saw. * **Record the right `event_type`** — distinguish `DISPLAYED` from `ACKNOWLEDGED` so your audit trail reflects what actually happened. * **Attribute business disclosures** — set `acknowledging_person_id` so you know which agent acted on the business's behalf. * **Confirm scope with compliance** — work with Synctera's compliance team to determine exactly which disclosures your product requires. ## Related guides Record disclosures as part of onboarding a person. Capture beneficial ownership certification and business disclosures. Verify customer identity alongside recording disclosures. Upload the disclosure text and link it via `document_id`. ## API reference * [Create a disclosure](/v2/reference/createdisclosure) * [List disclosures](/v2/reference/listdisclosures) * [Get a disclosure](/v2/reference/getdisclosure) # Sandbox Test Cases Source: https://docs.synctera.com/v2/docs/sandbox-test-cases ## KYB Test Scenarios These test cases are intended to be used with the [KYC/KYB Verification](/v2/docs/kyc-kyb-verification) guide to demonstrate multiple possible flows. | Specific Test Attribute | Specific Attribute Value | Expected Outcome | Expected Outcome Description | | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Name | Unregistered Business | Rejected | The business has no Secretary of State filings. The Business returned will have no associated registrations. | | Name | Similar Name Business | Review | The business has a Secretary of State filing with a similar name to the submitted business name. The "name" review task indicates that a similar name was found to the submitted name. | | Address | 123 Grand St., New York, NY 10013 | Rejected | Unable to identify a match to the submitted Office Address. The submitted address is not found to match any address listed in Business records. | | Address | 223 Grand St., New York, NY 10013 | Review | Identified a similar address. The submitted address is similar to an address that has been found. | | Address | 423 Grand St., New York, NY 10013 | Review | Identified an approximate address. Identified an address within 0.2 miles of the submitted Office Address | | Address | Include "cmra" in address\_line1 or full\_address (i.e 991 cmra st., New York, NY 10013") | Review | Identified a CMRA address. Submitted Office Address is zoned by USPS as a Commercial Mail Receiving Agency | | Address | Include "registered agent" in address\_line1 or full\_address (i.e 991 registered agent st., New York, NY 10013") | Review | "Identified a Registered Agent address: | | Submitted Office Address is actually the address of a Registered Agent, not the actual business" | | | | | Address | Include "undeliverable" in address\_line1 or full\_address (i.e 991 st. undeliverable, New York, NY 10013" | Rejected | "Identified an Undeliverable address: | | The USPS is unable to deliver mail to the submitted Office Address" | | | | | TIN | 110000099 | Rejected | TIN Name mismatch. The submitted TIN was found to be associated with a different entity name. | | TIN | 111222333 | Rejected | TIN Name unknown. The submitted TIN's status is unknown. | | Bankruptcy | A business name containing the word bankruptcy | Rejected | The business will have a bankruptcy. The Business will have a bankruptcy attached. | | Watchlist | A Business name or Person name containing the phrase watchlist hit. | Rejected | The business or person will have a watchlist hit on them | | Industry Classification | Any website | Accepted | The business' website will have an industry classification | | Industry Classification | A website containing the words `highrisk` | Review | The business' website will have an industry classification with a high risk result. | | SOS Filings Domestic | Business Name = "Domestic Missing" | Rejected | Missing Domestic Secretary of State Filing: The business has no domestic filing | | SOS Filings Domestic | Business Name = "Domestic Inactive" | Review | Domestic Secretary of State Filing is Inactive: Inactive domestic filing found | | SOS Filings Domestic | Business Name = "Domestic Unknown" | Review | Unable to detect status of Domestic Filing: No domestic filing status provided | | Liens Found | Business Name = "liens found" | Review | The liens search will return records for this business | | Any | Any | Accepted | Verified. If none of the above inputs match, the Business will fallback to verifying all information. Given most inputs then, you can expect to receive a Review object with successful tasks. | ## KYC Test Scenarios These test cases are intended to be used with the [KYC/KYB Verification](/v2/docs/kyc-kyb-verification) guide to demonstrate multiple possible flows. ### Test data Each accordion contains a ready-to-use person creation request. All scenarios use the same verification request, shown at the end. ```json theme={"system"} { "first_name": "Jerri", "last_name": "Hogarth", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "12620 PADDINGTON AVE", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10001", "country_code": "US" }, "dob": "1976-08-09", "ssn": "293-00-1642", "email": "hogarthandassoc@example.com", "phone_number": "+12125554549", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Foggy", "last_name": "Nelstein", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "1456 Holman Rd Apt 192", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10001", "country_code": "US" }, "dob": "1981-01-29", "ssn": "600-00-2071", "email": "nelsonandmurdock@example.com", "phone_number": "+19105553605", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Patsy", "last_name": "Walker", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "3092 HUDSON ST 7TH FL", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10014", "country_code": "US" }, "dob": "1981-01-29", "ssn": "600-00-2071", "email": "TWALKER@EXAMPLE.COM", "phone_number": "+12125552916", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Wilson", "last_name": "Fisk", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "3116 S 4TH ST", "address_line_2": "", "city": "Brooklyn", "state": "NY", "postal_code": "11211", "country_code": "US" }, "dob": "1981-01-29", "ssn": "600-00-2071", "email": "MR.FISK@EXAMPLE.COM", "phone_number": "+12125550921", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Staniel", "last_name": "Rand", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "82 CORPORATION AVE", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10013", "country_code": "US" }, "dob": "1981-01-29", "ssn": "600-00-2071", "email": "d.s.rand@example.co", "phone_number": "+12125556698", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Jessica", "last_name": "Jones", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "5035 W 43RD ST", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10036", "country_code": "US" }, "dob": "1981-01-29", "ssn": "600-00-2071", "email": "jjones1010@example.com", "phone_number": "+12125550412", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Madam", "last_name": "Gao", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "130 IRONSIDE ST.", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10001", "country_code": "US" }, "dob": "1981-01-29", "ssn": "600-00-2071", "email": "madam.g@example.com", "phone_number": "+12125556698", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Frank", "last_name": "Castle", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "2243 W 43RD ST", "address_line_2": "", "city": "New York", "state": "NY", "postal_code": "10036", "country_code": "US" }, "dob": "1973-09-22", "ssn": "234-00-0168", "email": "madam.g@example.com", "phone_number": "+12125556698", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Colleen", "last_name": "Wing", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "2922 HUNTINGTON DRIVE", "address_line_2": "", "city": "Forest Grove", "state": "OR", "postal_code": "97123", "country_code": "US" }, "dob": "1987-11-11", "ssn": "732-00-4625", "email": "madam.g@example.com", "phone_number": "+15035557811", "status": "ACTIVE", "is_customer": true } ``` ```json theme={"system"} { "first_name": "Jane", "last_name": "Doe", "legal_address": { "default_address_flg": true, "type": "home", "address_line_1": "831 SW Zachary Walks Crest E", "address_line_2": "", "city": "Lake Patriciabury", "state": "TN", "postal_code": "83192", "country_code": "US" }, "dob": "2001-08-04", "ssn": "585-50-6107", "email": "test@example.com", "phone_number": "+14786011896", "status": "ACTIVE", "is_customer": true } ``` **Verification request** — identical for every scenario. ```json theme={"system"} { "person_id": "{{person_id}}", "customer_ip_address": "24.21.33.212", "customer_consent": true } ``` ## Plaid Test Scenarios These test cases are intended to be used with the [external accounts](/v2/docs/external-accounts-guide) guide to demonstrate multiple possible flows. ### Instant Auth Testing Testing Scenarios | Username | Password | Pin | MFA Code | Answer | Institution | Scenario | | -------------------------------------------------------- | ----------------------------------------- | ---------------- | -------- | --------------- | ----------- | ------------------------------------------------------------------------------------------------------ | | user\_good | pass\_good | credential\_good | | | | Successful Linking via Instant Auth | | user\_good | mfa\_device | | 1234 | | | Successful Linking via Instant Auth with MFA Code | | user\_good | mfa\_selections | | | Yes | | Successful Linking via Instant Auth with MFA Selections | | user\_good | mfa*questions*\_ | | | answer\*\* | | "Successful Linking via Instant Auth with MFA Questions | | n-rounds of m-questions per round, where 0 \<= i, j \< 9 | | | | | | | | answer\*\*\*, for j-th question in i-th round."\* | | | | | | | | user\_good | mfa*selections* | | | answer\_1\_1\_0 | | "Successful Linking via Instant Auth with Multiple MFA Selections | | n-rounds of m-questions with o-answers per question | | | | | | | | 0 \< n, m \< 10 and 2 \<= o \< 10 | | | | | | | | answer\_0, for m-th question in n-th round" | | | | | | | | user\_good | error\_COUNTRY\_NOT\_SUPPORTED | | | | | Error Scenario where the country is not supported | | user\_good | error\_INSTITUTION\_DOWN | | | | | Error scenario where the institution is down and the accounts cannot be gathered | | user\_good | error\_INSTITUTION\_NOT\_RESPONDING | | | | | Error scenario where the institution is not responding and the accounts cannot be gathered | | user\_good | error\_INSTITUTION\_NO\_LONGER\_SUPPORTED | | | | | Error scenario where the institution is longer supported so accounts cannot be linked | | user\_good | error\_INSUFFICIENT\_CREDENTIALS | | | | | Error scenario where the user hasn't provided sufficient credentials and the accounts cannot be linked | | user\_good | error\_INTERNAL\_SERVER\_ERROR | | | | | Error scenario where there's been an internal server error at Plaid | | user\_good | error\_INVALID\_CREDENTIALS | | | | | Error scenario where the user has entered invalid credentials | | user\_good | error\_INVALID\_MFA | | | | | Error scenario where the user has entered invalid MFA responses | | user\_good | error\_INVALID\_SEND\_METHOD | | | | | | | user\_good | error\_ITEM\_LOCKED | | | | | | | user\_good | error\_ITEM\_NOT\_SUPPORTED | | | | | | | user\_good | error\_MFA\_NOT\_SUPPORTED | | | | | | | user\_good | error\_NO\_ACCOUNTS | | | | | Error scenario where there are no valid accounts to pull back from the institution | | user\_good | error\_PAYMENT\_INVALID\_RECIPIENT | | | | | | | user\_good | error\_PRODUCTS\_NOT\_SUPPORTED | | | | | Error scenario where the requested products are not supported by the institution being linked | | user\_good | error\_USER\_SETUP\_REQUIRED | | | | | | ### Instant Match Testing Scenarios | Username | Password | Account | Routing Number | Account Number | Institution | Scenario | | ---------- | ---------- | -------------------- | -------------- | ---------------- | ---------------- | ------------------------------------ | | user\_good | pass\_good | Plaid (\*\*\*\*1111) | 11401533 | 1111222233331111 | Houndstooth Bank | Successful Linking via Instant Match | | user\_good | pass\_good | Plaid (\*\*\*\*1111) | 21000021 | 1111222233331111 | Houndstooth Bank | Successful Linking via Instant Match | ### Micro Deposit Testing Scenarios | Username | Password | Account | Routing Number | Account Number | Institution | Micro Deposit Amount 1 | Micro Deposit Amount 2 | Scenario | | -------- | -------- | -------- | -------------- | ---------------- | ----------- | ---------------------- | ---------------------- | ----------------------------------- | | N/A | N/A | Checking | 110000000 | 1111222233330000 | N/A | \$0.01 | \$0.02 | Micro Deposits for Checking Account | | N/A | N/A | Savings | 110000000 | 1111222233330000 | N/A | \$0.01 | \$0.02 | Micro Deposits for Savings Account | # Sandbox Testing Source: https://docs.synctera.com/v2/docs/sandbox-testing Triggering specific scenarios and building mock vendors to end-to-end test can be time consuming. ### Overview Synctera's sandbox provides a few tools to help speed up testing so you can build resilient, polished apps. We provide some capabilities described here to make sure that your sandbox experience is realistic and productive. Leveraging these tools enables integrators to run end-to-end tests against the Synctera sandbox environment. ## Funding your Sandbox Accounts There are a few options available to provide "fake funds" for your sandbox accounts. 1. You can transfer funds via an account-to-account transfer from the "New Funding Account" internal account. This account exists in Sandbox for this purpose and so that you can also track your sandbox fund flows from this originating internal account. For example: ```bash theme={"system"} curl \ -X POST \ -H "Authorization: Bearer $apikey" \ -H "Content-Type: application/json" \ https://api.synctera.com/v0/transactions/internal_transfer \ --data-binary ' { "amount": 1025, "currency": "USD", "originating_account_id": "35c1a55e-4510-458d-9345-fe08121b5654", "receiving_account_id": "c8ddc14b-33be-447a-820d-3fe59ad49028", "type": "ACCOUNT_TO_ACCOUNT" }' ``` (in this example, the `originating_account_id` is the account id of the New Funding Account, and the receiving account is the account which you want to fund) 2. Funding through an [externally linked account](/v2/docs/external-accounts-guide). If you link an external account in the Sandbox you can then do an ACH transfer from this account to the receiving account in the sandbox. This option requires a few more steps to get to funding but does test a more realistic customer facing flow to load funds into an account. ## Simulations Our platform allows you to test various types of real world scenarios in the sandbox to help you see realistic patterns and activities before going live. ### Simulating Risk Events Testing positive and negative flows for risk is important. Triggers for specific flows such as KYC failure or a Watchlist can be found in the [sandbox test cases document](/v2/docs/sandbox-test-cases#kyc-test-scenarios). ### Simulating Card Transactions You can trigger typical card activities in our platform. Triggers to simulate inbound transactions can be found in our [simulations api reference](/v2/reference/simulateauthorization). ## Sandbox Wipe Testing different scenarios and flows may require a periodic reset of your sandbox data. We offer this as a feature to make it easier to manage your sandbox environment. ## Wiping Sandbox Data Customer data can be reset using the sandbox wipe feature described below. The following request will programmatically wipe sandbox: ```bash theme={"system"} curl \ -X POST \ https://api-sandbox.synctera.com/v0/wipe \ -H "Authorization: Bearer $apikey" ``` The `curl` example mentioned above assumes that you have set up `apikey` environment variables. See [Authentication](/v2/reference/need-to-know#authentication) for instructions. Currently, this only runs in sandbox and cannot run in PROD. ### Data That Will Be Wiped Sandbox wipe will delete customer data but keep configuration data. The following resources will be wiped: * Accounts * Account applications * Account products (interest) * ACH * Businesses * Cards * Card images * Cases * Customers * Disclosures * External Accounts * Internal Accounts * Payment schedules and history * Persons * RDC * Relationships * Transactions (including for Internal Accounts) * Verifications * Waitlist * Webhook events The following data will be retained * Account Templates * API Keys * Bank/Partner data * Card product * Disclosure document records * Groups * Roles * Users * Viral loop waitlist * Webhook registration and secrets # Secured charge accounts Source: https://docs.synctera.com/v2/docs/secured-sc-accounts-guide A secured charge account (`CHARGE_SECURED`) is a type of open-ended non-revolving credit account, secured by a customer's own funds. This account type forms the basis of a [Synctera Smart Card](/v2/docs/v1-smart-card) product. ## Creating a security A `CHARGE_SECURED` account first requires the existence of a security. This acts as a funding source for securing any credit transaction to be applied against the secured charge account: any change to the security's available funds will also change the `CHARGE_SECURED` account's ability to spend. ### Using a customer DDA as a linked security account For details on creating a `CHECKING` or `SAVING` account, refer to our guide [here](/v2/docs/checking-savings-accounts-guide). This approach enables a [Synctera Smart card](/v2/docs/v1-smart-card) product offering. Using a customer's `CHECKING` account to serve as the linked deposit account allows the customer to adjust their `CHARGE_SECURED` account's spending ability, while still enabling them to move money out of their DDA if desired. Although the linked deposit account in this case is simply a DDA, it must have certain characteristics for the linking to be successful: | Field | Value | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `account_type` | Must be `CHECKING` or `SAVING`. | | `relationships` | The account holder for this account must be the intended account holder of the secured charge account. | | `balance_ceiling` | Must be `null`. | | `balance_floor` | Must be `null`. | | `interest_product_id` | This links to an interest product, to configure an interest rate on the deposit account. Refer to our [interest guide](/v2/docs/interest-guide) for more details. | | `is_ach_enabled` | Must be `true`. | | `is_p2p_enabled` | Must be `true`. | It is not currently possible for a linked deposit account to secure more than one charge account. ## Creating a secured charge account You may refer to our V2 guide on accounts [here](/v2/docs/create-accounts-guide). A secured charge account is a credit account which infers its spending ability from its linked security. Once the security account is available for linking, a `CHARGE_SECURED` account can be created. ### Creating a `CHARGE_SECURED` account template Our system will mostly fill in default values for `CHARGE_SECURED` account templates, but a few specific attributes must be set for this account type: | Field | Value | | -------------------------- | ------------------------------------------------------ | | `template.account_type` | Must be `CHARGE_SECURED`. | | `template.minimum_payment` | Must be set. Currently, only type `FULL` is supported. | The following is a sample valid request: ```bash Bash theme={"system"} curl -X POST \ -H 'Authorization: Bearer $apikey' \ -H 'Content-Type: application/json' \ -d ' { "name": "Charge-Secured-Template", "description": "For creating charge secured accounts", "is_enabled": true, "template": { "account_type": "CHARGE_SECURED", "currency": "USD", "bank_country": "US", "minimum_payment": { "type": "FULL" } } }' $baseurl/v0/accounts/templates ``` ### Creating a `CHARGE_SECURED` account The account template will populate most of the required values for a new charge account, but you will need to provide details about the security: | Field | Value | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `account_template_id` | Set to the ID of the account template created in the last step. | | `relationships` | See guide [here](/v2/docs/create-accounts-guide). If linking to a deposit account, the account holder must currently be the same customer as the linked account. | | `security`.`linked_account_id` | If using a linked deposit account as the security, this field is required. | | `application_id` | The linked application for a charge secured account. This field is not required, but if provided, the application must be approved. | It is not currently possible to change the security of a secured charge account. The following is a sample valid request: ```bash Bash theme={"system"} curl -X POST \ -H 'Authorization: Bearer $apikey' \ -H 'Content-Type: application/json' \ -d ' { "account_template_id": "23ce6444-2648-4399-832c-adc1ac0a8e4d", "relationships": [{ "relationship_type": "ACCOUNT_HOLDER", "customer_id": "4abc9499-0184-43ca-9a14-e9648152f9da" }], "security": { "linked_account_id": "c1a58202-0cae-436d-9984-e1b951b95c87" } }' $baseurl/v0/accounts ``` ### Balance management All examples in this section are expressed in US dollars. This section serves as an overview of what to expect when transacting against an account of this type. #### Loading funds into the security account If the security and secured charge accounts are both new, then they will have no available funds. | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `0` | `0` | | **Secured Charge** | `0` | `0` | The first step for enabling transactions at this point would be to fund the security account. Let's simulate a \$100 credit: | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `10000` | `10000` | | **Secured Charge** | `10000` | `0` | As the available balance goes up on the security account, the secured charge account responds in kind by increasing its available credit. #### Transacting against the secured charge account Now, let's simulate what happens if we spend some of that newly available credit. Initiating a pending transaction of \$20 against the secured charge account: | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `8000` | `10000` | | **Secured Charge** | `8000` | `0` | As you can see, the pending transaction reduces the available credit of the secured charge account, but it also reduces the available balance on the security account. If the transaction settles: | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `8000` | `10000` | | **Secured Charge** | `8000` | `2000` | We can see that the balance of the secured charge account changed to reflect the posted transaction. ### Secured Charge accounts are credit accounts This means that the balance will express what has been *spent* against the account. This is in contrast to a DDA, such as a `CHECKING` or `SAVING` account, which is a debit account that expresses funds *deposited* in the account. It's important to keep this distinction in mind when displaying these account balances to your customers. #### Transacting against the security account [If the security account is a customer DDA](#using-a-customer-dda-as-a-linked-deposit-account), then we can also transact against the security. This concept is crucial for [Synctera Smart card](/v2/docs/v1-smart-card) product offerings, as the user keeps the ability to move their security funds if they so choose. Continuing with our scenario, let's immediately transfer \$50 out of the security account: | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `3000` | `5000` | | **Secured Charge** | `3000` | `2000` | After this action is complete, we can see the following effects: * The security account's balance was adjusted from \$100 to \$50 as expected. * As a result, the security account's available balance was also adjusted by \$50, to reflect the transferred funds. * The secured charge account responds to this change in available funds by reducing its available credit to match. * The secured charge account's balance does not change, as it was not the subject of the transaction. Note that the available balance of the security account continues to be critical to this equation -- although the security continues to hold \$50 in funds, it only has \$30 *available*. This means that if we were to run this scenario again, we would see an error due to a balance violation. The \$20 unavailable in the security is subject to a hold, as a result of the transaction applied against the secured charge account. Until the \$20 balance on the charge account is repaid, the \$20 hold on the security remains. #### Repaying the secured charge account Let's simulate a partial repayment against our example secured charge account for \$10: | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `4000` | `5000` | | **Secured Charge** | `4000` | `1000` | We can see now that the balance on the secured charge account has gone down, but this also freed up the security account's available balance by the same amount. #### Repayment of the secured charge account The account holder may need to authorize the auto-repayment logic described below. Please discuss with your compliance officer and ensure proper disclosure is included in the account agreement. Once a [statement](/v2/docs/charge-secured-statements-guide) is issued for a `CHARGE_SECURED` account, the account holder will be given a due date for full repayment of the statement balance. If account holder opts-in to the autopay feature after acknowledging the proper autopay disclosure, Synctera system will automatically repay any outstanding statement balance using funds held in the security account when a statement is generated. If we take our example scenario, we left an outstanding balance of \$10 on the secured charge account. Assuming that the balance does not change by the time a statement is issued, and the account holder has opted in for autopay, once the statement is generated, the following scenario will occur: | Account | Available (cents) | Balance (cents) | | ------------------ | ----------------- | --------------- | | **Security** | `4000` | `4000` | | **Secured Charge** | `4000` | `0` | As a result of this auto-repayment of the statement balance, the security account balance was debited, which reduces the total security available for lending, and the secured charge account was credited in turn, which eliminates the need for a hold on the security funds. This functionality ensures that a secured charge account never enters a state of delinquency. Account holder can also opt out from autopay and choose to repay their statement balance on their own using other supported payment methods, e.g. ACH, Wire. If the account holder does not pay in full by the due date listed on the account agreement, the account will not be able to spend anymore. The account holder will still be expected to make payments until the due amount is paid in full. # Set PIN Widget (Deprecated) Source: https://docs.synctera.com/v2/docs/set-pin-widget-legacy Using this widget you can add set pin to your website. It requires a Synctera widget vault token to initialize it with. The user will have 5 minutes to complete the pin submission. This widget is deprecated. For new integrations, use the [Set PIN Widget](/v2/docs/card-widgets-set-pin). The Set Pin Widget injects a configurable set of iframes into your app, allowing your user to securely enter a PIN in a PCI compliant manner. This helps remove some (but not all) of the PCI compliance requirements you would otherwise need to handle. The iframes injected by Synctera allow you complete control over the styling over the widget using only CSS. ## Quick start 1. Add `` to your page. 2. Embed the Set Pin widgets when and as needed (both the Controller and Confirm Set Pin widgets are needed): ```html html theme={"system"} ``` 3. Add your own submit button under the Set Pin widgets. 4. Listen for the `validity` event on the Controller Set Pin widget (the one with the id): ```typescript typescript theme={"system"} const setPinWidget = document.getElementById('synctera-set-pin'); setPinWidget.onValidity = (e, isValid) => button.disabled = !isValid; ``` 5. Have the button call `setPinWidget.submit()` to submit the pin.It returns a promise, which resolves if the pin submission was successful, or rejects if it failed. ### *Basic Example*: ```html HTML theme={"system"}
PIN
Confirm PIN
```
**Styling: If you add a custom class name to the Set Pin widget, custom styling will be activated (see [Custom Styling](#custom-styling)).** By default, the widgets use the browser's inbuilt styling for the Set Pin input text fields (note that without custom styling the widget iframe is 4px bigger than the input field inside to allow for any browser outline effects). *See [Custom Styling Example](#custom-styling-example) for a complete working example.* ## Environments * Sandbox: [https://widgets-sandbox.synctera.com/assets/set-pin/v1/loader.js](https://widgets-sandbox.synctera.com/assets/set-pin/v1/loader.js) * Production: [https://widgets.synctera.com/assets/set-pin/v1/loader.js](https://widgets.synctera.com/assets/set-pin/v1/loader.js) ## Browser support The widgets work on both mobile and desktop, and we ensure support for all modern browsers. It also works in many older browsers, which we try to support where feasible. | **Browser** | **Minimum tested version** | | ----------- | -------------------------- | | Chrome | 29 (2013) | | Firefox | 27 (2014) | | Edge | 79 (2020), 15 (2017) | | Safari | 12 (2018) | | Opera | 20 (2014) | | IE | 11 (2013) | ## Set Pin flow > **Summary** > > Fetch widget token from backend → Render widgets with token → Listen for "validity" event → User submits *controller* widget → Widget submits PIN to Synctera → And returns success or failure → Widget auto-destroys **Note: It is recommended to also add 'load' and 'error' [listeners](#events) for UI management (see [Widget API](#widget-api) below).** The flow for using the widgets: 1. On your backend, request a widget token from Synctera for the particular card you wish to use. 2. Make sure the Synctera Set Pin widget Javascript has been added to your website. 3. Render the two specialized Set Pin HTML tags as above, setting the token attribute, and your own button to submit the widget. 4. You can style these fields however you like (as explained below in [Custom Styling](#custom-styling)). 5. Listen for the "validity" event from the *controller* widget. 6. When valid, enable your button. 7. When the button is clicked, call the `submit()` function on the *controller* widget. 8. The submit function will submit the pin. 9. It also returns a promise which resolves when successful, or rejects when there's a failure. 10. Once submitted, the widgets will auto-destroy and you can now remove them. ## Widget API ### Element Attributes: | **Name** | **Value** | **Default** | **Details** | **Example** | | ------------- | ----------------------------- | ----------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- | | **token** | widget token ID | - | Required*Incompatible with: isConfirm* | `` | | **isConfirm** | true (Present)false (Omitted) | Omitted | Required*Incompatible with: token* | ```` | | **class** | class name (string) | Omitted | Optional*If present, it will activate custom styling* | `` | ### Events: | **Name** | **Called when...** | **Why?** | ***addEventListener*** | ***on*** | | ------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | **load** | The widgets have are fully loaded | For best user experience, show the widgets only when this event is triggered | `setPinEl.addEventListener('load', () => ...);` | `setPinEl.onLoad = () => ...` | | **validity** | The widgets are now (in)valid | Only allow `submit()` to be called when valid*To get the status, check the "isValid" property* | `setPinEl.addEventListener('validity', () => {``␠ buttonEl.disabled = !setPinEl.isValid;``});` | `setPinEl.onValidity = (e, isValid) => {``␠ buttonEl.disabled = !isValid;``};` | | **error** | The widgets failed to load | Non-recoverable error states*To get the error, check the "error" property* | `setPinEl.addEventListener('error', () => {``␠ console.log(setPinEl.error);``});` | `setPinEl.onError = () => {``␠ console.log(setPinEl.error);``};` | | **success** | The widget submitted successfully | Know when the widget is done and the pin was saved*Alternatively: The "submit()" method returns a promise resolving when done* | `setPinEl.addEventListener('success', () => ...);` | `setPinEl.onSuccess = () => ...` | | **failure** | The widget submitted unsuccessfully | Know if the pin was not saved and the user will need to try again*Alternatively: The "submit()" method returns a promise rejecting on failure\*\*To get the failure, check the "error" property* | `setPinEl.addEventListener('failure', () => {``␠ console.log(setPinEl.error);``});` | `setPinEl.onFailure = (e, errorDetails) => ...` | ### Fields: | **Name** | **Value / Parameters** | **Default / Returns** | **Details** | **Example** | | ------------ | ------------------------------ | --------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | | **isValid** | truefalse | false | true if both fields are valid and form is ready to submit | `setPinEl.isValid` | | **error** | \{ errorType:'...', error: \*} | undefined | Error details if an error or failure occurs | `setPinEl.error` | | **submit()** | *No parameters* | *Returns:* Promise | Submits the PIN to Sycntera's servers*Alternatively:* The widget fires "success" and "failure" events | `setPinEl.submit()``␠ .then(// success)``␠ .catch(// error)` | ## Custom styling > **Summary** > > * Add a class name to `set-pin` tags to activate Custom Styling: ` * Style as desired (i.e. border), but [Font Styles](#font-styles) are special > * For pseudo-selectors, e.g. `:hover`, `:focus`, etc - use pseudo-attributes instead: *Example:* `.customStyles[_hover] { border: 1px solid #616161; }` > * Font styles are *auto-forwarded*, but only certain values are allowed (see below) > * Optional: You can use `.customStyles[_required]` to show the widgets once they have loaded By default, without custom styling, the widgets use the browser's inbuilt styling for the Set Pin input text fields (note that the widget iframe is 4px bigger than the input field inside to allow for any browser outline effects). You may want to style the widget to match your webapp design or to add things like placeholders. This can be done entirely through css styling. When a `class` attribute is added to the widget, the 4px spacing is removed, the input box styling is stripped and the background is made transparent such that any elements placed behind the widget will be visible (i.e. a placeholder element). The text input is set to always take up 100% of the height and width of the iframe, and likewise for the iframe in the widget tag. Input text field pseudo selectors such as `:hover`, `:focus` and `:blank` are indirectly supported through css-like attributes instead of actual pseudo selectors. As the user hovers, focuses and types in the field, attributes will be added/removed on the `set-pin` tag automatically. Supported "pseudo attributes" are inspired from: [https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#input\_pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#input_pseudo-classes) *Where `customStyles` is the class name added to widget tags, e.g. ` ```html html theme={"system"}
PIN
Confirm PIN
``` ## Font Styles You can style the tag as you see fit (border, background, etc). Css font properties are handled in a special way to forward them to the iframe for styling the input, in a secure and sanitized manner. As such only certain css font properties are supported and only with certain values (all other values may be ignored, if they work they are not guaranteed across all browsers): | **Font css property name** | **Allowed values** | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | color | `rgb(, , )` or `rgba(, , , )` | | font-family | **One of:** courier: `Courier New, Courier, Lucida Console, Lucida Sans Typewriter, monospace` arial: `Arial, Helvetica, sans-serif` georgia: `Georgia, Times New Roman, Times, serif` helvetica: `Helvetica, Arial, sans-serif` lucida: `Lucida Console, Lucida Sans Typewriter, Courier New, Courier, monospace` times: `Times New Roman, Times, Georgia, serif` tahoma: `Tahoma, Verdana, sans-serif` verdana: `Verdana, Tahoma, sans-serif` | | font-size | `px` | | font-weight | `00` (a number, not 'bold' etc) | | line-height | `px` | | letter-spacing | `px` | Note that with the `font-family` property, we look for a keyword in the first font in the comma seperated list of fonts you supply. If there's a match, we use the font-family strings in the above table and not the font-family specified (for security). The above list of fonts are designed to ensure maximum coverage across different operating systems for similar style fonts. Custom fonts are not supported at this time. ## Typescript type files The following type definitions are available for Set Pin: * React: [https://widgets.synctera.com/assets/types/v1/set-pin.d.ts](https://widgets.synctera.com/assets/types/v1/set-pin.d.ts) ## Additional Resources For examples showing the Card Activation & Set PIN widget implementation please see the following: # Spend Controls Source: https://docs.synctera.com/v2/docs/spend-controls-guide Spend controls provide a way to monitor the flow of money. ## Overview In Synctera’s platform, **spend controls are independent entities** that must be associated with another entity (currently, an **account**) to take effect. A spend control defines: * **What to monitor** – time window, payment types (for example, CARD, ACH, WIRE, CASH), merchant category codes (MCCs), direction (DEBITS or CREDITS). * **How much** – amount\_limit over that window. * **What to do if violated** – decline the transaction (where possible) and/or create a **Case** in Synctera’s case management system. * **Webhooks** sent to the nominated FinTech endpoint will be sent each time Key characteristics: * **Many-to-many** – a spend control can apply to multiple accounts, and an account can have multiple spend controls. * **Direction-specific** – each spend control applies to either **DEBITS** or **CREDITS**; debits and credits do not offset each other for spend-control purposes. * **Rail-agnostic** – payment types cover card, ACH, wires, cash, and other movement rails; spend controls can be used for **debit**, **credit**, and **Synctera Pay / external card** flows via the appropriate payment types. Spending Controls can apply to customers, accounts, and cards. This includes both **deposit accounts** (CHECKING/SAVING/PREPAID) and **credit accounts** (for example, LINE\_OF\_CREDIT, CHARGE\_SECURED, CHARGE\_UNSECURED, REVOLVING credit accounts). ## Managing Spend Controls You manage spend controls with the Spend Controls API: * **Create** – POST /v2/spend\_controls * **Get** – GET /v2/spend\_controls/ * **Update** – PATCH /v2/spend\_controls/ * **List** – GET /v2/spend\_controls See the [**Spend Controls API reference**](/reference/createspendcontrol) for full request and response schemas. ### Creating a Spend Control To create a spend control, use [POST /v2/spend\_controls](/v2/reference/createspendcontrol). For example, to create a limit of \$1,000.00 in card spending over the last seven days: ```json JSON theme={"system"} { "name": "One thousand dollars weekly card limit", "amount_limit": 100000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 7 }, "payment_types": [ "CARD" ], "action_decline": true, "action_case": false, "is_active": true } ``` The `amount_limit` uses the smallest currency unit (eg. cents). The `time_range` field can be a rolling window defined by a number of days, as in the example above, or defined as a single transaction. For example, to create a limit of \$1,000.00 per card transaction: ```json JSON theme={"system"} { "name": "One thousand dollars per transaction limit", "amount_limit": 100000, "time_range": { "time_range_type": "SINGLE_TRANSACTION", }, "payment_types": [ "CARD" ], "action_decline": true, "action_case": false, "is_active": true } ``` The `action_decline` and `action_case` fields specify what will happen for a transaction that would exceed the spend control's limit. If `action_case` is set then a case will be created in Synctera's case management system for any transaction that would exceed the spend control's limit. If `action_decline` is set then the transaction will be declined if possible. Some transactions are forced, because they represent money movement that has already occurred outside of Synctera's platform. In such cases, if the transaction were to exceed the spend control's limit the transaction will not be declined but instead a case will be created, regardless of the `action_case` setting. At least one of `action_decline` and `action_case` must be set. To completely disable the spend control set `is_active` to false. You may omit the `payment_types` field. In that case, the spend control applies to all payment types. You may specify multiple payment types. This means that all the specified payment types count toward the limit. For example, to create a rule that creates a case if there is more than \$25,000.00 in combined ACH and wire spending over the last thirty days: ```json JSON theme={"system"} { "name": "25 thousand ACH and wire", "amount_limit": 2500000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 30 }, "payment_types": [ "ACH", "WIRE" ], "action_decline": false, "action_case": true, "is_active": true } ``` In this example the spending is counted for the entire rule. So if there were \$15,000.00 of ACH and \$15,000.00 of wire spending then the rule would take effect and a case would be created. The \$25,000.00 limit is for ACH and wire spending combined. If you want the payment types to be counted separately, create separate spend controls, one for each payment type. You may specify the `direction` of money movement to which the spend control applies. The options are `DEBITS` or `CREDITS`. For example, to create a rule that triggers a case if an account receives more than \$10,000.00 in cash deposits in the last seven days: ```json JSON theme={"system"} { "name": "seven day cash warning", "amount_limit": 1000000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 7 }, "payment_types": [ "CASH" ], "action_decline": false, "action_case": true, "is_active": true, "direction": "CREDITS" } ``` You may specify `merchant_category_codes` to which the spend control applies. Specifying merchant category codes only works with card transactions. The options for `merchant_category_codes` include individual codes or ranges of codes. For example, to create a weekly limit of \$1,000.00 with merchant category code `6012` or in the range of merchant category codes `7300–7999`: ```json JSON theme={"system"} { "name": "One thousand dollars weekly card limit for MCCs 6012, 7300–7999", "amount_limit": 100000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 7 }, "payment_types": [ "CARD" ], "action_decline": true, "action_case": false, "is_active": true, "merchant_category_codes": [ "6012", "7300–7999" ] } ``` In this example, the spending is counted for the entire rule. So if there were \$750.00 of spending with Merchant Category Code 6012 and subsequently \$750.00 of spending with Merchant Category Code 7375, the rule would take effect. If you want the `merchant_category_codes` to be counted separately, create separate spend controls for each merchant category code or range of merchant category codes. ### Spend Control Response The API responses from the spend control endpoints include the details of the spend control, including the UUID in the `id` field and the number of accounts that are using the spend control in the `number_of_related_accounts` field (which will be zero for newly-created spend controls). To check the status of a specific spend control by its UUID, use [GET /v2/spend\_controls/](/v2/reference/getspendcontrol): ```json JSON theme={"system"} { "id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "name": "One thousand dollars weekly card limit", "amount_limit": 100000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 7 }, "payment_types": [ "CARD" ], "action_decline": true, "action_case": false, "is_active": true, "creation_time": "2022-03-24T12:59:06.756Z", "last_modified_time": "2022-03-24T12:59:06.756Z", "number_of_related_accounts": 0, "direction": "DEBITS", "merchant_category_codes": [ "6012", "7300–7999" ] } ``` ### Updating a Spend Control To update a spend control, use [PATCH /v2/spend\_controls/](/v2/reference/updatespendcontrol). This request will disable a spend control: ```json JSON theme={"system"} { "is_active": false } ``` This request will set a new time range and amount limit: ```json JSON theme={"system"} { "amount_limit": 75000, "time_range": { "time_range_type": "ROLLING_WINDOW_DAYS", "days": 14 } } ``` ### List Spend Controls To list spend controls, use [GET /v2/send\_controls](/v2/reference/listspendcontrols). Using query parameters. you can filter by limit amount (range), payment type, number of related accounts (range), specific related account ID and name. ### List Accounts that use a Spend Control To list all accounts that use a spend control, use [GET /v2/accounts](/v2/reference/listaccounts) and include the spend control ID in the `spend_control_ids` query parameter. ## Link Spend Controls to Accounts ### Create an Account with Spend Controls To create an account with a spend control, use [POST /v2/accounts](/v2/reference/createaccount) with the optional field `spend_controls_ids`. For example: ```json JSON theme={"system"} { "account_template_id": "e14182d8-130c-4fa4-bcac-9b3df1537247", "relationships": [ { "person_id": "23ec211e-7c3e-4ead-b340-c5cab70257a2", "relationship_type": "ACCOUNT_HOLDER" } ], "spend_control_ids": [ "b9c7da4e-8220-4044-86a0-f91a592002a5" ] } ``` You may specify as many as ten `spend_control_ids`. Each spend control applies to the account independent of the other spend controls on the account and independent of other accounts that may use the same spend controls. ### Update an Account's Spend Controls To change the spend controls for an account, use [PATCH /v2/accounts/](/v2/reference/patchaccount). For example, to have the account use two spend controls: ```json JSON theme={"system"} { "spend_control_ids": [ "ad7495c3-82d0-482d-b1e4-f0cbab6e039c", "41d6ab10-73b3-4b82-9e75-a4981b35edfb" ] } ``` When updating the list of `spend_control_ids` for an account, the entire list is replaced. The list is not appended. Old values are dropped. So if you want to add a new spend controls to an account with existing spend controls make sure your update request includes both the old spend controls and the new ones. To remove spend controls from an account use an explicitly-empty JSON array. ```json JSON theme={"system"} { "spend_control_ids": [] } ``` ### Using Account Templates [Account templates](/v2/docs/create-accounts-guide#account-templates) may contain spend control IDs. As with other account template fields, these spend control IDs will be the default for any account created using the template but during account creation you can over-ride the template's default. If you create an account from a template which contains a list of `spend_control_ids` and specify your own list of `spend_control_ids` then the two lists are not combined. The list will be whatever you specify in the account creation request. ## Spend Monitoring Cases When spend controls are violated they may create a case in Synctera's case system. If the spend control has `action_case` set, or if the spend control has `action_decline` set and the transaction is forced, then there will be a case based on that specific account and spend control. Multiple accounts using the same spend control will have separate cases if multiple accounts violate the spend control. Multiple spend controls on the same account will have separate cases if multiple of the spend controls are violated. Multiple violations of a specific spend control for a specific account will combine into the same case as long as the case remains open. Any additional violations will be reflected in violation count of the case. If the case is closed and the account violates the spend control again then a new case will be created. # Statements Source: https://docs.synctera.com/v2/docs/statements-guide A statement is a disclosure of the state of an account, and its activity, over a billing period. Synctera will generate a statement payload for any account that requires periodic statements to be provided to the customer, through the [Statements API](https://docs.synctera.com/v2/reference/liststatements). These payloads are made available at the end of every billing period, which is usually from the first to the last day of a calendar month. At this time, Synctera does not generate a printable version of a statement. ### Prerequisites This guide assumes that you are already familiar with the customer and account APIs, and have one or more accounts created. If this is not the case, refer to the following guides: ## Statement generation The V2 version of this API supports multiple statement types * **DEPOSIT** – Checking, savings, and other depository accounts. * Guide: [Checkings and Savings Statements](https://docs.synctera.com/v2/docs/checking-savings-statements-guide) * **LINE\_OF\_CREDIT** – Unsecured line of credit accounts. * Guide: [Line of Credit Statements](https://docs.synctera.com/v2/docs/line-of-credit-statements-guide) * **CHARGE\_SECURED** – Synctera Smart Card / secured charge accounts (linked to a security deposit account). * Guide: [Charge Secured Statements](https://docs.synctera.com/v2/docs/charge-secured-statements-guide) * **CHARGE\_UNSECURED** – Unsecured charge accounts (beta). * Statement schema available via the v2 Statements API reference. For type‑specific fields and compliance requirements (for example, APR, minimum payment for credit products), use the dedicated statement guides linked above. A statement is generated automatically at the end of an account's billing period. At this time, billing frequency is monthly, meaning that at the end of every calendar month a bank statement will be generated for every eligible account: ### Billing frequency A statement is generated automatically at the end of an account’s **billing period**. * For **deposit accounts** (DEPOSIT statements), billing frequency is currently **monthly**, from the first to the last **calendar** day of each month. * For **Line of Credit** and other credit products, billing frequency is defined by the product configuration (for example, monthly or biweekly) and governed by Reg Z/FCBA requirements; see the Line of Credit / Charge Secured statement guides and credit PRDs. ### Eligible account types In v2, statements are available for the following account types via the Statements API: * **CHECKING** and **SAVING** – appear as statement\_type = "DEPOSIT". * **LINE\_OF\_CREDIT** – appear as statement\_type = "LINE\_OF\_CREDIT". * **CHARGE\_SECURED** – appear as statement\_type = "CHARGE\_SECURED". * **CHARGE\_UNSECURED** – appear as statement\_type = "CHARGE\_UNSECURED" (beta). Each eligible account receives a statement for every completed billing period in which it was active, subject to product‑specific rules (for example, “only if the account was active during the period” for some deposit accounts). Once a statement is generated, a notification will be sent via webhook. Please refer to the [Webhook Events](#webhook-events) section for details. ### Statement content In order to produce regulatory-compliant, human-readable statements, this API provides the following information: | Section | Field(s) | Description | | --------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | `start_date` and `end_date` | The date interval covered by the statement, inclusive. | | | `issue_date` | The date the statement was issued. | | | `opening_balance` and `closing_balance` | The final posted balances recorded at the beginning of `start_date` and at the end of `end_date`. | | | `disclosure` | A suggested disclosure statement to display. | | | `transactions` (**deprecated**) | A list of transactions posted during the statement period. This field is deprecated, please see [this section](#step-3-list-the-transactions-for-a-statement) for details. | | `account_summary` | - | Information about the account. | | `account_summary` | `financial_institution` | Information about the financial institution managing the account. | | `customer_service_details` | - | Contact information for use by the customer if they wish to dispute the information in this statement. | | `primary_account_holder_personal` | - | When `account_summary.customer_type` is `PERSONAL` then `primary_account_holder_personal` contains information about the person acting as primary account holder. | | `primary_account_holder_business` | - | When `account_summary.customer_type` is `BUSINESS` then `primary_account_holder_business` contains information about the company holding this account. | | `joint_account_holders` | - | A list of all individuals designated as joint account holders for this account. | | `authorized_signer` | - | A list of all individuals designated as authorized signers for this account. | | `savings_summary` | `apy` | If the account has an interest product associated with it, this field will describe the APY earned based on the interest payout in this period. | | `savings_summary` | `interest_earned` and `interest_earned_ytd` | If the account has an interest product associated with it, this field will describe the interest earned on during this billing period, and the sum of interest earned during the calendar year. | For more details about the schema returned by this API, please refer to the [Statements API specification](/v2/reference/getstatement). Here is a sample statement produced using the information provided by this API: Sample Statement ### Webhook Events This section assumes you are familiar with our webhook API. If not, please see the [webhooks guide](/v2/docs/webhooks-guide) for more context. When a statement is generated, a webhook notification will be sent to subscribers of event type `STATEMENT.CREATED`. The event will contain a full version of the statement payload, following the spec outlined in the [Statements API specification](/v2/reference/getstatement). Please note that if a statement contains an excessive number of transactions, the system may opt to return an empty list in the webhook notification to the subscriber due to technical limitations. This will be reflected in the payload with `transactions_omitted` set to `"true"` and an empty `transactions` attribute. ## API Workflow If statements are available for an account, you can retrieve a summarized list by calling `GET /v2/statements`, with an `account_id` query parameter: ```shell Shell theme={"system"} curl --request GET \ --url https://api.synctera.com/v0/statements?account_id=37083b2c-d3f9-4a7f-b781-7342285c368e \ -H 'Accept: application/json' \ -H "Authorization: Bearer $apikey" ``` This route only gives high-level details about each statement. Once you know the ID of the statement you're looking for, you can retrieve details about that statement. With a statement ID, you'll be able to pull detailed information about the statement: ```shell Shell theme={"system"} curl --request GET \ --url https://api.synctera.com/v0/statements/a4554821-22c2-4053-8b50-768365b98c83 \ -H 'Accept: application/json' \ -H "Authorization: Bearer $apikey" ``` Transaction information will be omitted from the statement detail response payload in future versions of the API. We recommend that all existing clients migrate to calling the dedicated transactions endpoint instead of relying on the `transactions` attribute. With a statement ID, you'll be able to pull the list of transactions that pertain to that statement: ```shell Shell theme={"system"} curl --request GET \ --url https://api.synctera.com/v0/statements/a4554821-22c2-4053-8b50-768365b98c83/transactions \ -H 'Accept: application/json' \ -H "Authorization: Bearer $apikey" ``` This list will only include posted transactions at the time of statement generation. These are also only returned to you in descending order of posted date. # Synctera Pay Source: https://docs.synctera.com/v2/docs/synctera-pay SyncteraPay aims to simplify the process for FinTechs to introduce their own payment partners into the Synctera ecosystem, enabling them to fully leverage their accounts and transaction flow. The platform facilitates daily reconciliation and settlement with the third-party payments provider. ## Overview With SyncteraPay, FinTechs can leverage their own payments partners outside the Synctera Marketplace. SyncteraPay allows Fintechs to ledger payments within the Synctera ecosystem that were initiated by third parties, by providing a payments endpoint that captures the necessary compliance and reconciliation data to record payments in our system, including: * **External party data** (the party and account that the money is being sent to/from), which is a requirement to run the mandatory OFAC checks on counterparties participating in money movement on the Synctera platform * **SyncteraPay-rail-specific fields** such as network reference ids (to tie the third party transaction to the SyncteraPay transaction), vendor information and currency exchange details, to ensure clear auditability, transparency and streamlined reconciliation between the two platforms * **A reconciliation template** for sending daily files of all posted SyncteraPay transactions, to ensure alignment between the Fintech’s ecosystem of payments and what has ultimately posted on our ledger SyncteraPay provides more than transaction ingestion for third-party payment providers. It adds the compliance, controls, and reconciliation framework required to support off-platform money movement within a regulated banking program. **By capturing mandatory counterparty data, preserving third-party reference details, and standardizing daily reconciliation, SyncteraPay helps FinTechs reduce operational risk, support sponsor bank oversight, and maintain an auditable record of payment activity.** The value of SyncteraPay is not only in enabling access to external payment partners, but in ​reducing the internal cost and risk of operating those partners​. Working with a third party vendor to support payments within the Synctera ecosystem requires Sponsor Bank approvals, including a TPRM review of the provider you are working with, and a full review of funds flow to ensure oversight and use-case specific requirements are both documented and agreed upon. **SyncteraPay is built to be approved by design, as it contains all of the necessary data to support a third party payments program on our ledger.** SyncteraPay supports both Outbound and Inbound payment flows: * **SyncteraPay Outbound (Send):** This function allows money transfer from a Synctera account to an external account in a different financial institution, via a third-party payments provider. * **SyncteraPay Inbound (Receive):** This function facilitates the receipt of money from an external account to a Synctera account, via a third-party provider. Transactions in SyncteraPay are created using the SyncteraPay APIs. The transaction recorded in the account is always the result of an off-platform activity that leads to a money movement, performed by the third-party payments provider. Transactions are final and cannot be reversed. In order to reverse a transaction or correct a transaction a new opposite transaction will have to have to be created. \*\*For more information about transactions and its status, please refer to Synctera’s transactions [guide](https://docs.synctera.com/v2/docs/transactions-guide). The current list of supported SyncteraPay transaction subtypes are found [here](https://docs.synctera.com/v2/reference/createsyncterapaytransfer) under **subtype.** ### Counterparty Set Up The customer may be the same party that is receiving the funds (in the event of a me-to-me transfer) or a different customer (Peer-to-Peer). Ensure that the customer exists on the Synctera platform by using the same customer if M2M, or adding the originating party (is customer = false). Using our external accounts endpoint, link the external account that belongs to the counterparty. If it is a true bank account, you can add this following the same steps you would to link and manually verify an external account described [here](https://docs.synctera.com/docs/external-accounts-guide). There may be some cases where the external account does not have its own unique account number; for example, a virtual account rolling into a pool account, or an international account that does not have the same properties as a US bank account. Provided your Sponsor Bank has approved the use case, you can use the following example for adding the external account to the originating customer on the Synctera platform/ledger: ```json theme={"system"} curl --request POST \ --url https://api-sandbox.synctera.com/v0/external_accounts \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "type": "OTHER_BANK_ACCOUNT", "customer_type": "{either BUSINESS or CONSUMER}", "account_owner_names": ["Account Owner"], "routing_identifiers": { "bank_name": "{Bank Name}", "bank_countries": ["Country of operation of the bank"] }, "account_identifiers": { "number": "{uuid if no account number exists}" }, "verification": { "vendor": "MANUAL", "status": "VERIFIED" }, "business_id": "{uuid of the business in Synctera. Set customer_id as the uuid of the customer in Synctera if it is a consumer use case}" }' ``` ### Outgoing Transaction Flow Transactions executed via a third-party provider need coordination between the Synctera account and the third-party payment provider. All outgoing payments follow a two-step process. The first step is a transaction authorization that verifies that the account is capable of transacting and has sufficient funds for the transaction. The second step is the transaction posting ensuring the successful processing of the transfer with the third-party payment provider and includes adding extra transaction data for reconciliation. These steps are performed via the Synctera APIs. Assuming Steps 1 and 2 above have already been completed: Create a transaction authorization to hold available funds. The external account added in Step 2 is reflected as the **final\_external\_account\_id** in the request. ```json JSON theme={"system"} // request { "account_id": "b01db9c7-78f2-4a99-8aca-1231d32f9b96", "customer_id": "46fec39e-e776-4571-bf90-d0e1d15172fe", "effective_date": "2022-03-18", "amount": 10000, "currency": "USD", "dc_sign": "CREDIT", "direction": "OUTGOING", "subtype": "OUTGOING_INTERNATIONAL_REMITTANCE", "synctera_pay_network": "WISE", "configuration_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "final_external_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "source_data": {}, "synctera_pay_vendor_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7" } // response { "amount": 10000, "currency": "USD", "dc_sign": "CREDIT", "direction": "OUTGOING", "subtype": "OUTGOING_INTERNATIONAL_REMITTANCE", "synctera_pay_network": "WISE", "effective_date": "2022-03-18", "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "is_same_day": true, "status": "PENDING", "tenant_id": "abcdef_ghijkl", "configuration_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "final_external_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "source_data": {}, "synctera_pay_vendor_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "customer_id": "46fec39e-e776-4571-bf90-d0e1d15172fe", "destination_account_id": "fccb4a46-1261-4e91-b622-73b5b946183d", "destination_account_owner_name": "", "failed": false, "network_status": "PENDING", "originating_account_id": "b01db9c7-78f2-4a99-8aca-1231d32f9b96", "originating_account_owner_name": "", "suspended": false, "transaction_id": "45b5246f-ad97-4629-9aac-465b74a05505" } ``` If successful, the third-party provider has processed the transaction, and it can now be posted to the customer's account. At this stage, the FinTech should include the transaction reference ID provided by the third-party provider for future transaction reconciliation. Update the status to POSTED once funds are verified to post the hold. Include the reference id obtained from the third party provider in this step as the **reference\_id**. ```json JSON theme={"system"} // request { "status": "POSTED", "reference_id": "", "exchange_details": { "source_currency": "USD", "target_currency": "GBP", "source_amount": 10000, "target_amount": 10000, "rate": "1.30445", "fees": [ { "fee_type": "FX", "description": "string", "amount": 0, "percentage": "string", "currency": "string" } ] } } // response { "amount": 10000, "currency": "USD", "dc_sign": "CREDIT", "direction": "OUTGOING", "subtype": "OUTGOING_INTERNATIONAL_REMITTANCE", "synctera_pay_network": "WISE", "effective_date": "2022-03-18", "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "is_same_day": true, "status": "POSTED", "tenant_id": "abcdef_ghijkl", "configuration_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "exchange_details": { "rate": 1.30445, "source_amount": 10000, "source_currency": "USD", "target_amount": 10000, "target_currency": "GBP", "fees": [ { "currency": "", "fee_type": "FX", "amount": 2, "description": "", "percentage": "" } ] }, "final_external_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "source_data": {}, "synctera_pay_vendor_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "customer_id": "46fec39e-e776-4571-bf90-d0e1d15172fe", "destination_account_id": "fccb4a46-1261-4e91-b622-73b5b946183d", "destination_account_owner_name": "", "failed": false, "history": [ { "data": {}, "message": "", "timestamp": "2023-11-07T05:31:56Z" } ], "network_status": "POSTED", "original_reference_id": "", "originating_account_id": "b01db9c7-78f2-4a99-8aca-1231d32f9b96", "originating_account_owner_name": "", "posting_date": "2022-03-18", "reference_id": "", "suspended": false, "transaction_id": "45b5246f-ad97-4629-9aac-465b74a05505" } ``` ### **Incoming Transaction Flow** For **Incoming SyncteraPay** (sending funds in from an external provider to a Synctera DDA via SyncteraPay), utilize the [**v2/synctera\_pay/incoming**](https://docs.synctera.com/v2/reference/createincomingsyncterapaytransfer) endpoints. This guide assumes you already have an Incoming SyncteraPay Configuration set up on your tenant, which defines the use case, subtype and Settlement DDA. For more information on configuration set up, reach out to your Implementation Manager.  Assuming Steps 1 and 2 for Counterparty Set Up have already been completed: Ensure you have captured the network reference id of the transfer to include in the Incoming SyncteraPay call in the next step. Call [POST /v2/synctera\_pay/incoming/transfers](https://docs.synctera.com/v2/reference/createincomingsyncterapaytransfer) with the following: * Set **payee\_id** to the recipient of the SyncteraPay transfer. * Set  **payer\_id** to the customer\_id or business\_id from Step 1. * Set **reference\_id** to the id associated with the external transaction from Step 3.  * Set **source\_external\_account\_id** to the external account id created in Step 2.  * Set **destination\_account\_id** to the Synctera account owned by the customer payee\_id, that the funds will be distributed to.  * Set **configuration\_id** to the Synctera provided id. ```json theme={"system"} //request { "amount": 2, "configuration_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "destination_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "payee_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "payer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "reference_id": "", "settlement_date": "2023-12-25", "source_external_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "external_data": {} } // response { "amount": 2, "configuration_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "creation_time": "2010-05-06T12:23:34.321Z", "destination_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "last_updated_time": "2010-05-06T12:23:34.321Z", "payee_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "payer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "reference_id": "", "settlement_date": "2023-12-25", "source_external_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "status": "CREATE_HOLD", "tenant": "abcdef_ghijkl", "external_data": {}, "transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a" } ``` ### Daily Bulk Settlement With Third Party Provider At the end of the business day, or multiple times a day (depending on the Fintech/Payments provider agreement), the third-party payment provider will need to settle for the total amount of Inbound or Outbound Payments processed via SyncteraPay. The Synctera platform can create and receive bulk wire and ach transfers to settle these payments. The Bulk Settlement function is accessible via the Synctera UI and available to both the FinTech and Synctera Operations agents. \*\*SyncteraPay transactions and Settlements are not allowed by default. Please contact your implementation manager to enable this capability. **Note:** If you are using Incoming SyncteraPay and Outgoing SyncteraPay and have been approved by Synctera and your Sponsor Bank to perform end of day netting bulk transfers for SyncteraPay DDA EOD Settlement, you will need to work with your Implementation Manager to ensure the Standard Operating Procedure and methods are mutually aligned and supported. # Transaction Disputes Source: https://docs.synctera.com/v2/docs/transaction-disputes Customers can dispute transactions on their card or account for many reasons, ranging from not recognizing the transaction to unauthorized activity. ## Overview Customers can dispute transactions on their card or account for many reasons, ranging from not recognizing the transaction to unauthorized activity. Disputing a transaction involves a series of actions between the parties involved, where supporting documentation is exchanged until a decision is reached on who is financially responsible. To begin the dispute process, open a dispute on a transaction through the Synctera Console or the Disputes API (described below). When the dispute is opened, a Dispute Case is automatically created. The Dispute and Dispute Case track the dispute details, lifecycle, and events during investigation. The Dispute Case and Dispute Lifecycle are described in this [article](/v2/docs/dispute-cases-fintechs). Through both the Dispute Case in the Synctera Console and the Disputes API, you are guided through the dispute flow. Available actions depend on the payment rail of the original transaction. Once an action is created against a dispute, subsequent actions may become available as the case progresses. Payment-rail–specific behavior differs. For example, card disputes are evaluated and filed with the card network by Synctera on your behalf after evidence is gathered. For card-specific steps, reason codes, and lifecycles, see [Card Transaction Disputes](/v2/docs/card-transaction-disputes). The walkthrough below uses an ACH dispute as the general API example. ## Webhook Events To monitor transaction disputes, webhooks are triggered anytime one of the following events occurs: | Webhook | Description | | ----------------- | ------------------------------------- | | `DISPUTE.CREATED` | A new dispute has been created. | | `DISPUTE.UPDATED` | An existing dispute has been updated. | To subscribe to the dispute webhooks refer to the [Webhooks Guide](/v2/docs/webhooks-guide). ## Disputing a Transaction The following steps walk through disputing a transaction using the Disputes API. Examples use `payment_rail` = `ACH`. Refer to the links below for payment-rail–specific details: ### 1. Create a Dispute To create a dispute, use [`POST /v1/disputes`](/v2/reference/createdispute). ACH disputes support incoming ACH credit and debit transactions. The example below uses a personal account, so Regulation E and its applicable deadline fields appear in the response; those fields are omitted for business accounts. ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "ACH", "transaction_id": "{$transaction_id}", "disputed_amount": 500, "date_customer_reported": "2024-05-28T12:25:00.000Z", "memo": "Some details about the reason for creating the dispute." } ' ``` This will return a response with the created dispute. ```json JSON theme={"system"} { "account_id": "bdec606d-e6ed-473d-b645-4e689f06a4d2", "applicable_regulation": "REGULATION_E", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "NONE", "currency": "USD", "customer_id": "9d9ba3c5-81b7-4f42-bbe5-6f5e3d9d71f6", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [], "disputed_amount": 500, "id": "73688b78-8b16-4ca6-9d96-e7622799b01d", "last_updated_time": "2024-05-28T22:48:24.279984Z", "memo": "Some details about the reason for creating the dispute.", "network": "ACH", "payment_rail": "ACH", "status": "OPEN", "tenant": "asbght_iujkio", "timestamp_investigation_due": "2024-07-12T12:25:00Z", "timestamp_provisional_credit_due": "2024-06-11T12:25:00Z", "transaction_id": "10c6290e-d9bb-4e0f-a769-d38f25687ccc", "action_history": [], "available_actions": [ { "action": "STOP_PAYMENT", "state": "CREATE" }, { "action": "ACH_RETURN", "state": "CREATE" } ], "lifecycle_state": "PENDING_ACTION" } ``` Note the returned `id` attribute and the list of `available_actions`. ### 2. Upload Supporting Documents Supporting documents can be uploaded to any dispute (ACH or card) with [`POST /v1/disputes/{dispute_id}/documents`](/v2/reference/adddisputedocument). Uploaded files appear on the dispute under `dispute_documents` and can be referenced from actions via `supporting_doc_id` when applicable. Optionally set `category` on upload: | Category | Description | | --------------------------- | ---------------------------------------- | | `TRANSACTION_RECEIPT` | Receipt for the disputed transaction | | `PRIOR_TRANSACTION_RECEIPT` | Receipt from a prior related transaction | | `MERCHANT_CORRESPONDENCE` | Correspondence with the merchant | | `COUNTERFEIT_EVIDENCE` | Evidence that goods were counterfeit | | `REFUND_PROMISE` | Evidence of a promised refund | | `OTHER` | Other supporting documentation | ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/documents \ -H "Authorization: Bearer $apiKey" \ -F file=@file.pdf \ -F category=OTHER ``` This will return a response with the created document. ```json JSON theme={"system"} { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "73688b78-8b16-4ca6-9d96-e7622799b01d", "file_name": "file.pdf", "id": "dff07f15-417f-4998-9bcf-82881144f8d9", "category": "OTHER", "tenant": "asbght_iujkio" } ``` Note the returned document `id` as it can be used in subsequent dispute actions via `supporting_doc_id`. ACH supporting documents can be up to 14MB. For card disputes, files must be JPEG, PNG, or PDF, max 4.5MB each, and up to 10 documents per dispute. Some card reason codes also require a document with a specific `category` before the case can be filed — see [Card Transaction Disputes](/v2/docs/card-transaction-disputes#reason-code). ### 3. Create a Dispute Action Select the action you wish to create from the list of `available_actions` on the dispute. To create the action, use [`POST /v1/disputes/{dispute_id}/actions`](/v2/reference/createaction) ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/actions \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "ACH", "action": "ACH_RETURN", "state": "CREATE", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "supporting_doc_id": "{$document_id}", "message": "Customer did not authorize this debit" } ' ``` This will return a response with the created action. ```json JSON theme={"system"} { "action": "ACH_RETURN", "creation_time": "2024-05-28T22:58:30.396998Z", "id": "109ac96e-9572-4d43-9a01-772631d0e869", "message": "Customer did not authorize this debit", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "status": "SUBMITTED", "tenant": "asbght_iujkio" } ``` `ACH_RETURN` requires a `reason_code` and corresponding ACH `return_code`. `R10` is valid for `UNAUTHORIZED_TRANSACTION`. After this action is created, the dispute moves to `ACH_AWAITING_APPROVAL` while it is reviewed. Uploaded documents remain listed on the dispute under `dispute_documents`. Although `supporting_doc_id` is stored from the request, current ACH action responses expose the document through `dispute_documents` rather than returning `supporting_doc_id` on the action. ### 4. Monitor for Dispute Updates When the dispute is updated, a `DISPUTE.UPDATED` webhook is triggered. The webhook's `event_resource` contains the versioned dispute resource; the `v1` object has the same shape as a response from [`GET /v1/disputes/{dispute_id}`](/v2/reference/getdispute), including the updated `action_history`, `lifecycle_state`, and `available_actions`. Depending on the update, a final decision may be reached or further actions may be available. If the dispute `decision` is still `ONGOING`, review the latest actions and any new supporting documents before continuing. The decoded `v1` dispute object after Synctera requests more information is: ```json JSON theme={"system"} { "account_id": "bdec606d-e6ed-473d-b645-4e689f06a4d2", "applicable_regulation": "REGULATION_E", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "NONE", "currency": "USD", "customer_id": "9d9ba3c5-81b7-4f42-bbe5-6f5e3d9d71f6", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "ONGOING", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "73688b78-8b16-4ca6-9d96-e7622799b01d", "file_name": "file.pdf", "id": "dff07f15-417f-4998-9bcf-82881144f8d9", "category": "OTHER", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "73688b78-8b16-4ca6-9d96-e7622799b01d", "last_action_by": "INITIATOR", "last_updated_time": "2024-05-29T14:30:00.010000Z", "memo": "Some details about the reason for creating the dispute.", "network": "ACH", "payment_rail": "ACH", "status": "OPEN", "tenant": "asbght_iujkio", "timestamp_investigation_due": "2024-07-12T12:25:00Z", "timestamp_provisional_credit_due": "2024-06-11T12:25:00Z", "transaction_id": "10c6290e-d9bb-4e0f-a769-d38f25687ccc", "action_history": [ { "action": "ACH_RETURN", "creation_time": "2024-05-28T22:58:30.396998Z", "id": "109ac96e-9572-4d43-9a01-772631d0e869", "message": "Customer did not authorize this debit", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "status": "SUBMITTED", "tenant": "asbght_iujkio" }, { "action": "ACH_RETURN", "creation_time": "2024-05-29T14:30:00Z", "id": "c501b7c7-4ad9-4091-8b37-c0c0299fc12f", "message": "Need more authorization evidence", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "status": "MORE_INFO_REQUIRED", "tenant": "asbght_iujkio" } ], "available_actions": [ { "action": "ACH_RETURN", "state": "CREATE" }, { "action": "ACH_RETURN", "state": "REJECT" } ], "lifecycle_state": "ACH_MORE_INFO_REQUIRED" } ``` In `ACH_MORE_INFO_REQUIRED`, you can re-submit the same action type (`ACH_RETURN` with `state` = `CREATE`, including `reason_code` and `return_code`) after uploading additional documents, or reject the action. Use document IDs from `dispute_documents` to retrieve contents for review. ### 5. Review Additional Supporting Documents To retrieve supporting documentation from the dispute, use [`GET /v1/disputes/documents/{document_id}/contents`](/v2/reference/getdisputedocumentcontents) ```bash Shell theme={"system"} curl \ -X GET \ $baseurl/v1/disputes/documents/{$document_id}/contents \ -H "Authorization: Bearer $apiKey" \ -o file.pdf ``` The response body contains the document contents and is saved as `file.pdf`. ### 6. Re-submit the ACH Return After providing the requested information, re-submit the ACH return using an action listed in `available_actions`. ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v1/disputes/{$dispute_id}/actions \ -H "Authorization: Bearer $apiKey" \ --json ' { "payment_rail": "ACH", "action": "ACH_RETURN", "state": "CREATE", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "supporting_doc_id": "{$document_id}", "message": "Attached customer affidavit" } ' ``` This returns the re-submitted action: ```json JSON theme={"system"} { "action": "ACH_RETURN", "creation_time": "2024-05-29T15:00:00Z", "id": "6917ee86-deac-4f08-8472-8888601adbf6", "message": "Attached customer affidavit", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "status": "SUBMITTED", "tenant": "asbght_iujkio" } ``` The dispute returns to `ACH_AWAITING_APPROVAL` while Synctera reviews the additional information. ### 7. Review the Final Decision When the ACH return is accepted, another `DISPUTE.UPDATED` webhook is sent. You can also retrieve the current state with [`GET /v1/disputes/{dispute_id}`](/v2/reference/getdispute): ```bash Shell theme={"system"} curl \ -X GET \ $baseurl/v1/disputes/{$dispute_id} \ -H "Authorization: Bearer $apiKey" ``` ```json JSON theme={"system"} { "account_id": "bdec606d-e6ed-473d-b645-4e689f06a4d2", "applicable_regulation": "REGULATION_E", "creation_time": "2024-05-28T22:48:24.279984Z", "credit_status": "NONE", "currency": "USD", "customer_id": "9d9ba3c5-81b7-4f42-bbe5-6f5e3d9d71f6", "date_customer_reported": "2024-05-28T12:25:00Z", "decision": "WON", "dispute_documents": [ { "creation_time": "2024-05-28T22:56:12.921781Z", "dispute_id": "73688b78-8b16-4ca6-9d96-e7622799b01d", "file_name": "file.pdf", "id": "dff07f15-417f-4998-9bcf-82881144f8d9", "category": "OTHER", "tenant": "asbght_iujkio" } ], "disputed_amount": 500, "id": "73688b78-8b16-4ca6-9d96-e7622799b01d", "last_action_by": "INITIATOR", "last_updated_time": "2024-05-30T16:00:00.010000Z", "memo": "Some details about the reason for creating the dispute.", "network": "ACH", "payment_rail": "ACH", "status": "OPEN", "tenant": "asbght_iujkio", "timestamp_final_decision": "2024-05-30T16:00:00Z", "timestamp_investigation_due": "2024-07-12T12:25:00Z", "timestamp_provisional_credit_due": "2024-06-11T12:25:00Z", "transaction_id": "10c6290e-d9bb-4e0f-a769-d38f25687ccc", "action_history": [ { "action": "ACH_RETURN", "creation_time": "2024-05-28T22:58:30.396998Z", "id": "109ac96e-9572-4d43-9a01-772631d0e869", "message": "Customer did not authorize this debit", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "status": "SUBMITTED", "tenant": "asbght_iujkio" }, { "action": "ACH_RETURN", "creation_time": "2024-05-29T14:30:00Z", "id": "c501b7c7-4ad9-4091-8b37-c0c0299fc12f", "message": "Need more authorization evidence", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "status": "MORE_INFO_REQUIRED", "tenant": "asbght_iujkio" }, { "action": "ACH_RETURN", "creation_time": "2024-05-29T15:00:00Z", "id": "6917ee86-deac-4f08-8472-8888601adbf6", "message": "Attached customer affidavit", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "status": "SUBMITTED", "tenant": "asbght_iujkio" }, { "action": "ACH_RETURN", "creation_time": "2024-05-30T16:00:00Z", "id": "82f203c5-fe66-488b-937b-1b6ee42ba06c", "payment_rail": "ACH", "reason_code": "UNAUTHORIZED_TRANSACTION", "return_code": "R10", "status": "ACCEPTED", "tenant": "asbght_iujkio" } ], "available_actions": [], "lifecycle_state": "ACH_FILED_WITH_NETWORK" } ``` An accepted ACH return sets `decision` to `WON` and `lifecycle_state` to `ACH_FILED_WITH_NETWORK`. A rejected return instead sets `decision` to `LOST` and `lifecycle_state` to `ACH_REJECTED`. ### 8. Close Dispute After the dispute reaches a final decision, close it with [`PATCH /v1/disputes/{dispute_id}`](/v2/reference/updatedispute): ```bash Shell theme={"system"} curl \ -X PATCH \ $baseurl/v1/disputes/{$dispute_id} \ -H "Authorization: Bearer $apiKey" \ --json ' { "status": "CLOSED" } ' ``` The response is the updated dispute. Its final decision and lifecycle do not change; `status` becomes `CLOSED`, `last_updated_time` reflects the close, and `available_actions` remains empty. # Transactions Source: https://docs.synctera.com/v2/docs/transactions-guide A "transaction" in the Synctera platform represents any movement of funds between accounts. ## Overview Transactions comes in 2 flavours: * Pending transactions * Posted transactions A pending transaction represents a "hold" or "authorization" for the movement of funds in an account. Pending transactions are used whenever we need to guarantee the availability of funds for any multi-step payment flow. See [The Transaction Life-cycle](#the-transaction-life-cycle) below for an example. A pending transaction is mutable, meaning that up to the point that the pending transaction is posted or expired, the amount of the hold may be increased, decreased, canceled, or declined. Note that this functionality is not typically exposed directly to integrator, but instead depends on the business logic of the specific payment rail. Once a transaction is "posted", it is then considered immutable and cannot be changed. Any adjustments (such as a reversal, for example) requires the creation of a new transaction. ## Creating Transactions Transactions can be initiated in a few different ways: ### Directly, via the Synctera payment APIs: * Originating an ACH debit or credit ([ACH API Reference](/v2/reference/addtransactionout)) * An internal transfer between two Synctera accounts ([Internal Transfer API Reference](/v2/reference/createinternaltransfer)). ### Indirectly, via an external payment network: * A card transaction at an ATM or point-of-sale. * An incoming ACH debit or credit from another bank (such as a direct deposit). An integrator can subscribe various `TRANSACTION` webhook events to be notified when a transaction is created or updated, even when the transactions aren't directly initiated by your application. ## Anatomy of a Transaction The full spec for pending and posted transactions is documented in the API reference for [Pending Transactions](/v2/reference/getpendingtransactionbyid) and [Posted Transactions](/v2/reference/getpostedtransactionbyid) respectively, there are several fields worth describing in more detail: ### id The `id` of a transaction is a unique identifier for a particular payment. This identifier is preserved through the entire life-cycle of a transaction. This means that a pending transaction and its final posted transaction will share the same id. ### type The `type` of a transaction generally represents the "payment rail" that is being used. For ACH payments this will be `ach`, which debit card transactions will use `card`. ### subtype The `subtype` field represents the specific operation that initiated the transaction. For example, for card transactions, the subtype might be could be `atm_withdrawal` for taking money out of an ATM, or `pos_purchase` for any purchase made at a Point-of-Sale system. ### effective\_date The `effective_date` of a transaction represents the time that the transaction should be considered effective for the purposes of interest calculation. ### posted\_date This value is specific to posted transactions. This value represents the current banking day the transaction was initiated on, from the perspective of the sponsor bank. This doesn't always match up with the chronological time. Notably, "banking days" do not include weekends or bank holidays. As an example, of a payment is made on Friday at 9PM, the `effective_date` would have the current date/time the transaction was created, while the `posted_date` would actually be the following Monday. ### user\_data The `user_data` field represents key-value meta-data specific to a given payment rail. For example, transactions with type `ach` will have a `user_data` field containing ACH-specific meta-data (ACH return codes, trace numbers, or file names), which card transactions will have card-specific meta-data (merchant codes, etc...). This is **not** used for arbitrary metadata supplied by a Fintech, see [`external_data`](#externaldata) below. This field is only populated by internal Synctera payment services. Below is an example of a `user_data` from an ACH debit transaction that has been sent out to the ACH network (indicated by the `file_name` field being populated): ```json JSON theme={"system"} { "id": 1234, "idemkey": "87a964a7-9191-488d-bbb8-b4f9a39578f6", "exported": "2022-03-22T16:55:01.60644546Z", "file_name": "20220322T165501.596_OUTBOUND.ach", "account_id": "7b0ccc9f-957a-4e0b-bc4b-9a3d59c2eef6", "account_no": "1234567890", "customer_id": "226de0b5-e9b9-48f3-b562-c9bc3b35cd5b", "description": "KandaBank", "is_same_day": false, "trace_number": "601282010001234", "reference_info": "This is some reference info", "source_account_id": "d23b541b-1fda-4c3f-b44e-3605f2095618", "source_account_name": "Alberta Charleson" } ``` ### external\_data The `external_data` field will include any arbitrary key-value meta-data that you as a Fintech would like to associate with the payment. This is only available for payments initiated directly via one of the Synctera payment APIs (for example, an outgoing ACH payment, or an internal transfer). ### risk\_info The `risk_info` field is used to hold risk analysis details from Synctera's Risk/Fraud service. This is an example of a `risk_info` payload where the fraud service has determined that the transaction is not fraudulent: ```json JSON theme={"system"} { "accept": true, "reasons": ["TRANSACTION_ACCEPTED"], "provider": "FEEDZAI", "provider_info": { "alert": false, "score": 0, "status": "ok", "decision": "approve", "action_codes": ["[Transfers-DR6]"], "lifecycle_id": "c67c7799-f273-4318-8649-1378e42d64af", "sca_required": false, "sender_segment": "27", "event_external_id": "c67c7799-f273-4318-8649-1378e42d64af", "sender_bank_branch_id": "4", "secondary_action_codes": [] }, "provider_reasons": ["Transfers-DR6"] } ``` ### lines The `lines` field is specific to Posted Transactions. The Synctera Ledger uses a concept called [Double-Entry Accounting](https://en.wikipedia.org/wiki/Double-entry_bookkeeping) to help ensure the integrity of all financial operation. This means that every debit or credit to an account must be offset by a corresponding credit or debit to another account. This is represented in the [Posted Transaction resource](/v2/reference/getpostedtransactionbyid) by the `data.lines` field. This field is an array of (primarily) two accounting entries: A debit from one account, and a credit from another account. In many cases, only one side of a transaction will represent a real Synctera (customer) account. For example, consider an ACH payment to an external bank, or an ATM withdrawal. In this case, Synctera uses an [internal account](/v2/reference/listinternalaccounts), called a *settlement account* as a proxy to offset the transaction. ## Transaction Types and Subtypes Transactions (both pending and posted) are categorized using a combination of `type` and `subtype` fields, as mentioned above. The set of types and subtypes currently supported by the Synctera ledger are documented below: | Type | Subtype | D/C to originating party | | ------------------- | -------------------------------------------- | ------------------------ | | `ach` | `incoming_credit` | `Credit` | | `ach` | `incoming_credit_contested_return` | `Credit` | | `ach` | `incoming_credit_dishonored_return` | `Credit` | | `ach` | `incoming_credit_return` | `Credit` | | `ach` | `incoming_credit_reversal` | `Debit` | | `ach` | `incoming_debit` | `Debit` | | `ach` | `incoming_debit_contested_return` | `Debit` | | `ach` | `incoming_debit_dishonored_return` | `Debit` | | `ach` | `incoming_debit_return` | `Debit` | | `ach` | `incoming_debit_reversal` | `Credit` | | `ach` | `outgoing_credit` | `Debit` | | `ach` | `outgoing_credit_contested_return` | `Debit` | | `ach` | `outgoing_credit_dishonored_return` | `Debit` | | `ach` | `outgoing_credit_return` | `Debit` | | `ach` | `outgoing_credit_reversal` | `Credit` | | `ach` | `outgoing_debit` | `Credit` | | `ach` | `outgoing_debit_contested_return` | `Credit` | | `ach` | `outgoing_debit_dishonored_return` | `Credit` | | `ach` | `outgoing_debit_return` | `Credit` | | `ach` | `outgoing_debit_reversal` | `Debit` | | `ach` | `temp_hold` | `Debit` | | `card` | `auth` | `Debit` | | `card` | `auth_atm_withdrawal` | `Debit` | | `card` | `auth_quasi_cash` | `Debit` | | `card` | `pindebit_auth` | `Debit` | | `card` | `auth_cashback` | `Credit` | | `card` | `auth_incremental` | `Credit` | | `card` | `auth_clearing` | `Debit` | | `card` | `auth_clearing_atm_withdrawal` | `Debit` | | `card` | `auth_clearing_quasi_cash` | `Debit` | | `card` | `pindebit_auth_clearing` | `Debit` | | `card` | `auth_advice` | `Debit` | | `card` | `auth_reversal` | `Credit` | | `card` | `pindebit_auth_reversal` | `Credit` | | `card` | `oc_auth_reversal` | `Credit` | | `card` | `refund_auth_reversal` | `Credit` | | `card` | `refund` | `Credit` | | `card` | `pindebit_refund` | `Credit` | | `card` | `refund_auth_clearing` | `Credit` | | `card` | `pindebit_reversal` | `Credit` | | `card` | `balance_inquiry` | `Debit` | | `card` | `pindebit_balance_inquiry` | `Debit` | | `card` | `pindebit` | `Debit` | | `card` | `pindebit_atm_withdrawal` | `Debit` | | `card` | `pindebit_cashback` | `Credit` | | `card` | `pindebit_quasi_cash` | `Debit` | | `card` | `oc_auth` | `Debit` | | `card` | `oc_auth_clearing` | `Debit` | | `card` | `oc_auth_capture` | `Debit` | | `card` | `pindebit_refund_reversal` | `Debit` | | `card` | `refund_auth` | `Credit` | | `card` | `card_transaction` | `Debit` | | `card` | `pos_purchase` | `Debit` | | `card` | `atm_withdrawal` | `Debit` | | `card` | `pos_cashback` | `Credit` | | `card` | `credit` | `Credit` | | `card` | `pos_refund` | `Credit` | | `card` | `pos_purchase_refund` | `Credit` | | `card` | `provisional_credit` | `Credit` | | `card` | `card_network_first_chargeback` | `Credit` | | `card` | `card_network_final_chargeback` | `Credit` | | `card` | `provisional_credit_reversal` | `Debit` | | `check` | `mobile_deposit` | `Credit` | | `check` | `mobile_deposit_reversal` | `Debit` | | `check` | `mobile_deposit_return` | `Debit` | | `check` | `mobile_deposit_return_reversal` | `Credit` | | `external_card` | `card_funding` | `Credit` | | `external_card` | `card_funding_reversal` | `Debit` | | `external_card` | `card_send` | `Debit` | | `external_card` | `card_send_reversal` | `Credit` | | `internal_transfer` | `account_decrease_limit` | `Debit` | | `internal_transfer` | `account_decrease_limit_reversal` | `Credit` | | `internal_transfer` | `account_increase_limit` | `Credit` | | `internal_transfer` | `account_increase_limit_reversal` | `Debit` | | `internal_transfer` | `account_to_account` | `Debit` | | `internal_transfer` | `account_to_account_reversal` | `Credit` | | `internal_transfer` | `ach_credit_sweep` | `Debit` | | `internal_transfer` | `ach_credit_sweep_reversal` | `Credit` | | `internal_transfer` | `ach_debit_sweep` | `Credit` | | `internal_transfer` | `ach_debit_sweep_reversal` | `Debit` | | `internal_transfer` | `cashback` | `Debit` | | `internal_transfer` | `cashback_reversal` | `Credit` | | `internal_transfer` | `fee` | `Debit` | | `internal_transfer` | `fee_reversal` | `Credit` | | `internal_transfer` | `incoming_wire` | `Credit` | | `internal_transfer` | `incoming_wire_reversal` | `Debit` | | `internal_transfer` | `interest_payout` | `Credit` | | `internal_transfer` | `interest_payout_reversal` | `Debit` | | `internal_transfer` | `jit_fund` | `Debit` | | `internal_transfer` | `jit_fund_reversal` | `Credit` | | `internal_transfer` | `loc_usage` | `Debit` | | `internal_transfer` | `loc_usage_reversal` | `Credit` | | `internal_transfer` | `manual_adjustment` | `Debit` | | `internal_transfer` | `manual_adjustment_reversal` | `Credit` | | `internal_transfer` | `marketplace_bill_pay` | `Debit` | | `internal_transfer` | `marketplace_bill_pay_reversal` | `Credit` | | `internal_transfer` | `marketplace_event_tickets` | `Debit` | | `internal_transfer` | `marketplace_event_tickets_reversal` | `Credit` | | `internal_transfer` | `marketplace_gift_card` | `Debit` | | `internal_transfer` | `marketplace_gift_card_reversal` | `Credit` | | `internal_transfer` | `marketplace_mobile_top_up` | `Debit` | | `internal_transfer` | `marketplace_mobile_top_up_reversal` | `Credit` | | `internal_transfer` | `mastercard_gross_sweep` | `Debit` | | `internal_transfer` | `mastercard_gross_sweep_reversal` | `Credit` | | `internal_transfer` | `mastercard_interchange_sweep` | `Credit` | | `internal_transfer` | `mastercard_interchange_sweep_reversal` | `Debit` | | `internal_transfer` | `mastercard_net_sweep` | `Debit` | | `internal_transfer` | `mastercard_net_sweep_reversal` | `Credit` | | `internal_transfer` | `outgoing_international_remittance` | `Debit` | | `internal_transfer` | `outgoing_international_remittance_reversal` | `Credit` | | `internal_transfer` | `program_decrease` | | | `internal_transfer` | `program_decrease_reversal` | | | `internal_transfer` | `program_expansion` | | | `internal_transfer` | `program_expansion_reversal` | | | `internal_transfer` | `promotional_credit` | `Credit` | | `internal_transfer` | `promotional_credit_reversal` | `Debit` | | `internal_transfer` | `pulse_gross_sweep` | `Debit` | | `internal_transfer` | `pulse_gross_sweep_reversal` | `Credit` | | `internal_transfer` | `pulse_interchange_sweep` | `Credit` | | `internal_transfer` | `pulse_interchange_sweep_reversal` | `Debit` | | `internal_transfer` | `repayment` | `Credit` | | `internal_transfer` | `repayment_reversal` | `Debit` | | `internal_transfer` | `sign_up_bonus` | `Credit` | | `internal_transfer` | `sign_up_bonus_reversal` | `Debit` | | `internal_transfer` | `subscription_fee` | `Debit` | | `internal_transfer` | `subscription_fee_reversal` | `Credit` | | `internal_transfer` | `transfer_fee` | `Debit` | | `internal_transfer` | `transfer_fee_reversal` | `Credit` | | `wire` | `originated` | `Debit` | | `wire` | `originated_reversal` | `Credit` | | `wire` | `originated_return` | `Credit` | | `wire` | `originated_return_reversal` | `Debit` | | `wire` | `received` | `Credit` | | `wire` | `received_reversal` | `Debit` | ## The Transaction Life-cycle While specific details may differ slightly across different payment networks, most payments follow the same basic flow: 1. A hold is placed on an account for the requested amount. This is represented in the system as a pending transaction. 2. Synctera performs various account status, KYC, and fraud checks. If any of these checks fail, the pending transaction is declined. 3. The amount of the hold may be increased or decreased. This is mainly seen in the context of a card transaction. For example if you are at a gas station authorize $100 at the pump, but only end up filling up $50 worth. 4. At some point later the pending transaction either expires, is cancelled, or settles. When settled, this is represented as a new posted transaction. Depending on the type of payment, the time between steps (1) and (3) may be anywhere from a few seconds, to several days (in the case of ACH payments). Each time a transaction changes state, a webhook will be triggered. The exact events are described below: | Scenario | Webhook event(s) | Notes | | ------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | A hold is placed on an account | `TRANSACTION.PENDING.CREATED` | | | Hold amount is increased or decreased | `TRANSACTION.PENDING.UPDATED` | Final amount is reflected in `total_amount`. | | Fraud service declines transaction | `TRANSACTION.PENDING.UPDATED` | `status` field changes from `PENDING` to `DECLINED` to `DECLINED`. Additional risk data may be placed in `user_data`. | | Fraud service accepts transaction | `TRANSACTION.PENDING.UPDATED` | Additional risk data may be placed in `user_data`. | | Transaction expires | `TRANSACTION.PENDING.UPDATED` | `status` field changes from `PENDING` to `EXPIRED`. | | Transaction is posted to account | `TRANSACTION.PENDING.UPDATED`, `TRANSACTION.POSTED.CREATED` | Pending transaction `status` changes from `PENDING` to `POSTED`. A new "posted" transaction is created. | ## Transaction History Synctera provides 2 endpoints for viewing transactions: 1. [List pending transactions](/v2/reference/listpendingtransactions) retrieves all "pending" or "unsettled" transaction within a given time period 2. [List posted transactions](/v2/reference/listpostedtransactions) returns all "posted" or "settled" transactions within a given time period You can also take advantage of the `TRANSACTION` [Webhook](/v2/docs/webhooks-guide)) events to build your own transaction feed tailored to your specific use case. # Unsecured charge accounts Source: https://docs.synctera.com/v2/docs/unsecured-charge-accounts-guide ## Account Template of Charge card Account Templates contain predefined values for creating an account. When creating an account with an account template ID, the Accounts object inherits all values from the Account Template object first, before applying passed-in values. The Account Template API spec can be found [here](/v2/reference/createaccounttemplate) Some specific points regarding Account Template configuration for Charge card * `grace_period` - The number of days past the billing period to allow for payment before it is considered overdue. This directly infers the payment due date. This is a required field. * `account_type` - Use `CHARGE_UNSECURED` as account type for an unsecured charge account. This is a required field. ```bash Bash theme={"system"} curl -X POST \ -H 'Authorization: Bearer $apikey' \ -H 'Content-Type: application/json' \ -d ' { "name": "Charge Card Template", "description": "An account template for Charge card accounts", "is_enabled": true, "application_type": "CREDIT", "template": { "account_type": "CHARGE_UNSECURED", "currency": "USD", "bank_country": "US", "grace_period": 21, "minimum_payment": { "type": "FULL" } } }' $baseurl/v0/accounts/templates ``` ## Unsecured Charge card Account ### API fields The Account API has certain fields that are specific to Line of Credit. These fields are: | Field Name | Description | Example | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | | account\_type | For Charge card, please set this field as `CHARGE_UNSECURED` | `CHARGE_UNSECURED` | | `application_id` | Charge cards require the customer application to be approved and accepted by the applicant ([details](/v2/docs/credit-applications-guide)). `application_id` is required for creating an unsecured charge card account. | | | `credit_limit` | Defined in cents, the credit limit for this account. | `100000` (i.e., \$1000) | Example Create an account of type `CHARGE_UNSECURED` (refer to the [Accounts API spec](/v2/reference/createaccount), or the [Accounts Guide](/v2/docs/create-accounts-guide)) ```bash Bash theme={"system"} curl -X POST \ -H 'Authorization: Bearer $apikey' \ -H 'Content-Type: application/json' \ -d ' { "account_template_id": "{ACCOUNT_TEMPLATE_UUID}", "account_purpose": "Charge Card Account", "credit_limit": 100000, "application_id": "{APPLICATION_UUID}", "relationships": [ { "relationship_type": "PRIMARY_ACCOUNT_HOLDER", "customer_id": "{CUSTOMER_UUID}" } ] }' $baseurl/v0/accounts ``` Sample response body ```json JSON theme={"system"} { "access_status": "ACTIVE", "account_number": "790586668526", "account_purpose": "Charge Card Account", "account_type": "CHARGE_UNSECURED", "balance_ceiling": { "balance": 100000 }, "balances": [ { "balance": 20000, "type": "ACCOUNT_BALANCE" }, { "balance": 80000, "type": "AVAILABLE_BALANCE" } ], "bank_routing": "112233445", "creation_time": "2022-04-07T20:37:46.356692Z", "currency": "USD", "customer_ids": ["{CUSTOMER_UUID}"], "customer_type": "PERSONAL", "id": "3389aeac-0163-4479-8702-ff8572d39fe8", "is_account_pool": false, "last_updated_time": "2022-04-07T20:37:46.356692Z", "status": "ACTIVE", "is_ach_enabled": true, "is_card_enabled": true, "is_p2p_enabled": true, "minimum_payment": { "type": "FULL" }, "application_id": "{APPLICATION_UUID}", "metadata": {}, "grace_period": 21 } ``` # Charge card Source: https://docs.synctera.com/v2/docs/v1-charge-card A Charge card is a type of payment card that requires the cardholder to pay the full balance owed each month by the statement due date. Unlike credit cards, charge cards do not allow for revolving credit, i.e. cardholders can not carry over a balance from one month to the next. If the cardholder fails to pay the full balance by the due date, they may be subject to significant penalties, including suspension on card usage, or cancellation of the card / closure of account. Since the balance must be paid in full each month, there are no interest charges with charge cards. Charge cards may not have a pre-set credit limit. However, the spending limit may vary based on cardholder spending habits, payment history, credit record, and other financial factors. Like credit cards, the use of a charge card can influence cardholder's credit history. Timely payments can positively affect their credit scores, while late payments or non-payments can have a negative impact. Charge cards can be issued to consumer or business. ## Program Setup prior issuing Charge card Your organization has to be given specific privileges to be able to issue charge cards. Please reach out to your contact at Synctera for more information. ## Creating a Charge card Product To issue a Charge card product, the following steps have to be completed: As a precursor, the person set-up has to be completed ([Person API spec](/v2/docs/create-a-personal-customer)), including passing the KYC/KYB process via [KYC Verification API Overview](/v2/docs/kyc-kyb-verification) These must be accepted by the personal or business customers (including credit agreement). See the [disclosures section](#disclosures) for details. A `CHARGE_UNSECURED` account cannot be created until the customer applies for an unsecured charge card via the Application API. Overview [here](/v2/docs/credit-applications-guide) Setting up an Account Template for `CHARGE_UNSECURED`. See the unsecured charge account API guide [here](/v2/docs/unsecured-charge-accounts-guide). Creation of the charge account. See the unsecured charge account API guide [here](/v2/docs/unsecured-charge-accounts-guide). See the [personal cards guide](/v2/docs/personal-cards) for further details. If a charge card application is denied, adverse action reasons need to be sent to the personal customers (optional for business customers) and the adverse actions ID needs to be included in the charge card application when the application status is marked as `CREDIT_DENIED`. See the Adverse Actions API spec [here](/v2/reference/createadverseaction). ### Disclosures As the application and the accounts are being created, the fintech has to inform Synctera of the Disclosures acknowledged by the applicant. Specifically for Charge card, the required disclosures include: At the time the Application is created 1. E-Sign 2. Privacy Notice 3. USA Patriot Act Notice 4. Owner Certification (for business customers) Prior to the Account being created 1. Account Terms & Conditions 2. ACH Authorization Please see details for the Disclosures here - [Customer Disclosures](/v2/docs/record-disclosure-acceptance) # Line of Credit Source: https://docs.synctera.com/v2/docs/v1-line-of-credit A Line of Credit (LoC) account is used to offer unsecured credit to customers of a fintech. It allows a borrower to utilize funds, as needed, up to a predetermined limit. The borrower may then repay the funds and borrow again as needed. The `curl` examples assume you have set up `baseurl` and `apikey` environment variables. See [Base URL](/v2/reference/environments) and [Authentication](/v2/reference/authentication) for instructions. Some examples depend on identifiers generated by previous steps. These are indicated like `{APPLICATION_ID}`. ## Program Setup prior issuing Line of Credit Your organization has to be given specific privileges to be able to issue line of credit. Please reach out to your contact at Synctera for more information. ## Creating a Line of Credit Product To create a Line of Credit, the following steps have to be completed: As a precursor, the person set-up has to be completed ([Person API spec](/v2/docs/create-a-personal-customer)), including passing the KYC/KYB process via [KYC Verification API Overview](/v2/docs/kyc-kyb-verification) These must be accepted by the personal or business customers (including the credit agreement). See the [disclosures section](#disclosures) for details. An LoC account cannot be created until the customer applies for a line of credit via the Application API. Overview [here](/v2/docs/credit-applications-guide) Define the interest rates charged on the LoC account. See the LoC Account API guide [here](/v2/docs/line-of-credit-accounts-guide). Setting up an Account Template specific for Line of Credit. See the LoC Account API guide [here](/v2/docs/line-of-credit-accounts-guide). Creation of the LoC account. See the LoC Account API guide [here](/v2/docs/line-of-credit-accounts-guide). If a LoC application is denied, adverse action reasons need to be sent to the personal customers (optional for business customers) and the adverse actions ID needs to be included in the LoC application when the application status is marked as `CREDIT_DENIED`. See the Adverse Actions API spec [here](/v2/reference/createadverseaction). ### Disclosures As the application & the accounts are being created FinTech has to inform Synctera of the Disclosures acknowledged by the applicant. Specifically for Line of Credit, the required disclosures include: At the time the Application is created 1. E-Sign 2. Privacy Notice 3. USA Patriot Act Notice 4. Owner Certification (for business customers) Prior to the Account being Created 1. Account Terms & Conditions 2. ACH Authorization Please see details for the Disclosures here - [Customer Disclosures](/v2/docs/record-disclosure-acceptance) # Synctera Smart Card Source: https://docs.synctera.com/v2/docs/v1-smart-card The first Synctera consumer credit card offering is a dynamically secured charge card, which we call a **Synctera Smart Card**. As a secured card, this product does not require the customer to have a long, rich credit history. However, unlike a traditional secured card, its spending power does not come from a fixed deposit; rather, it is based on the available funds of a customer's linked deposit account. This enables a consumer to make purchases on their charge card, while retaining the ability to access the funds that help secure it. As the customer makes purchases using the charge card, the available funds in the linked deposit account decrease, as does the card's spending power. When the card balance is repaid by the customer, the funds in the linked deposit account are made available again, and the card's spending power is restored. The Synctera Smart card product comprises two accounts: * A [deposit account](/v2/docs/checking-savings-accounts-guide) as the security account * A [secured charge account](/v2/docs/secured-sc-accounts-guide) ## Creating a Smart card product To issue a Smart card product, the following steps have to be completed: As a precursor, a [person must be setup](/v2/docs/create-a-personal-customer), and [KYC/KYB verification](/v2/docs/kyc-kyb-verification) must be completed. These must be accepted by the personal or business customers (including the credit agreement). See the [disclosures section](#disclosures) for details. A charge secured account can optionally include an application which can be created via the Application API. Overview [here](/v2/docs/credit-applications-guide). If a charge secured application is denied due to KYC failure or other reasons, adverse action reasons need to be sent to the personal customers (optional for business customers) and the adverse actions id needs to be included in the charge secured application when the application status is marked as `CREDIT_DENIED`. See the Adverse Actions API guide \[here]. See the relevant guide [here](/v2/docs/secured-sc-accounts-guide#using-a-customer-dda-as-a-linked-deposit-account). See the relevant guide [here](/v2/docs/secured-sc-accounts-guide#creating-a-charge_secured-account) See the [personal cards guide](/v2/docs/personal-cards) for further details. See the [external accounts guide](/v2/docs/external-accounts-guide) for further details. This will be a combined statement for both accounts. See the [secured charge statement guide](/v2/docs/charge-secured-statements-guide) for further details. ### Disclosures Before a Smart card product can be used, the FinTech has to inform Synctera of relevant disclosures acknowledged by the customers. When the consumer is being onboarded: 1. USA Patriot Act Notice 2. E-Sign 3. Privacy Notice After the consumer has been onboarded: 1. Smart card account agreement 2. Security agreement 3. (Optional) Authorization for automatic payments (from the security account) For more details on recording acceptance of individual disclosures, see the [disclosure guide](/v2/docs/record-disclosure-acceptance). ### Issue a charge card When issuing a Smart card, the card type shall be `CREDIT`. You may issue physical or virtual cards. ### Smart card autopay enablement When setting up charge secured account with system autopay, Fintech can 1. Use disclosure API to send "SC\_AUTO\_PAYMENT" as "ACKNOWLEDGED" when customer opt in to auto pay, then create a charge secured account setting `is_system_auto_pay_enabled` = `true`. This flow is commonly used during the onboarding process OR 2. Create a charge secured account (`is_system_auto_pay_enabled` default is `false`). Then use disclosure API to send "SC\_AUTO\_PAYMENT" as "ACKNOWLEDGED" when customer opts in. Afterward, patch the `is_system_auto_pay_enabled` to be `true`. This flow can be used during onboarding or customer decides to opt in after account is created. The validation check from Synctera would ensure that `is_system_auto_pay_enabled` cannot be set to `true` for charge secured accounts unless autopay disclosure has been acknowledged by that customer. While we continue improving our V1 guides, please visit our [Cards V1 API](/v2/reference/issuecard) for details on how to issue a card of type `CREDIT`. # Verification Response Codes Source: https://docs.synctera.com/v2/docs/verification-response-codes Synctera passes through the outcome codes to the Develop to provide more transparency on the outcome of KYx verifications. These codes can be seen in Console for each Customer, or returned via the API. ### KYC Response Code Mappings Each code allows a suggested Accept, Review or Reject - these are not the sole measures of a Customer outcome, but are shared in order to provide feedback to the Developer in order to provide more clarity during the onboarding process. | Module | Rule | Outcome | Description | | --------- | ---- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | KYC | I903 | REJECT | Address was not provided at input | | KYC | I906 | REJECT | DOB was not provided at input | | KYC | I917 | REJECT | Full name and address can be resolved to the individual but the SSN / ITIN is not | | KYC | R704 | REJECT | Address is a correctional facility | | KYC | R901 | REJECT | SSN / ITIN cannot be resolved to the individual | | KYC | R907 | REJECT | SSN has been reported as deceased | | KYC | R909 | REJECT | Identity has been reported as deceased | | KYC | R911 | REJECT | SSN issued prior to DOB | | KYC | R913 | REJECT | SSN / ITIN is invalid | | KYC | R932 | REJECT | Address is a correctional facility | | KYC | R933 | REJECT | Last name is not correlated with the SSN / ITIN on record | | KYC | R940 | REJECT | SSN / ITIN not found in public records | | KYC | R963 | REJECT | Address ZIP code only serves PO Boxes | | Address | I911 | REJECT | Address is a PO Box | | Address | R703 | REVIEW | Address is invalid or does not exist | | Address | R705 | REVIEW | Address cannot be resolved to the individual | | Address | R707 | REJECT | Address is a commercial mail receiving agency or commercial mail drop | | Address | R708 | REJECT | Address is a PO Box | | Address | R916 | REVIEW | Address is invalid or does not exist | | Address | R963 | REJECT | Address ZIP code only serves PO Boxes | | Address | R972 | REVIEW | Address is a commercial mail receiving agency | | Address | R973 | REJECT | Address is a unique ZIP code, or corporate only, routing all mail internally by the assigned organization rather than by the USPS | | Synthetic | R298 | REVIEW | Identity resembles a manipulated Synthetic identity | | Synthetic | R299 | REVIEW | Identity resembles a fabricated Synthetic identity | | Synthetic | R703 | REVIEW | Address is invalid or does not exist | | Synthetic | R705 | REVIEW | Address cannot be resolved to the individual | | Synthetic | R901 | REJECT | SSN / ITIN cannot be resolved to the individual | | Synthetic | R922 | REVIEW | DOB cannot be resolved to the individual | | Synthetic | R940 | REJECT | SSN / ITIN not found in public records | | Fraud | R210 | REVIEW | Frequency of SSN in Socure records is unusually high | | Fraud | R621 | REVIEW | Phone number has been in service less than 7 days | | Fraud | R622 | REVIEW | Phone number has been in service between 7 and 30 days | | Fraud | R652 | REVIEW | IP address is associated with spam activity | | Fraud | R704 | REJECT | Address is a correctional facility | | Phone | R621 | REVIEW | Phone number has been in service less than 7 days | | Phone | R622 | REVIEW | Phone number has been in service between 7 and 30 days | | Alert | R110 | REJECT | Email on Alert List | | Alert | R111 | REJECT | SSN on Alert List | | Alert | R113 | REJECT | Phone Number on Alert List | | Document | I808 | REJECT | Document image resolution is insufficient | | Document | I846 | REVIEW | Expired document within the grace period specified | | Document | I848 | REVIEW | The document is not captured properly | | Document | I849 | REVIEW | Incorrect ID type selected | | Document | I854 | REVIEW | The back of the license was not passed; no barcode to extract information | | Document | I860 | REVIEW | Facial correlation was not calculated | | Document | R810 | REJECT | Document pattern and layout integrity check failed | | Document | R819 | REJECT | Image captured from a screen, or is a paper copy of an ID | | Document | R820 | REVIEW | Document headshot has been modified | | Document | R822 | REVIEW | First name extracted from document does not match input first name | | Document | R823 | REVIEW | Last name extracted from document does not match input last name | | Document | R824 | REVIEW | Address extracted from document does not match input address | | Document | R825 | REVIEW | DOB extracted from document does not match input DOB | | Document | R826 | REVIEW | Document Number extracted from document does not match input number | | Document | R827 | REJECT | Document is expired | | Document | R831 | REVIEW | Cannot extract the minimum information from barcode | | Document | R833 | REVIEW | Cannot extract the minimum required information from MRZ | | Document | R834 | REVIEW | Selfie fails the liveness check | | Document | R838 | REVIEW | Minimum amount of information cannot be extracted from document | | Document | R850 | REVIEW | Self-portrait or the headshot is not usable for Facial Match | | Document | R853 | REJECT | Unable to classify the ID or this is an unsupported ID type | | Document | R856 | REVIEW | Obstructions on the face affecting the liveness | | Document | R857 | REJECT | No face found in the selfie frame | | Document | R858 | REVIEW | The age on the document doesn't correlate with the selfie predicted age | | Document | R859 | REJECT | ID front correlates with another submitted ID front | The codes above can be used to provide feedback to the Customer on the outcome of the verification attempt while the Console can be used to align with the Synctera Ground Control team in order to verify next steps for the Customer being onboarded. # Webhooks Source: https://docs.synctera.com/v2/docs/webhooks-guide The Webhook API enables integrators to subscribe to specific events on the Synctera platform. ## Overview Additionally, this API helps integrators reduce the number of requests to the Synctera platform for resource checks. For example, when a customer swipes a card, the Webhook API, if subscribed, will send a `POST` request to the predefined URL about the transaction. With webhooks, Synctera will push updates to the integrator instead of the integrator pulling updates. ### Understand Webhooks and Events Creating a webhook defines what events the integrator wants to subscribe to via the `event_types` field. The following example shows how to subscribe to account updates and customer events. Use the request body of `POST /v0/webhooks` to create a webhook. `enabled_events` specifies that this webhook should be invoked whenever an account is updated, or when anything happens to a customer. Once such an event occurs, the Webhook API sends a `POST` request to `https://example.com`. ```json JSON theme={"system"} { "enabled_events": ["ACCOUNT.UPDATED", "CUSTOMER.*"], "is_enabled": true, "url": "https://example.com" } ``` Most events use the `.[.]` naming convention. For example, `ACCOUNT.UPDATED` means an account was updated. Resources can have sub-resources: `TRANSACTIONS.POSTED.CREATED` means to subscribe to changes of the sub-resource `TRANSACTION.POSTED`. You can also use a wildcard `*` for convenience purposes. For example, you can use it after a `` like `CUSTOMER.*`, which allows you to receive notifications for all the customer events without explicitly listing all of them. Note that Synctera will continuously add more events, so the webhook will automatically subscribe to any new events added to `` and send requests. ### Integration Steps 1. Create a signature secret for request validation 2. Implement a server to receive webhook requests 3. Create a webhook for events 4. Triggering events To ensure that your incoming webhook requests come from Synctera, you must cryptographically validate each request as it arrives. Synctera will use a shared secret to sign each webhook request before sending it to you, and then you will use the same secret to validate requests. To create a webhook secret, call [`POST /v0/webhook_secrets`](/v2/reference/createsecret) with an empty request body: ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v0/webhook_secrets \ -H "Authorization: Bearer $apikey" \ --data-binary '' ``` Synctera will respond with the generated secret in the response: ```json JSON theme={"system"} { "secret": "{signature_secret}" } ``` You must use the same secret to validate all incoming webhook requests. **Secret Replacement** You may want to rotate the secret or immediately replace it for security purposes. To rotate a secret: 1. Call [`PUT /v0/webhook_secrets`](/v2/reference/replacesecret) to deprecate the old secret and generate a new one. Set the `is_rolling_secret` field to `true` to generate the new secret without deleting the old secret right away. ```bash Shell theme={"system"} curl \ -X PUT \ $baseurl/v0/webhooks/secret \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ --data-binary ' { "is_rolling_secret": true }' ``` The request deletes the last secret in 24 hours, so you will have time to update it. If you want to delete the last secret immediately without waiting for 24 hours, call [`DELETE /v0/webhook_secrets?old_secret_only=true`](/v2/reference/revokesecret) The applications that receive webhook requests should be publicly accessible so the Synctera platform can send the webhook request to the URL defined in the webhook resource. The schema for the webhook request is defined in the **OpenAPI spec** as `webhook_request_object`. **Request Headers** The request uses the `POST` method and contains the following headers: * `Synctera-Signature` - This is the signature of the request. Use the signature secret generated from step 2 to verify the request body. * `Request-Timestamp` - The time when Synctera's platform sent the request, as a POSIX timestamp: seconds since 1970-01-01 00:00:00 UTC. * `Content-Type` - Has the value `application/json`. **Example Request Body** ```json JSON theme={"system"} { "id": "8145af83-0423-488f-8799-1c8c0bf8b189", "url": "http://example.com", "webhook_id": "873f7f9c-3063-4098-adcf-1f3af25286f8", "type": "ACCOUNT.UPDATED", "event_time": "2022-01-25T11:45:54.485698-05:00", "metadata": "test webhook", "event_resource": "{\"id\":\"7fef9ad7-67dc-4af0-9ce2-70011131c20c\", \"status\": \"ACTIVE_OR_DISBURSED\" ... }", "event_resource_changed_fields": "{\"status\": \"RESTRICTED\"}" } ``` * `id` - The current event ID * `url` - The URL that you specified in your webhook, also the endpoint you will receive this request. * `webhook_id` - The ID of the webhook that sends out this request * `type`- The event type * `metadata` - The same value as the `metadata` defines in the webhook * `event_resource` Escaped JSON string representing the `` of the event. If the type has ``, then the string represents the sub-resource. * `event_resource_changed_fields` Escaped JSON string representing the top level fields that have been updated by the event, containing the value prior to the event. Only update event includes this field. **Resource JSON string example** * object before change: `{"a": 1, "b": 2, "c": 3, "n": {"m": 1}}` * object after change: `{"a": 4, "c": 3, "d": 5, "n": {"m": 1, "p": 2}}` `event_resource` is just the "object after change" itself. `event_resource_changed_fields` is `{"a": 1, "b": 2, "d": null, "n": {"m": 1}}` because: * `a` has value changed, value in `before-change object` is 1 * `b` is deleted from the object, value in `before-change object` is 2 * `c` is not changed, so it is not included in `event_resource_changed_fields` * `d` is added to the object, value is null because `before-change object` does not have it * `n` is a nested object where sub-field `p` is added. Note that the old value of the entire top level field `(n)` is included in the old value, and that added sub-fields (e.g. `p`) are not included. Therefore, `event_resource_changed_fields` from the original request body means the account resource has been updated. The account status was changed from `RESTRICTED` to `ACTIVE_OR_DISBURSED`. **Request Validation** The `Synctera-Signature` is generated via [HMAC](https://en.wikipedia.org/wiki/HMAC) with SHA256 hash and the signature secret as the key. The expected value of the `Synctera-Signature` is `HMAC256({request_timestamp} + '.' + {request_body}, {signature_secret_key})`. Your service should validate the header matches what you expect. Furthermore, `Synctera-Signature` may include two signature strings delimited by `.` during the rolling secret period, which the old and new signature secrets generate. To prevent replay attacks, integrators should check that the request time is within 5 minutes of `now()` See the example code below in Go to handle signature validation: ```go go theme={"system"} func ValidateSignature(secret string, payload []byte, reqTime string, signature string) error { // Parse request time reqTimeVal, err := strconv.ParseInt(reqTime, 10, 64) if err != nil { return err } // Generate the signature mac := hmac.New(sha256.New, []byte(secret)) if _, err := mac.Write([]byte(reqTime + ".")); err != nil { return err } if _, err := mac.Write(payload); err != nil { return err } generatedSignature := hex.EncodeToString(mac.Sum(nil)) // Verify with the signature header for _, curSign := range strings.Split(signature, ".") { if generatedSignature != curSign { continue } reqT := time.Unix(reqTimeVal, 0) if !reqT.Add(time.Minute * 5).After(time.Now()) { return errors.New("signature expired") } return nil } return errors.New("invalid signature") } ``` **Response** The Webhook API expects an HTTP `200` response to indicate that the application processed the request successfully. Any `4xx` or `5xx` level code will be considered a failure on the application side. The Webhook API will retry the same request with exponential backoff until a successful response is received or 55 hours have passed. Events (successful or failed) are retained for 60 days. **Request timeout** Webhook requests will timeout after 5 seconds. Should a webhook request timeout, Synctera will automatically retry with exponential back off. Call the [`POST /v0/webhooks`](/v2/reference/createwebhook) endpoint to create a webhook subscription. For example, If you have deployed your new service so it is accessible on the public Internet at `https://api.example.com/webhook`: ```bash Shell theme={"system"} curl \ -X POST \ $baseurl/v0/webhooks \ -H "Authorization: Bearer $apikey" \ -H 'Content-Type: application/json' \ --data-binary ' { "url": "https://api.example.com/webhook", "description": "random test", "enabled_events": ["ACCOUNT.*", "CUSTOMER.UPDATED"], "metadata": "nothing", "is_enabled": true }' ``` * `url` is the endpoint that Synctera's webhook service will send requests to * `description` is a brief string that you use to describe the purpose of this webhook (mainly as a reminder to yourself) * `enabled_events` is the list of events that the webhook should subscribe to * `metadata` is an arbitrary string which will be included in every request body as the field `metadata` * `is_enabled` means the webhook should send requests for matching events; if false, events will be ignored Once you create the webhook, it will send requests for any newly triggered events. Subscribing to a wildcard event, e.g. `ACCOUNT.*`, will send all webhooks for all events that match that pattern. Note that this can include new event types added after the subscription was created. Webhook requests are not guaranteed to be real-time calls. In most cases Synctera will send a webhook immediately after an event occurs in most. However, in rare cases the delay could be 15-30 seconds on average. Your app should rely on synchronous responses for time sensitive operations. Webhook requests may be delivered multiple times, e.g. if Synctera does not receive a 200 response and therefore retries. Your application must handle duplicate requests, e.g. by checking the event ID. Similarly, webhook requests are not guaranteed to be delivered in order. If you update customer A, then customer B, then customer A again, then those three webhooks are *usually* delivered in that order. But when errors happen, all bets are off. You should *not* assume that the state of a resource included in a webhook request is the latest state. If you need the latest state, you should fetch it with an API call back to Synctera. We highly recommend testing your application to ensure it can receive the webhook request. There are several useful endpoints to test if the application is working correctly. * [`POST /v0/webhooks/trigger`](/v2/reference/triggerevent) fires a mock event on the Synctera platform, which triggers all the webhooks that match the event (specified in the request body) to send out a request. This will help debug the application without having to CRUD on the actual resource. However, note that the webhook response body will **NOT** contain `event_resource` in this case. * [`GET /v0/webhooks//events/`](/v2/reference/getevent) returns the event with the history of the request sent, including those failed attempts with the response body. * [`POST /v0/webhooks//events//resend`](/v2/reference/resendevent) will trigger it to send the webhook request with the same event again, without waiting for the next automatic retry attempt. # Create a address Source: https://docs.synctera.com/v2/reference/createaddress openapi-v2.json post /addresses Create a address. # Create disclosure record Source: https://docs.synctera.com/v2/reference/createdisclosure openapi-v2.json post /disclosures Record the fact that a regulatory document was disclosed to a customer. # Create a person Source: https://docs.synctera.com/v2/reference/createperson openapi-v2.json post /persons Create a person who may act as a personal customer or a director/officer/owner of a business. You can then verify the identity of this customer and associate them with other people and accounts. Note that if no shipping_address attribute is provided in the request, the shipping_address will be set to a copy of the legal_address. # Create a personal identifier Source: https://docs.synctera.com/v2/reference/createpersonalid openapi-v2.json post /persons/personal_ids Create a personal identifier, e.g. SSN, for this customer # Subscribe a customer or business to monitoring Source: https://docs.synctera.com/v2/reference/createsubscription openapi-v2.json post /monitoring/subscriptions This endpoint is rarely needed. Since August 2022, watchlist monitoring is automatically enabled for all businesses and customers who are verified (KYC/KYB) through Synctera's platform. # Delete a personal identifier Source: https://docs.synctera.com/v2/reference/deletepersonalid openapi-v2.json delete /persons/personal_ids/{personal_id_id} Delete personal identifier # Delete monitoring subscription Source: https://docs.synctera.com/v2/reference/deletesubscription openapi-v2.json delete /monitoring/subscriptions/{subscription_id} # Get address information by id Source: https://docs.synctera.com/v2/reference/getaddress openapi-v2.json get /addresses/{address_id} Get address information by its unique identifier # Retrieve a monitoring alert Source: https://docs.synctera.com/v2/reference/getalert openapi-v2.json get /monitoring/alerts/{alert_id} # Get disclosure Source: https://docs.synctera.com/v2/reference/getdisclosure openapi-v2.json get /disclosures/{disclosure_id} Get disclosure by ID. # Get person Source: https://docs.synctera.com/v2/reference/getperson openapi-v2.json get /persons/{person_id} Get person by ID. # Retrieve monitoring subscription Source: https://docs.synctera.com/v2/reference/getsubscription openapi-v2.json get /monitoring/subscriptions/{subscription_id} # Introduction Source: https://docs.synctera.com/v2/reference/introduction The API Reference describes our RESTful APIs endpoints. Each endpoint description provides the information you’ll need to form requests and handle responses: parameters for request path, request body, and responses. You’ll also find example requests and responses. ## API Preview Features that may be useful to integrators are accessible as early as possible on the Synctera platform. We have a few stages of API release: alpha, beta, stable. Any endpoint that is not tagged as alpha or beta is stable. **alpha** - Alpha APIs are previews of APIs in development with plans to hit stable release within 3 months. Alpha APIs are meant to collaborate with early partners to refine functionality. Endpoints will only be available in sandbox and may return a 501 not implemented or a stubbed mock response. Please reach out to your point of contact at Synctera if you'd like to provide feedback or collaborate with us on development. **beta** - Beta APIs are meant to enable testing a feature in production but not for use with real end customers. Beta APIs are fully functional, but may experience breaking changes before final stable release. Should Synctera need to make any breaking changes, Beta partners will be notified and given ample time to update. Beta API features may also be unstable. Please reach out to your point of contact at Synctera if you'd like to provide feedback or request additional details on planned updates. **stable** - Stable APIs are ready for end customers in production. **deprecated** - APIs marked as deprecated will no longer be supported in the next version of the API. # List Addresses Source: https://docs.synctera.com/v2/reference/listaddresses openapi-v2.json get /addresses # List monitoring alerts Source: https://docs.synctera.com/v2/reference/listalerts openapi-v2.json get /monitoring/alerts # List disclosures Source: https://docs.synctera.com/v2/reference/listdisclosures openapi-v2.json get /disclosures Retrieves paginated list of disclosures associated with the authorized requester. # List persons Source: https://docs.synctera.com/v2/reference/listpersons openapi-v2.json get /persons Retrieves paginated list of persons associated with the authorized requester. # List monitoring subscriptions Source: https://docs.synctera.com/v2/reference/listsubscriptions openapi-v2.json get /monitoring/subscriptions # Need to Know Source: https://docs.synctera.com/v2/reference/need-to-know ## Request Validation Synctera will not correct your requests other than for potential abuse / sanitization. You will need to validate and clean your input to ensure that your customer information is usable for features like KYC or mailing physical cards. ## Environments ## Base URLs The base URL for your request determines whether the request goes to the Synctera sandbox or, when you’ve rolled your code out for real, to the Synctera production environment where your requests will transact business in the real world. Use the sandbox base URL to make requests of the sandbox, and the production base URL to make requests of the real Synctera platform. | Environment | URL | | ----------- | -------------------------------------------------------------------- | | Sandbox | [https://api-sandbox.synctera.com](https://api-sandbox.synctera.com) | | Production | [https://api.synctera.com](https://api.synctera.com) | The examples in the Guides assume that you have set an environment variable `baseurl`, e.g. ```shell shell theme={"system"} export baseurl=https://api-sandbox.synctera.com ``` You also need to set `apikey`, see the [Authentication](/reference/need-to-know#authentication) section for more details. ## Sandbox You can experiment with our APIs in the Synctera sandbox, which is self-contained and has no interaction with the real world. You can use our sandbox to test our underlying services, accessing our vendors’ sandboxes as necessary when using their services. You’ll need an API key to authorize requests to the sandbox. If you don’t have one: 1. Switch to your Sandbox workspace using the workspace selector at the top of the screen 2. In the "Welcome to your Sandbox" view, click "Generate", then click the Copy icon to copy the key 3. Save the key by pasting it somewhere you can later retrieve it ## Authentication You authenticate each request by presenting your API key in the request header. `Authorization: Bearer {API_KEY}` For example, the beginning of a request using a fictitious key: ```shell Shell theme={"system"} curl https://api-sandbox.synctera.com/v2/customers \ -H 'Authorization: Bearer 476d901b4-a264a79-9db9-96d3dfaafb732' ``` The examples in the Guides assume that you have set an environment variable `apikey`, e.g. ```shell Shell theme={"system"} export apikey=476d901b4-a264a79-9db9-96d3dfaafb732 ``` You also need to set `baseurl`, see the [Environments](/reference/need-to-know#environments) section for more details. ## Idempotency All of our API endpoints support idempotency, in which a request defines a state, not an action. If you repeat an idempotent request through accident or because you're unsure if an earlier request made it through, the repeated requests won't accumulate with unintended results. If you repeat an idempotent request three times to credit an account with \$30, for example, you won't accidentally credit \$90, you will credit the intended \$30. The response to any request made with an idempotency header is cached, and a subsequent request with the same idempotency key will return the cached response, including the original response status code. Our endpoints support idempotency as defined in the [IETF draft specification](https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header-02). To send an idempotent request, add the header `Idempotency-Key: {KEY}` to your request, where `{KEY}` is an arbitrary value that you generate. When you repeat a request (e.g. because of an error or timeout), you need to send the same idempotency key as the previous attempt. When sending a distinct (not repeated) request, you must send a new, distinct, idempotency key. Each idempotency key and any resulting cached responses persist for 7 days and then disappear. An example of a cURL request using an idempotent request header with an example key value of 259: ```shell Shell theme={"system"} curl -X POST https://api-sandbox.synctera.com/v2/customers \ -H 'Idempotency-Key: 259' ``` ### Errors and Idempotency In general, requests that return an error are cached in the same way as successful requests. The following specific cases are exceptions. A repeat of these requests with the same idempotency key will re-execute the request and not return a cached response: * 500-series status codes are not cached, since they may not have been fully executed * requests that are rate-limited and return a 429 status code are not cached An idempotency key can only be re-used for the same request. If you try to use it with a different request, you will receive a 422 response with an `IDEMPOTENCY_INVALID_REUSE` error code. If you re-use an idempotency key while the previous request is still being processed, you will receive a 409 response with an `IDEMPOTENCY_CONCURRENT_USE` error code. ### Synctera Money Movement Endpoints Currently the Synctera ledger (including all POST and PATCH endpoints that deal with transactions or money transfers) implements a stricter form of idempotency. For these endpoints: 1. An idempotency key header is required. Requests missing an idempotency key header will result in a 400 Bad Request with the message "missing Idempotency-Key header". 2. The response to successfully executed requests is not cached. Instead, subsequent requests with the same idempotency key will result in a 409 Conflict response with the message "duplicate idempotency key". 3. Idempotency keys used by successfully executed requests persist indefinitely. They are persisted on a per resource basis where the resources are pending transactions and posted transactions. These idempotency keys can never be re-used for another resource of the same type, i.e, given a posted transaction with id 123, another posted transaction with id 123 would result in a 409 Conflict but a pending transaction with id 123 would be successful. ## Customer Device Fingerprinting All our API endpoints support customer device fingerprinting, requiring the use of the `Customer-Device-Info` header. This header is used to provide information about the customer's device and must be included in the request headers for all API endpoints. The `customer_id` must match the customer/business ID in the request parameters. The IP address must be the customer's IP address in IPv4 or IPv6 format. This header should be included in scenarios such as: * Requests made for "internal purposes" by a FinTech, such as loading all account balances at the end of the day. * Requests made on behalf of an end-customer, such as initiating a transaction or viewing account details. The `Customer-Device-Info` header would look like this: ```json JSON theme={"system"} "Customer-Device-Info": { "customer_id": "123e4567-e89b-12d3-a456-426614174000", "ip_address": "123.456.789.012", "device_type": "iOS", "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1" } ``` Here's a curl example of how to include the `Customer-Device-Info` header in a request: ```shell Shell theme={"system"} curl -X POST https://api-sandbox.synctera.com/v2/customers \ -H 'Customer-Device-Info: {"customer_id":"123e4567-e89b-12d3-a456-426614174000","ip_address":"123.456.789.012","device_type":"iOS","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}' ``` * For **end-customer calls**, set customer\_id to the person’s id once known, and pass the customer IP, device type, and user agent. * For **system or batch calls**, you may omit the header or send `{is_system_call: true, ...}` instead of customer\_id. ## Response Codes Requests to our APIs return standard HTTP status codes (described here) often accompanied by additional data. All are formatted as JSON. * 2xx codes indicate success and are often accompanied by response parameters generated by endpoint service. * 4xx codes indicate request failure due to missing or erroneous request information. * 5xx codes indicate an error in endpoint service. ## OpenAPI Specification You can download the Synctera OpenAPI schema decribing our API surface below. This schema can be used with the various openapi tools like [openapi generator.](https://github.com/OpenAPITools/openapi-generator) Using openapi generator, you can generate a client library to interact with Synctera. Below is an example to generate a java client library using openapi generator. ```java theme={"system"} java -jar openapi-generator-cli-6.0.0-20211025.061654-22.jar generate -i synctera_openapi.json -g java -o ./java_client ``` # Update address information by id Source: https://docs.synctera.com/v2/reference/updateaddress openapi-v2.json patch /addresses/{address_id} Update address # Update a monitoring alert Source: https://docs.synctera.com/v2/reference/updatealert openapi-v2.json patch /monitoring/alerts/{alert_id} # Update a personal identifier Source: https://docs.synctera.com/v2/reference/updatepersonalid openapi-v2.json patch /persons/personal_ids/{personal_id_id} Update a personal identifier, e.g. SSN, for this customer # Add an external account Source: https://docs.synctera.com/v2/reference/addexternalaccounts openapi-v2.json post /external_accounts Add an external account for a customer. The account will be created in an unverified state. # Add internal accounts Source: https://docs.synctera.com/v2/reference/addinternalaccounts openapi-v2.json post /internal_accounts Add an internal account. Note: In production, this action can only be performed by Synctera administrators. # Add external accounts through a vendor, such as Plaid. Source: https://docs.synctera.com/v2/reference/addvendorexternalaccounts openapi-v2.json post /external_accounts/add_vendor_accounts Add external accounts for a customer through an existing access token. The token must be valid, and the information on the accounts returned by the vendor must correspond to the customer. A success response for this route may include failures if an account could not be added, so it's important that the caller checks the response body. # Create a permanent access token for an external account Source: https://docs.synctera.com/v2/reference/createaccesstoken openapi-v2.json post /external_accounts/access_tokens # Create an account Source: https://docs.synctera.com/v2/reference/createaccount openapi-v2.json post /accounts Creates an account copying values from account template into the account resource. Any fields defined as part of account creation will overwrite the ones provided from the account template. Account holder `verification_status` must be `ACCEPTED` to create an account. Required fields: - relationships # Create account relationship Source: https://docs.synctera.com/v2/reference/createaccountrelationship openapi-v2.json post /accounts/{account_id}/relationships Add a customer to an account # Create an account product Source: https://docs.synctera.com/v2/reference/createaccountresourceproduct openapi-v2.json post /accounts/products Create an account product. Rates cannot be nil or empty. The FEE account product has been deprecated. Instead, use the /v1/fee_templates and /v1/fees endpoints. # Create an account template Source: https://docs.synctera.com/v2/reference/createaccounttemplate openapi-v2.json post /accounts/templates Create an account template. An account template is needed to create an account in a lead mode. # Create an adverse action notice Source: https://docs.synctera.com/v2/reference/createadverseaction openapi-v2.json post /adverse_actions An adverse action notice is required for Reg B and FCRA when an application to grant or increase credit is refused; a counteroffer is made; an credit account is terminated; the terms on the account has an unfavorable change. # Create an Apple Pay CSR Source: https://docs.synctera.com/v2/reference/createapplepaycsr openapi-v2.json post /certificates/applepay/csr Generates and returns a Certificate Signing Request (CSR) that can be used to create an Apple Pay Payment Processing Certificate in the Apple Developer Portal. # Create an application Source: https://docs.synctera.com/v2/reference/createapplication-1 openapi-v2.json post /applications > 🚧 Beta > This is an Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Submit a record of application details for an account. # Create autopay configuration Source: https://docs.synctera.com/v2/reference/createautopayconfig openapi-v2.json post /autopay_configs > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Create an autopay configuration for a lending account. Only one active autopay configuration can exist per lending account. # Create a bulk order configuration Source: https://docs.synctera.com/v2/reference/createbulkorderconfig openapi-v2.json post /cards/bulk_issuance Bulk card orders can be configured to ship cards in bulk. In order to create a bulk order the associated card product needs to be configured for bulk issuance (Refer to Card Product `bulk_shipping_enabled`). Once a Card Product is configured a bulk order can be created. Cards are dynamically added to the bulk order using the `bulk_order_config_id` (Refer to Issue Card `bulk_order_config_id`) and will be shipped based on the `bulk_issuance_policy`. Bulk orders configured with `AUTO` will be fulfilled daily at 9:30PM PST, all cards that have been added to the bulk order prior to the cutoff will be shipped in the next bulk order, any subsequent cards will be added to the next days order. Bulk orders configured with `MANUAL` will be shipped when an integrator sends a fulfillment request (Refer to Bulk Issuance Fulfill). # Create a business Source: https://docs.synctera.com/v2/reference/createbusiness openapi-v2.json post /businesses Create a business who may act as a customer or a related business. You can then verify the identity of this customer and associate them with other people and accounts. # Create a credit score and associate it with a customer Source: https://docs.synctera.com/v2/reference/createcreditscores openapi-v2.json post /credit_scores Credit score under customers that can link to accounts and applications # Create a risk evaluation override Source: https://docs.synctera.com/v2/reference/createevaluationoverride openapi-v2.json post /evaluation_overrides Create a new risk evaluation override. # Create an external score Source: https://docs.synctera.com/v2/reference/createexternalscore openapi-v2.json post /crr/external_scores Assign an externally sourced risk score to a customer or business # Create a relationship Source: https://docs.synctera.com/v2/reference/createrelationship openapi-v2.json post /relationships Create a party relationship. # Create Spend Control Source: https://docs.synctera.com/v2/reference/createspendcontrol openapi-v1.json post /spend_controls Create a spend control # Create a verification Source: https://docs.synctera.com/v2/reference/createverification openapi-v2.json post /verifications Upload evidence of an externally performed KYC/KYB. You may use your own KYC/KYB provider and upload evidence of those results instead of using one of Synctera's providers. Verifying a personal customer requires that the following fields already be set: * `first_name` * `last_name` * `dob` * `email` or `phone_number` * `legal_address` * `shippings_address` * `ssn` or at least one other identifier in `personal_ids` Verifying a business customer requires that the following fields already be set: * `entity_name` * `legal_address` * `email` or `phone_number` * `ein` not required for sole proprietorships Please refer to https://learn.synctera.com/docs/using-your-own-kyc-vendor for more details using external KYC/KYB. # Create a link token to verify an external account Source: https://docs.synctera.com/v2/reference/createverificationlinktoken openapi-v2.json post /external_accounts/link_tokens # Delete account relationship Source: https://docs.synctera.com/v2/reference/deleteaccountrelationship openapi-v2.json delete /accounts/{account_id}/relationships/{relationship_id} Delete account relationship # Delete account template Source: https://docs.synctera.com/v2/reference/deleteaccounttemplate openapi-v2.json delete /accounts/templates/{template_id} Delete account template # Delete autopay configuration Source: https://docs.synctera.com/v2/reference/deleteautopayconfig openapi-v2.json delete /autopay_configs/{autopay_config_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Delete an autopay configuration by ID. # Delete a risk evaluation override Source: https://docs.synctera.com/v2/reference/deleteevaluationoverride openapi-v2.json delete /evaluation_overrides/{evaluation_override_id} Delete evaluation override by ID. # Delete an external account Source: https://docs.synctera.com/v2/reference/deleteexternalaccount openapi-v2.json delete /external_accounts/{external_account_id} Deletes an external account, given an external account ID. If no accounts left, the access token to the financial institution will be removed # Delete an external score Source: https://docs.synctera.com/v2/reference/deleteexternalscore openapi-v2.json delete /crr/external_scores/{external_score_id} Delete a specific external score # Delete relationship Source: https://docs.synctera.com/v2/reference/deleterelationship openapi-v2.json delete /relationships/{relationship_id} Delete party relationship by ID. # Initiate Document Verification Session Source: https://docs.synctera.com/v2/reference/docvsession openapi-v2.json post /verifications/docv_session Initiate document verification session to be used with `/verifications/verify`. # Sync external account transactions through a vendor, such as Plaid Source: https://docs.synctera.com/v2/reference/externalaccountrefreshtransactions openapi-v2.json post /external_accounts/{external_account_id}/refresh_transactions Sync external accounts for a customer through an existing access token. The token must be valid. Accounts linked in the same auth session (having the same access token) will be synced together. # Get account Source: https://docs.synctera.com/v2/reference/getaccount openapi-v2.json get /accounts/{account_id} Get an account by account_id. Note: GENERAL_LEDGER accounts are in Alpha status, and cannot yet be created. We may make breaking changes. # Get account relationship Source: https://docs.synctera.com/v2/reference/getaccountrelationship openapi-v2.json get /accounts/{account_id}/relationships/{relationship_id} Get account relationship by ID # Get account template Source: https://docs.synctera.com/v2/reference/getaccounttemplate openapi-v2.json get /accounts/templates/{template_id} Get an account template # Retrieve an adverse action notice Source: https://docs.synctera.com/v2/reference/getadverseaction openapi-v2.json get /adverse_actions/{adverse_action_id} # Get an application Source: https://docs.synctera.com/v2/reference/getapplication-1 openapi-v2.json get /applications/{application_id} > 🚧 Beta > This is an Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get an application's details. # Authorization Test Source: https://docs.synctera.com/v2/reference/getauthorizationtest openapi-v2.json get /fdx_auth_requests/authorization_test Use this endpoint to initiate a test of the Plaid Core Exchange authorization flow. Your configured Authentication URI will be returned in the response body which you can navigate to in browser, then perform your authentication process using the appended auth_request_id. If that authentication is successful, this flow should end by redirecting to our success page from the authorize response. This endpoint is only supported in the sandbox environment. # Get autopay Source: https://docs.synctera.com/v2/reference/getautopay openapi-v2.json get /autopays/{autopay_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get an autopay by ID. The response includes the estimated amount that will be paid based on the config snapshot and current balances. # Get autopay configuration Source: https://docs.synctera.com/v2/reference/getautopayconfig openapi-v2.json get /autopay_configs/{autopay_config_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get an autopay configuration by ID. # Get bulk order configuration Source: https://docs.synctera.com/v2/reference/getbulkorderconfig openapi-v2.json get /cards/bulk_issuance/{bulk_order_config_id} Get the details about a bulk order configuration. # Get business Source: https://docs.synctera.com/v2/reference/getbusiness openapi-v2.json get /businesses/{business_id} Get business by ID. # Retrieve a credit score Source: https://docs.synctera.com/v2/reference/getcreditscore openapi-v2.json get /credit_scores/{credit_score_id} # Get a risk evaluation override Source: https://docs.synctera.com/v2/reference/getevaluationoverride openapi-v2.json get /evaluation_overrides/{evaluation_override_id} Get a risk evaluation override by ID. # Get an external account Source: https://docs.synctera.com/v2/reference/getexternalaccount openapi-v2.json get /external_accounts/{external_account_id} Returns an external account, given an external account ID. # Get external account balances Source: https://docs.synctera.com/v2/reference/getexternalaccountbalance openapi-v2.json get /external_accounts/{external_account_id}/balance Given an external account ID, return the account balances in real time. The data returned by this endpoint is always fetched synchronously; it is not cached by Synctera. As a result, response latency is often high. # List transactions of a given external account Source: https://docs.synctera.com/v2/reference/getexternalaccounttransactions openapi-v2.json get /external_accounts/{external_account_id}/transactions Returns a list of transactions on from the external account, given an external account ID. Maximum 500 transctions will be returned. # Get an external score Source: https://docs.synctera.com/v2/reference/getexternalscore openapi-v2.json get /crr/external_scores/{external_score_id} Get a specific external score # Get an FDX token Source: https://docs.synctera.com/v2/reference/getfdxtoken openapi-v2.json get /fdx_tokens/{fdx_token_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get an FDX token # Get internal account by id Source: https://docs.synctera.com/v2/reference/getinternalaccounts openapi-v2.json get /internal_accounts/{internal_account_id} Returns an internal account by id # Get relationship Source: https://docs.synctera.com/v2/reference/getrelationship openapi-v2.json get /relationships/{relationship_id} Get relationship by ID. # Get Spend Control Source: https://docs.synctera.com/v2/reference/getspendcontrol openapi-v1.json get /spend_controls/{spend_control_id} Get spend control # Get a statement Source: https://docs.synctera.com/v2/reference/getstatement openapi-v2.json get /statements/{statement_id} Gets a full statement by its ID. # Get a statement's transactions Source: https://docs.synctera.com/v2/reference/getstatementtransactions openapi-v2.json get /statements/{statement_id}/transactions Gets the list of transactions for a statement's period. # Get verification Source: https://docs.synctera.com/v2/reference/getverification1 openapi-v2.json get /verifications/{verification_id} Get customer verification result. # Grant an FDX authorization request Source: https://docs.synctera.com/v2/reference/grantfdxauthrequest openapi-v2.json post /fdx_auth_requests/authorize > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Grant or deny an FDX authorization request # Initiate account closure Source: https://docs.synctera.com/v2/reference/initiateaccountclosure openapi-v2.json post /accounts/{account_id}/initiate_closure Initiates an account closure. It immediately changes the account status to `IN_CLOSING`. Once the account status is `IN_CLOSING`, the account can no longer be used to create new transactions. # List account relationships Source: https://docs.synctera.com/v2/reference/listaccountrelationship openapi-v2.json get /accounts/{account_id}/relationships List all customers of an account # List account products Source: https://docs.synctera.com/v2/reference/listaccountresourceproducts openapi-v2.json get /accounts/products List account products The FEE account product has been deprecated. Instead, use the /v1/fee_templates and /v1/fees endpoints. # List accounts Source: https://docs.synctera.com/v2/reference/listaccounts openapi-v2.json get /accounts Get a paginated list of accounts. GENERAL_LEDGER accounts are not included by default. To include them, set include_general_ledger=true, or filter by account_type=GENERAL_LEDGER, general_ledger_type or general_ledger_category. Note: GENERAL_LEDGER accounts are in Alpha status, and cannot yet be created. We may make breaking changes. # List account templates Source: https://docs.synctera.com/v2/reference/listaccounttemplates openapi-v2.json get /accounts/templates List account templates # List adverse action notices Source: https://docs.synctera.com/v2/reference/listadverseactions openapi-v2.json get /adverse_actions # List applications Source: https://docs.synctera.com/v2/reference/listapplications-1 openapi-v2.json get /applications > 🚧 Beta > This is an Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. List records of applications made for accounts. # List autopay configurations Source: https://docs.synctera.com/v2/reference/listautopayconfigs openapi-v2.json get /autopay_configs > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. List autopay configurations with optional filters. # List autopays Source: https://docs.synctera.com/v2/reference/listautopays openapi-v2.json get /autopays > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. List autopay records with optional filters. Autopays are created automatically when a statement is generated for an account with an active autopay configuration. # List Bulk Order Configurations Source: https://docs.synctera.com/v2/reference/listbulkorderconfigs openapi-v2.json get /cards/bulk_issuance List bulk order configurations matching query parameters # List business Source: https://docs.synctera.com/v2/reference/listbusinesses openapi-v2.json get /businesses Retrieves paginated list of businesses associated with the authorized requester. # List credit scores Source: https://docs.synctera.com/v2/reference/listcreditscores openapi-v2.json get /credit_scores # List CRRs Source: https://docs.synctera.com/v2/reference/listcrr openapi-v2.json get /crr Get paginated list of CRR # List risk evaluation overrides Source: https://docs.synctera.com/v2/reference/listevaluationoverrides openapi-v2.json get /evaluation_overrides List evaluation overrides. # List external accounts Source: https://docs.synctera.com/v2/reference/listexternalaccounts openapi-v2.json get /external_accounts Returns a list of all external accounts assigned to customers. # List external scores Source: https://docs.synctera.com/v2/reference/listexternalscores openapi-v2.json get /crr/external_scores Get paginated list of externally sourced risk scores # List FDX authorization requests Source: https://docs.synctera.com/v2/reference/listfdxauthrequests openapi-v2.json get /fdx_auth_requests > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get paginated list of FDX authorization requests # List tokens Source: https://docs.synctera.com/v2/reference/listfdxtoken openapi-v2.json get /fdx_tokens > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get paginated list of FDX tokens # List internal accounts Source: https://docs.synctera.com/v2/reference/listinternalaccounts openapi-v2.json get /internal_accounts Returns a list of all internal accounts. # List relationships Source: https://docs.synctera.com/v2/reference/listrelationships openapi-v2.json get /relationships Retrieves paginated list of relationships viewable by the authorized requester. # List Spend Controls Source: https://docs.synctera.com/v2/reference/listspendcontrols openapi-v1.json get /spend_controls List spend controls # List statements Source: https://docs.synctera.com/v2/reference/liststatements openapi-v2.json get /statements Gets a list of statement summaries for an account. # Liststoppayment Source: https://docs.synctera.com/v2/reference/liststoppayment openapi-v2.json get /accounts/stop_payments # List verifications Source: https://docs.synctera.com/v2/reference/listverifications1 openapi-v2.json get /verifications List customer verification results. # Patch account Source: https://docs.synctera.com/v2/reference/patchaccount openapi-v2.json patch /accounts/{account_id} Patch account. Immutable fields: - account_number - account_type - account_template_id - customer_type Please note: - Other fields cannot be modified when access_status is FROZEN. - access_status has to be patched individually without other fields. # Patch account product Source: https://docs.synctera.com/v2/reference/patchaccountproduct openapi-v2.json patch /accounts/products/{product_id} Patch account product. Rates requires at minimum 1 entry if specified. The FEE account product has been deprecated. Instead, use the /v1/fee_templates and /v1/fees endpoints. # Patch account template Source: https://docs.synctera.com/v2/reference/patchaccounttemplate openapi-v2.json patch /accounts/templates/{template_id} Patch account template # Modify an application Source: https://docs.synctera.com/v2/reference/patchapplication-1 openapi-v2.json patch /applications/{application_id} > 🚧 Beta > This is an Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Modify an existing application for an account. # Update autopay Source: https://docs.synctera.com/v2/reference/patchautopay openapi-v2.json patch /autopays/{autopay_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Update an autopay. Currently only supports cancelling a pending autopay by setting the status to SKIPPED. # Patch internal account Source: https://docs.synctera.com/v2/reference/patchinternalaccount openapi-v2.json patch /internal_accounts/{internal_account_id} Patch internal account. Note: In production, this action can only be performed by Synctera administrators. # Reveal Personal ID Source: https://docs.synctera.com/v2/reference/personalidreveal openapi-v2.json get /persons/personal_ids/{personal_id_id}/reveal Get a personal ID with the id number encrypted using the fintechs provided public key. Optionally specify which personal ID configuration to use for encryption. If not specified, the oldest configured public key will be used. # Sync external accounts through a vendor, such as Plaid. Source: https://docs.synctera.com/v2/reference/syncvendorexternalaccounts openapi-v2.json post /external_accounts/sync_vendor_accounts Sync external accounts for a customer through an existing access token. The token must be valid, and the information on the accounts returned by the vendor must correspond to the customer. A success response for this route may include failures if an account could not be added and deletions if the account is removed by the end user, so it's important that the caller checks the response body. # Update account Source: https://docs.synctera.com/v2/reference/updateaccount openapi-v2.json put /accounts/{account_id} > Deprecated. Please use PATCH /v0/accounts. This route only supports types CHECKING and SAVING. Update account Shadow mode required fields: - account_number - status Lead mode required fields: - All fields are required. Please note: - access_status needs to be in ACTIVE. - PUT request cannot change access_status. # Update account closure Source: https://docs.synctera.com/v2/reference/updateaccountclosure openapi-v2.json patch /accounts/{account_id}/initiate_closure Update an account closure. # Update account relationship Source: https://docs.synctera.com/v2/reference/updateaccountrelationship openapi-v2.json put /accounts/{account_id}/relationships/{relationship_id} Update account relationship. Only relationship_type can be updated. customer_id should not be modified. # Update account template Source: https://docs.synctera.com/v2/reference/updateaccounttemplate openapi-v2.json put /accounts/templates/{template_id} Update account template # Update autopay configuration Source: https://docs.synctera.com/v2/reference/updateautopayconfig openapi-v2.json patch /autopay_configs/{autopay_config_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Update an autopay configuration. You can update the payment source, status, or config. # Patch business Source: https://docs.synctera.com/v2/reference/updatebusiness openapi-v2.json patch /businesses/{business_id} Update business by ID. # Update a risk evaluation override Source: https://docs.synctera.com/v2/reference/updateevaluationoverride openapi-v2.json patch /evaluation_overrides/{evaluation_override_id} Update evaluation override by ID. # Patch an external account Source: https://docs.synctera.com/v2/reference/updateexternalaccount openapi-v2.json patch /external_accounts/{external_account_id} Edits an unverified external account, given an external account ID. # Update an external score Source: https://docs.synctera.com/v2/reference/updateexternalscore openapi-v2.json patch /crr/external_scores/{external_score_id} Update a specific external score # Update person Source: https://docs.synctera.com/v2/reference/updateperson openapi-v2.json patch /persons/{person_id} Update person by ID. Note that if: * legal address is provided in the request, AND * shipping_address is not provided in the request, AND * the customer resource does not have shipping_address then shipping_address will be set to a copy of the legal_address. # Update relationship Source: https://docs.synctera.com/v2/reference/updaterelationship openapi-v2.json patch /relationships/{relationship_id} Update relationship by ID. # Update Spend Control Source: https://docs.synctera.com/v2/reference/updatespendcontrol openapi-v1.json patch /spend_controls/{spend_control_id} Update spend control # Verify a customer's identity Source: https://docs.synctera.com/v2/reference/verify openapi-v2.json post /verifications/verify Initiate identity verification and run the specified identity checks. Verifying a personal customer requires that the following fields already be set: * `first_name` * `last_name` * `dob` * `email` * `phone_number` * `legal_address` * `ssn` Verifying a business customer requires that the following fields already be set: * `entity_name` * `legal_address` # Check if an individual is on any watchlists Source: https://docs.synctera.com/v2/reference/verifyadhoc openapi-v2.json post /verifications/adhoc # Activate a card Source: https://docs.synctera.com/v2/reference/activatecard openapi-v2.json post /cards/activate Activate a card # Authenticate 3DS Source: https://docs.synctera.com/v2/reference/authenticate3ds openapi-v2.json post /external_cards/authenticate_3ds Validates the results of an External Card Transfer 3DS authentication challenge. # Create Apple Pay External Card Transfer Source: https://docs.synctera.com/v2/reference/createapplepayexternalcardtransfer openapi-v2.json post /external_cards/transfers/applepay > 🚧 Alpha > Apple Pay transfers is currently in Alpha release and spec is subject to change. Create External Card Transfer using an Apple Pay card # Create a barcode for a cash transaction Source: https://docs.synctera.com/v2/reference/createbarcode openapi-v2.json POST /cash/barcodes Create a barcode for a cash transaction # Create Batch Payments Source: https://docs.synctera.com/v2/reference/createbatchpayments openapi-v2.json post /batches Create multiple batch payments # Create Batch Payment Template Source: https://docs.synctera.com/v2/reference/createbatchpaymenttemplate openapi-v2.json post /batch_templates Create a Batch Payment template # Create Card Image Source: https://docs.synctera.com/v2/reference/createcardimage openapi-v2.json post /cards/images Create a card image entity. Note that this does not include the image data itself. You can upload the image data via a subsequent uploadCardImageData request using the ID created here. # Cash Authorization for an upcoming transfer Source: https://docs.synctera.com/v2/reference/createcashauthorization openapi-v2.json post /cash/authorization Create a new cash authorization > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Create digital wallet token provision request for Apple Pay Source: https://docs.synctera.com/v2/reference/createdigitalwalletapple openapi-v2.json post /cards/{card_id}/digital_wallet_tokens/applepay # Create digital wallet token provision request for Google Pay Source: https://docs.synctera.com/v2/reference/createdigitalwalletgoogle openapi-v2.json post /cards/{card_id}/digital_wallet_tokens/googlepay # Create External Card from token Source: https://docs.synctera.com/v2/reference/createexternalcardfromtoken openapi-v2.json post /external_cards/tokens Create an External Card from token. The token and cardholder name are obtained through the iFrame. The token must be used within 5 minutes or else it will expire. If a Business ID is provided, address verification will be performed against the legal address of the business. Otherwise, the legal address of the Customer will be used. In either case, the name of the Customer will be used to match against the cardholder name. Each unique External Card is limited to a single Customer, so once an External Card is created for a Customer, it cannot be used for any other Customers, even if the card is deleted. Given there is a limited number of test cards, to allow easier testing, this restriction is relaxed in the sandbox environment. # Create External Card Transfer Source: https://docs.synctera.com/v2/reference/createexternalcardtransfer openapi-v2.json post /external_cards/transfers Create External Card Transfer # Create External Card Transfer Reversal Source: https://docs.synctera.com/v2/reference/createexternalcardtransferreversal openapi-v2.json post /external_cards/transfers/{transfer_id}/reversals Create External Card Transfer Reversal # Create a fee Source: https://docs.synctera.com/v2/reference/createfee openapi-v2.json post /fees Create a fee # Create a fee config Source: https://docs.synctera.com/v2/reference/createfeeconfig openapi-v2.json post /fee_configs Create a new standalone fee config. Use PUT /fee_products/{fee_product_id}/fee_configs to set the full list of fee configs on a fee product. # Create a fee product Source: https://docs.synctera.com/v2/reference/createfeeproduct openapi-v2.json post /fee_products Create a new fee product bundle # Create a fee template Source: https://docs.synctera.com/v2/reference/createfeetemplate openapi-v2.json post /fee_templates Create a fee template A fee template defines the properties of a fee that a fintech wishes to use to easily charge their customers. The fintech can then create fee templates for different amounts or categories of fees that represent different instances of services or charges # Create Gateway Source: https://docs.synctera.com/v2/reference/creategateway openapi-v2.json post /cards/gateways Create a new Authorization Gateway Configuration # Create Google Pay External Card Transfer Source: https://docs.synctera.com/v2/reference/creategooglepayexternalcardtransfer openapi-v2.json post /external_cards/transfers/googlepay > 🚧 Alpha > Google Pay transfers is currently in Alpha release and spec is subject to change. Create External Card Transfer using a Google Pay card. # Create a reward Source: https://docs.synctera.com/v2/reference/createreward openapi-v2.json post /rewards Create a reward # Create a reward config Source: https://docs.synctera.com/v2/reference/createrewardconfig openapi-v2.json post /reward_configs Create a new standalone reward config. Use PATCH /reward_products/{reward_product_id} to associate it with a reward product. # Create a reward product Source: https://docs.synctera.com/v2/reference/createrewardproduct openapi-v2.json post /reward_products Create a new reward product bundle # Create a reward template Source: https://docs.synctera.com/v2/reference/createrewardtemplate openapi-v2.json post /reward_templates Create a reward template A reward template defines the properties of a reward that a fintech wishes to use to easily charge their customers. The fintech can then create reward templates for different amounts or categories of rewards that represent different instances of services or charges # Create 3DS Decision Gateway Source: https://docs.synctera.com/v2/reference/createthreedsdecisiongateway openapi-v2.json post /cards/three_ds_decision_gateways Create a new 3DS Decision Gateway # Delete External Card Source: https://docs.synctera.com/v2/reference/deleteexternalcard openapi-v2.json delete /external_cards/{external_card_id} Delete an External Card # Fulfill a bulk order Source: https://docs.synctera.com/v2/reference/fulfillbulkorder openapi-v2.json post /cards/bulk_issuance/{bulk_order_config_id}/fulfill Bulk orders configured with a `MANUAL` bulk issuance policy will be shipped when a fulfillment request is made (Refer to Bulk Orders `bulk_issuance_policy`). All cards that have been created with the corresponding `bulk_order_config_id` since the previous fulfillment, will be included in the bulk order. # Get a list of barcodes Source: https://docs.synctera.com/v2/reference/getbarcodes openapi-v2.json GET /cash/barcodes Get a list of barcodes # Get BatchPayment Source: https://docs.synctera.com/v2/reference/getbatchpayment openapi-v2.json get /batches/{id} Get a Batch Payment # Get Batch Payments Source: https://docs.synctera.com/v2/reference/getbatchpayments openapi-v2.json get /batches Get all Batch Payments # Get Batch Payment Template Source: https://docs.synctera.com/v2/reference/getbatchpaymenttemplate openapi-v2.json get /batch_templates/{id} Get a Batch Payment template # Get Batch Payment Templates Source: https://docs.synctera.com/v2/reference/getbatchpaymenttemplates openapi-v2.json get /batch_templates Get all Batch Payment templates # Get Card Source: https://docs.synctera.com/v2/reference/getcard openapi-v2.json get /cards/{card_id} Get the details about a card that has been issued # Get Card Barcode Source: https://docs.synctera.com/v2/reference/getcardbarcode openapi-v2.json get /cards/{card_id}/barcodes This endpoint is for testing environment only to provide access to barcode of a test card # Get Card Image Data Source: https://docs.synctera.com/v2/reference/getcardimagedata openapi-v2.json get /cards/images/{card_image_id}/data Get card image data # Get Card Image Details Source: https://docs.synctera.com/v2/reference/getcardimagedetails openapi-v2.json get /cards/images/{card_image_id} Get card image details # Get card widget URL Source: https://docs.synctera.com/v2/reference/getcardwidgeturl openapi-v2.json get /cards/card_widget_url This endpoint returns a URL address of the specified widget for a given card # Get cash authorizations Source: https://docs.synctera.com/v2/reference/getcashauthorizations openapi-v2.json get /cash/authorization Get all cash authorizations > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Get cash order authorization Source: https://docs.synctera.com/v2/reference/getcashorderauthorization openapi-v2.json get /cash/authorization/{id} Get a specific cash order authorization > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Get cash transfer Source: https://docs.synctera.com/v2/reference/getcashtransfer openapi-v2.json get /cash/{id} Get a specific cash transfer > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Get cash transfers Source: https://docs.synctera.com/v2/reference/getcashtransfers openapi-v2.json get /cash Get all cash transfers > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Get a client token Source: https://docs.synctera.com/v2/reference/getclientaccesstoken openapi-v2.json post /cards/{card_id}/client_token Create a client access token for interacting with a card. This token will be used on the client to identify the card for flows like viewing Full PAN or setting the PIN in a PCI compliant manner. # Get Digital Wallet Token Source: https://docs.synctera.com/v2/reference/getdigitalwallettoken openapi-v2.json get /cards/digital_wallet_tokens/{digital_wallet_token_id} Get the details about the digital wallet token of a card NB: Digital wallet tokens cannot be created outside of production. # Get External Card Source: https://docs.synctera.com/v2/reference/getexternalcard openapi-v2.json get /external_cards/{external_card_id} Get External Card # Get External Card Transfer Source: https://docs.synctera.com/v2/reference/getexternalcardtransfer openapi-v2.json get /external_cards/transfers/{transfer_id} Get External Card Transfer # Get Fee Source: https://docs.synctera.com/v2/reference/getfee openapi-v2.json get /fees/{fee_id} Get a fee by ID. # Get a fee config Source: https://docs.synctera.com/v2/reference/getfeeconfig openapi-v2.json get /fee_configs/{fee_config_id} Get a single fee config by ID # Get a fee product Source: https://docs.synctera.com/v2/reference/getfeeproduct openapi-v2.json get /fee_products/{fee_product_id} Get a single fee product by ID # Get a Fee template Source: https://docs.synctera.com/v2/reference/getfeetemplate openapi-v2.json get /fee_templates/{fee_template_id} Get a fee template by ID. # Get Gateway Source: https://docs.synctera.com/v2/reference/getgateway openapi-v2.json get /cards/gateways/{gateway_id} Get the details of an Authorization Gateway that has been configured # Get payment Source: https://docs.synctera.com/v2/reference/getpayment openapi-v2.json get /payments/{payment_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Get a payment by ID. # Get Reward Source: https://docs.synctera.com/v2/reference/getreward openapi-v2.json get /rewards/{reward_id} Get a reward by ID. # Get a reward config Source: https://docs.synctera.com/v2/reference/getrewardconfig openapi-v2.json get /reward_configs/{reward_config_id} Get a single reward config by ID # Get a reward product Source: https://docs.synctera.com/v2/reference/getrewardproduct openapi-v2.json get /reward_products/{reward_product_id} Get a single reward product by ID # Get a Reward template Source: https://docs.synctera.com/v2/reference/getrewardtemplate openapi-v2.json get /reward_templates/{reward_template_id} Get a reward template by ID. # Get 3DS DecisionGateway Source: https://docs.synctera.com/v2/reference/getthreedsdecisiongateway openapi-v2.json get /cards/three_ds_decision_gateways/{id} Get the details of a 3DS Decision Gateway # Get a widget access token Source: https://docs.synctera.com/v2/reference/getwidgetaccesstoken openapi-v2.json get /cards/{card_id}/widget_token Create an ephemeral (short-term, limited-scope) access token for interacting with a card via Synctera widgets. # Initialize 3DS Source: https://docs.synctera.com/v2/reference/initialize3ds openapi-v2.json post /external_cards/initialize_3ds Initializes an External Card Transfer 3DS authentication. # Issue a Card Source: https://docs.synctera.com/v2/reference/issuecard openapi-v2.json post /cards Issue or reissue a new card for a customer # List Card Image Details Source: https://docs.synctera.com/v2/reference/listcardimagedetails openapi-v2.json get /cards/images List all card image details # List Card Products Source: https://docs.synctera.com/v2/reference/listcardproducts openapi-v2.json get /cards/products List of available Card Products # List Cards Source: https://docs.synctera.com/v2/reference/listcards openapi-v2.json get /cards List of cards matching query parameters # List Digital Wallet Tokens Source: https://docs.synctera.com/v2/reference/listdigitalwallettokens openapi-v2.json get /cards/digital_wallet_tokens List Digital Wallet Tokens # List External Cards Source: https://docs.synctera.com/v2/reference/listexternalcards openapi-v2.json get /external_cards List External Cards # List External Transfers Source: https://docs.synctera.com/v2/reference/listexternalcardtransfers openapi-v2.json get /external_cards/transfers List External Card Transfers # List fee categories Source: https://docs.synctera.com/v2/reference/listfeecategories openapi-v2.json get /fee_categories Returns descriptions of all supported fee categories. Use this endpoint to discover available categories when configuring fee configs. # List fee configs Source: https://docs.synctera.com/v2/reference/listfeeconfigs openapi-v2.json get /fee_configs Get a paginated list of all fee configs # List fee products Source: https://docs.synctera.com/v2/reference/listfeeproducts openapi-v2.json get /fee_products Get a paginated list of fee products # List fees Source: https://docs.synctera.com/v2/reference/listfees openapi-v2.json get /fees Get paginated list of fees # List fee templates Source: https://docs.synctera.com/v2/reference/listfeetemplates openapi-v2.json get /fee_templates Get paginated list of fee templates # List Gateways Source: https://docs.synctera.com/v2/reference/listgateways openapi-v2.json get /cards/gateways List of gateways matching query parameters # List payments Source: https://docs.synctera.com/v2/reference/listmadepayments openapi-v2.json get /payments > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. List payments against lending accounts, spanning both automated (autopay) and one-time/manual payments. # List reward configs Source: https://docs.synctera.com/v2/reference/listrewardconfigs openapi-v2.json get /reward_configs Get a paginated list of all reward configs # List reward products Source: https://docs.synctera.com/v2/reference/listrewardproducts openapi-v2.json get /reward_products Get a paginated list of reward products # List rewards Source: https://docs.synctera.com/v2/reference/listrewards openapi-v2.json get /rewards Get paginated list of rewards # List reward templates Source: https://docs.synctera.com/v2/reference/listrewardtemplates openapi-v2.json get /reward_templates Get paginated list of reward templates # List 3DS Decision Gateways Source: https://docs.synctera.com/v2/reference/listthreedsdecisiongateways openapi-v2.json get /cards/three_ds_decision_gateways List of 3DS decision gateway matching query parameters # Lookup 3DS Source: https://docs.synctera.com/v2/reference/lookup3ds openapi-v2.json post /external_cards/lookup_3ds Using device collection data, performs a lookup for an External Card Transfer 3DS authentication. The results will indicate whether the transfer is successfully authenticated or if a 3DS challenge is required. # Make a payment Source: https://docs.synctera.com/v2/reference/makepayment openapi-v2.json post /payments > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Make a one-time payment against a lending account (e.g. a card paydown), funded either from an internal Synctera platform account or an external ACH-linked account. If effective_date is today or omitted, the payment executes immediately and the response reflects its final status (EXECUTED, FAILED, or SKIPPED). If effective_date is in the future, the payment is scheduled and executes on that date. # Update a cash order authorization Source: https://docs.synctera.com/v2/reference/patchcashorderauthorization openapi-v2.json patch /cash/authorization/{id} > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Update a cash transfer Source: https://docs.synctera.com/v2/reference/patchcashtransfer openapi-v2.json patch /cash/{id} To cancel a transfer, update the status to 'CANCELLED'. Only 'INITIATED' or 'PENDING` transfers can be cancelled. > 🚧 Alpha > This is an Alpha spec-only endpoint. Feedback from the community is welcome. We may make breaking changes. # Patch Fee Template Source: https://docs.synctera.com/v2/reference/patchfeetemplate openapi-v2.json patch /fee_templates/{fee_template_id} Update a fee template by ID. # Update payment Source: https://docs.synctera.com/v2/reference/patchpayment openapi-v2.json patch /payments/{payment_id} > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Update a payment. Currently only supports cancelling a pending payment (one not yet executed, e.g. scheduled for a future effective_date) by setting the status to SKIPPED. # Patch Reward Template Source: https://docs.synctera.com/v2/reference/patchrewardtemplate openapi-v2.json patch /reward_templates/{reward_template_id} Update a reward template by ID. # Reveal Card Details Source: https://docs.synctera.com/v2/reference/revealcarddetails openapi-v2.json get /cards/{card_id}/reveal > 🚧 PCI Compliance > This endpoint requires PCI compliance. If you are PCI compliant and want this endpoint enabled, please work with your Synctera representative. Reveal card details # Reverse a fee Source: https://docs.synctera.com/v2/reference/reversefee openapi-v2.json post /fees/{fee_id}/reverse Reverse the fee by creating a reversal transaction. # Reverse a reward Source: https://docs.synctera.com/v2/reference/reversereward openapi-v2.json post /rewards/{reward_id}/reverse Reverse the reward by creating a reversal transaction. # Set Card PIN Source: https://docs.synctera.com/v2/reference/setcardpin openapi-v2.json post /cards/{card_id}/pin > 🚧 PCI Compliance > This endpoint requires PCI compliance. If you are PCI compliant and want this endpoint enabled, please work with your Synctera representative. Set a new PIN for a card # Update Batch Payment Source: https://docs.synctera.com/v2/reference/updatebatchpayment openapi-v2.json patch /batches/{id} Update a Batch Payment # Update Batch Payment Template Source: https://docs.synctera.com/v2/reference/updatebatchpaymenttemplate openapi-v2.json patch /batch_templates/{id} Update a Batch Payment template # Update Card Source: https://docs.synctera.com/v2/reference/updatecard openapi-v2.json patch /cards/{card_id} Integrators can update the card resource to change status, update shipping (if the card hasn't been shipped) or edit metadata. # Update Card Image Details Source: https://docs.synctera.com/v2/reference/updatecardimagedetails openapi-v2.json patch /cards/images/{card_image_id} Update card image details. The only detail that can be updated is the card status as APPROVED or REJECTED. # Update Digital Wallet Token's life cycle status Source: https://docs.synctera.com/v2/reference/updatedigitalwallettokenstatus openapi-v2.json patch /cards/digital_wallet_tokens/{digital_wallet_token_id} The status of a digital wallet token can be updated as, ACTIVE to SUSPENDED, SUSPENDED to ACTIVE, ACTIVE to TERMINATED or SUSPENDED to TERMINATED. NB: Digital wallet tokens cannot be created outside of production. # Update External Card Source: https://docs.synctera.com/v2/reference/updateexternalcard openapi-v2.json patch /external_cards/{external_card_id} Update External Card data # Update a fee config Source: https://docs.synctera.com/v2/reference/updatefeeconfig openapi-v2.json patch /fee_configs/{fee_config_id} Update a fee config's properties # Update a fee product Source: https://docs.synctera.com/v2/reference/updatefeeproduct openapi-v2.json patch /fee_products/{fee_product_id} Update the name of a fee product, description, or status # Update Gateway Source: https://docs.synctera.com/v2/reference/updategateway openapi-v2.json patch /cards/gateways/{gateway_id} Update Authorization Gateway configuration # Update a reward config Source: https://docs.synctera.com/v2/reference/updaterewardconfig openapi-v2.json patch /reward_configs/{reward_config_id} Update a reward config's properties # Update a reward product Source: https://docs.synctera.com/v2/reference/updaterewardproduct openapi-v2.json patch /reward_products/{reward_product_id} Update the name, description, status, or reward_config_ids of a reward product # Update 3DS Decision Gateway Source: https://docs.synctera.com/v2/reference/updatethreedsgateway openapi-v2.json patch /cards/three_ds_decision_gateways/{id} Update 3DS Decision Gateway # Upload Card Image Source: https://docs.synctera.com/v2/reference/uploadcardimagedata openapi-v2.json post /cards/images/{card_image_id}/data Upload card image data # Simulate receiving ACH return Source: https://docs.synctera.com/v2/reference/achreturnsimulation openapi-v2.json post /ach/transaction_simulations/receiving_return Use to simulate receiving ACH return in test environments. Creates an incoming ACH file with a single return entry based on a previously created outgoing transaction. The file gets automatically processed. # Simulate receiving ACH transaction Source: https://docs.synctera.com/v2/reference/achtransactionsimulation openapi-v2.json post /ach/transaction_simulations/receiving_transaction Use to simulate receiving ACH transaction in test environments. Creates an incoming ACH file with a single transaction, which gets automatically processed. # Add a document to a dispute Source: https://docs.synctera.com/v2/reference/adddisputedocument openapi-v2.json post /disputes/{dispute_id}/documents Add a supporting document to a dispute object # Create New Gateway Endpoint Configuration Source: https://docs.synctera.com/v2/reference/addgatewayconfig openapi-v2.json post /ach/gateways By creating Gateway Endpoint Configuration object for Fintech, you enable ACH in Auth flow for all the ACH transactions for specified Fintech (Tenant) # Send an ACH Source: https://docs.synctera.com/v2/reference/addtransactionout openapi-v2.json post /ach Send an ACH # Cancel an outgoing wire Source: https://docs.synctera.com/v2/reference/cancelwire openapi-v2.json patch /wires/{wire_id} Cancel an outgoing tranfer # Create a dispute action Source: https://docs.synctera.com/v2/reference/createaction openapi-v2.json post /disputes/{dispute_id}/actions Create an action on a disputed transaction # Dispute a transaction Source: https://docs.synctera.com/v2/reference/createdispute openapi-v2.json post /disputes Create a dispute against a transaction. # Create a document Source: https://docs.synctera.com/v2/reference/createdocument openapi-v2.json post /documents Store a document in the Synctera platform. # Create a new document version Source: https://docs.synctera.com/v2/reference/createdocumentversion openapi-v2.json post /documents/{document_id}/versions Docs # Create a EDD Source: https://docs.synctera.com/v2/reference/createedd openapi-v2.json post /edd Create a EDD # Create Incoming Synctera Pay Transfer Source: https://docs.synctera.com/v2/reference/createincomingsyncterapaytransfer openapi-v2.json post /synctera_pay/incoming/transfers Create incoming Synctera Pay transfer > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Create an internal transfer Source: https://docs.synctera.com/v2/reference/createinternaltransfer openapi-v2.json post /transactions/internal_transfer An internal transfer is an payment between two accounts within the same Fintech. By default, the payment is posted immediately. To indicate that you want to separate the authorization from the completion of the payment, use `capture_mode` = `MANUAL`. In that case, a separate call to update the status of the transfer will be required to complete the payment. # Create a migration mapping Source: https://docs.synctera.com/v2/reference/createmigrationmapping openapi-v2.json post /migration_mappings Create a migration mapping that associates a resource's old tenant identity with its new tenant identity. # Create a note Source: https://docs.synctera.com/v2/reference/createnote openapi-v2.json post /notes Create a note # Create a payment schedule Source: https://docs.synctera.com/v2/reference/createpaymentschedule openapi-v2.json post /payment_schedules Create a payment schedule # Create a Remote Check Deposit Source: https://docs.synctera.com/v2/reference/createrdcdeposit openapi-v2.json post /rdc/deposits Create a new deposit using remote deposit capture to an account # Create a secret Source: https://docs.synctera.com/v2/reference/createsecret openapi-v2.json post /webhook_secrets Create a webhook secret. The secret will be used to verify all subsequent webhook request signature. # Create Synctera Pay Transfer Source: https://docs.synctera.com/v2/reference/createsyncterapaytransfer openapi-v2.json post /synctera_pay Create an Outgoing Synctera Pay transfer > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Create a webhook Source: https://docs.synctera.com/v2/reference/createwebhook openapi-v2.json post /webhooks Create a webhook # Send a wire Source: https://docs.synctera.com/v2/reference/createwire openapi-v2.json post /wires Create an outgoing wire transfer # Delete a document Source: https://docs.synctera.com/v2/reference/deletedocument openapi-v2.json delete /documents/{document_id} Delete a document. Before a document can be deleted, it must have a deletion_reason explaining why the document was deleted. Use the [PATCH endpoint](ref:updatedocument) to set the `deletion_reason` property. # Delete a EDD Source: https://docs.synctera.com/v2/reference/deleteedd openapi-v2.json delete /edd/{edd_id} Delete a EDD # Delete Gateway Endpoint Configuration by ID Source: https://docs.synctera.com/v2/reference/deletegatewayconfigbyid openapi-v2.json delete /ach/gateways/{id} Use this to permanently remove Gateway Configuration and disable Auth Flow for Fintech (Tenant) # Delete migration mapping Source: https://docs.synctera.com/v2/reference/deletemigrationmapping openapi-v2.json delete /migration_mappings/{mapping_id} Soft-delete a migration mapping. # Delete a webhook Source: https://docs.synctera.com/v2/reference/deletewebhook openapi-v2.json delete /webhooks/{webhook_id} Delete a webhook # List All Gateway Configurations Source: https://docs.synctera.com/v2/reference/getallgatewayconfigs openapi-v2.json get /ach/gateways Gateway Endpoint Configuration object represents details required for Auth flow Request to the Fintech (Tenant) # Get a barcode Source: https://docs.synctera.com/v2/reference/getbarcode openapi-v2.json GET /cash/barcodes/{barcode_id} Get a barcode # Get a Dispute Source: https://docs.synctera.com/v2/reference/getdispute openapi-v2.json get /disputes/{dispute_id} Get a dispute by ID. # Get dispute document contents Source: https://docs.synctera.com/v2/reference/getdisputedocumentcontents openapi-v2.json get /disputes/documents/{document_id}/contents Returns the bytes of the requested document # Get a document Source: https://docs.synctera.com/v2/reference/getdocument openapi-v2.json get /documents/{document_id} Returns the document attributes. Use /documents/{document_id}/contents to get the contents. # Get contents of latest document version Source: https://docs.synctera.com/v2/reference/getdocumentcontents openapi-v2.json get /documents/{document_id}/contents Returns the bytes of the requested document. # Get document contents by version Source: https://docs.synctera.com/v2/reference/getdocumentversion openapi-v2.json get /documents/{document_id}/versions/{document_version}/contents Returns the bytes of the requested document. # Get a document by version Source: https://docs.synctera.com/v2/reference/getdocumentversioncontents openapi-v2.json get /documents/{document_id}/versions/{document_version} Returns the document (attributes). Use /documents/{document_id}/versions/{version}/contents to get the contents. # Get a EDD Source: https://docs.synctera.com/v2/reference/getedd openapi-v2.json get /edd/{edd_id} Get a EDD # Get webhook event Source: https://docs.synctera.com/v2/reference/getevent openapi-v2.json get /webhooks/{webhook_id}/events/{event_id} Get webhook event by ID # Get Gateway Endpoint Configuration By ID Source: https://docs.synctera.com/v2/reference/getgatewayconfigbyid openapi-v2.json get /ach/gateways/{id} Gateway Endpoint Configuration object represents details required for Auth flow Request to the Fintech (Tenant) # Get Incoming ACH Transaction By ID Source: https://docs.synctera.com/v2/reference/getincomingachbyid openapi-v2.json get /ach/incoming/{id} > 🚧 Beta > This is a Beta endpoint for use by early adopters. Do not use this endpoint with real customers. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # List Incoming ACH Transactions Source: https://docs.synctera.com/v2/reference/getincomingachlist openapi-v2.json get /ach/incoming > 🚧 Beta > This is a Beta endpoint for use by early adopters. Do not use this endpoint with real customers. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Get Incoming Synctera Pay Configuration Source: https://docs.synctera.com/v2/reference/getincomingsyncterapayconfiguration openapi-v2.json get /synctera_pay/incoming/configurations/{id} # Get Incoming Synctera Pay Transfer Source: https://docs.synctera.com/v2/reference/getincomingsyncterapaytransfer openapi-v2.json get /synctera_pay/incoming/transfers/{id} # Get incoming wire by id Source: https://docs.synctera.com/v2/reference/getincomingwire openapi-v2.json get /wires/incoming/{wire_id} Get an incoming wire by id # Retrieve a list of institutions Source: https://docs.synctera.com/v2/reference/getinstitutions openapi-v2.json get /institutions # Get an internal transfer Source: https://docs.synctera.com/v2/reference/getinternaltransferbyid openapi-v2.json get /transactions/internal_transfer/{id} Get an internal transfer auth by ID # Get migration mapping Source: https://docs.synctera.com/v2/reference/getmigrationmapping openapi-v2.json get /migration_mappings/{mapping_id} Get a migration mapping by ID. # Get a pending transaction Source: https://docs.synctera.com/v2/reference/getpendingtransactionbyid openapi-v2.json get /transactions/pending/{id} Get a pending transaction by its uuid # Get a posted transaction Source: https://docs.synctera.com/v2/reference/getpostedtransactionbyid openapi-v2.json get /transactions/posted/{id} Get a posted transaction by its uuid # Get Remote Check Deposit Source: https://docs.synctera.com/v2/reference/getrdcdeposit openapi-v2.json get /rdc/deposits/{deposit_id} Retrieves one deposit made using remote deposit capture associated with an account # Get the available retailer map URL. Source: https://docs.synctera.com/v2/reference/getretailermapurl openapi-v2.json GET /cash/barcodes/retailer_map_url Get the available retailer map URL # Get Outgoing Synctera Pay Configuration Source: https://docs.synctera.com/v2/reference/getsyncterapayconfiguration openapi-v2.json get /synctera_pay/configurations/{id} Get an Outgoing Synctera Pay configuration # Get Outgoing Synctera Pay Configurations Source: https://docs.synctera.com/v2/reference/getsyncterapayconfigurations openapi-v2.json get /synctera_pay/configurations Get all Outgoing Synctera Pay configurations # Get Outgoing Synctera Pay Transfer Source: https://docs.synctera.com/v2/reference/getsyncterapaytransfer openapi-v2.json get /synctera_pay/{id} Get an Outgoing Synctera Pay transfer > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Get Outgoing Synctera Pay Transfers Source: https://docs.synctera.com/v2/reference/getsyncterapaytransfers openapi-v2.json get /synctera_pay Get all Outgoing Synctera Pay transfers > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Get an Outgoing Synctera Pay vendor Source: https://docs.synctera.com/v2/reference/getsyncterapayvendor openapi-v2.json get /synctera_pay/vendors/{id} Get a Synctera Pay vendor > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # List Outgoing Synctera Pay vendors Source: https://docs.synctera.com/v2/reference/getsyncterapayvendors openapi-v2.json get /synctera_pay/vendors Get paginated list of Outgoing Synctera Pay vendors associated > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Get a sent ACH transaction Source: https://docs.synctera.com/v2/reference/gettransactionout openapi-v2.json get /ach/{transaction_id} Get a single sent ACH transaction # Get Transactions From Batch Payments Templates Source: https://docs.synctera.com/v2/reference/gettransactionsbatchpayments openapi-v2.json get /transactions/batchable Get all transactions that have the potential to be included in a batch payment. # Get a webhook Source: https://docs.synctera.com/v2/reference/getwebhook openapi-v2.json get /webhooks/{webhook_id} Get a webhook # Get an outgoing wire by id Source: https://docs.synctera.com/v2/reference/getwire openapi-v2.json get /wires/{wire_id} Get a wire by id # List disputes Source: https://docs.synctera.com/v2/reference/listdisputes openapi-v2.json get /disputes Get paginated list of disputes # List documents Source: https://docs.synctera.com/v2/reference/listdocuments openapi-v2.json get /documents Returns a paginated list of documents (metadata only, not contents). # List EDD Source: https://docs.synctera.com/v2/reference/listedd openapi-v2.json get /edd Get paginated list of EDD # List webhook events Source: https://docs.synctera.com/v2/reference/listevents openapi-v2.json get /webhooks/{webhook_id}/events List webhook events. This response will not associate with the event response history. # List Incoming Synctera Pay Configurations Source: https://docs.synctera.com/v2/reference/listincomingsyncterapayconfigurations openapi-v2.json get /synctera_pay/incoming/configurations # List Incoming Synctera Pay Transfers Source: https://docs.synctera.com/v2/reference/listincomingsyncterapaytransfers openapi-v2.json get /synctera_pay/incoming/transfers # List incoming wires Source: https://docs.synctera.com/v2/reference/listincomingwires openapi-v2.json get /wires/incoming Get paginated list of incoming wires # List migration mappings Source: https://docs.synctera.com/v2/reference/listmigrationmappings openapi-v2.json get /migration_mappings List migration mappings. Either tenant or old_tenant may view the records they are part of. # List notes Source: https://docs.synctera.com/v2/reference/listnotes openapi-v2.json get /notes Get paginated list of notes # List payments Source: https://docs.synctera.com/v2/reference/listpayments openapi-v2.json get /payment_schedules/payments Get paginated list of payments # List payment schedules Source: https://docs.synctera.com/v2/reference/listpaymentschedules openapi-v2.json get /payment_schedules Get paginated list of payment schedules # List pending transactions Source: https://docs.synctera.com/v2/reference/listpendingtransactions openapi-v2.json get /transactions/pending Get paginated list of pending transactions matching the provided filters # List posted transactions Source: https://docs.synctera.com/v2/reference/listpostedtransactions openapi-v2.json get /transactions/posted Get paginated list of posted transactions matching the provided filters # List Remote Check Deposits Source: https://docs.synctera.com/v2/reference/listrdcdeposits openapi-v2.json get /rdc/deposits Retrieves a paginated list of the deposits made using remote deposit capture associated with an account # List sent ACH transactions Source: https://docs.synctera.com/v2/reference/listtransactionsout openapi-v2.json get /ach List sent ACH transactions # List webhooks Source: https://docs.synctera.com/v2/reference/listwebhooks openapi-v2.json get /webhooks List all webhooks # List outgoing wires Source: https://docs.synctera.com/v2/reference/listwires openapi-v2.json get /wires Get paginated list of wires # Get merchant from MX Source: https://docs.synctera.com/v2/reference/mxreadmerchant openapi-v2.json get /mx/merchants/{merchant_guid} Returns information about a particular merchant from MX, such as a logo, name, and website. # Update Gateway Endpoint Configuration By ID Source: https://docs.synctera.com/v2/reference/patchgatewayconfigbyid openapi-v2.json patch /ach/gateways/{id} Gateway Endpoint Configuration object represents details required for Auth flow Request to the Fintech (Tenant) # Update an incoming wire by id Source: https://docs.synctera.com/v2/reference/patchincomingwire openapi-v2.json patch /wires/incoming/{wire_id} Update an incoming wire by id # Patch Note Source: https://docs.synctera.com/v2/reference/patchnote openapi-v2.json patch /notes/{note_id} Update a Note by ID. # Update a payment schedule Source: https://docs.synctera.com/v2/reference/patchpaymentschedule openapi-v2.json patch /payment_schedules/{payment_schedule_id} Update a payment schedule # Update a sent ACH transaction Source: https://docs.synctera.com/v2/reference/patchtransactionout openapi-v2.json patch /ach/{transaction_id} Update a sent ACH transaction (either status or funds availability) # Replace an existing secret Source: https://docs.synctera.com/v2/reference/replacesecret openapi-v2.json put /webhook_secrets Replace an existing webhook secret immediately or as part of rotation. This new secret will be used to verify all subsequent webhook request signature. # Resend an event Source: https://docs.synctera.com/v2/reference/resendevent openapi-v2.json post /webhooks/{webhook_id}/events/{event_id}/resend Resend a webhook event # Return a Synctera Pay Transfer Source: https://docs.synctera.com/v2/reference/returnsyncterapaytransfer openapi-v2.json post /synctera_pay/{id}/return Trigger a return upon an existing Outgoing Synctera Pay transfer > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Revoke the secret Source: https://docs.synctera.com/v2/reference/revokesecret openapi-v2.json delete /webhook_secrets Revoke the existing webhook secret. If this is called at the rolling secret time, then both old and new secrets will be revoked # Simulate authorization Source: https://docs.synctera.com/v2/reference/simulateauthorization openapi-v2.json post /cards/transaction_simulations/authorization Simulate an `authorization` type transaction by including the `card_token` and other authorization details in your request. # Simulate authorization advice Source: https://docs.synctera.com/v2/reference/simulateauthorizationadvice openapi-v2.json post /cards/transaction_simulations/authorization/advice An authorization advice allows an amount to be decreased after the authorization. This endpoint allows you to simulate post-swipe adjustments. Simulate an `authorization.advice` type transaction by including the `original_transaction_token` and other authorization details in your request. # Simulate Card Fulfillment Event Source: https://docs.synctera.com/v2/reference/simulatecardfulfillmentevent openapi-v2.json post /cards/{card_id}/webhook_simulations/fulfillment This endpoint is for testing environment only to trigger a simulated change in card fulfillment status event # Trigger an event Source: https://docs.synctera.com/v2/reference/triggerevent openapi-v2.json post /webhooks/trigger Trigger an specific event for webhook testing purpose # Update a barcode Source: https://docs.synctera.com/v2/reference/updatebarcode openapi-v2.json PATCH /cash/barcodes/{barcode_id} Update a barcode # Update a dispute Source: https://docs.synctera.com/v2/reference/updatedispute openapi-v2.json patch /disputes/{dispute_id} Update a dispute. # Update a document Source: https://docs.synctera.com/v2/reference/updatedocument openapi-v2.json patch /documents/{document_id} Update attributes of the latest document version. # Update an internal transfer Source: https://docs.synctera.com/v2/reference/updateinternaltransferbyid openapi-v2.json patch /transactions/internal_transfer/{id} Update an internal transfer. This is only relevant when committing or cancelling an internal transfer authorization (created with `capture_mode` = `MANUAL`) that hasn't already been completed. # Update migration mapping Source: https://docs.synctera.com/v2/reference/updatemigrationmapping openapi-v2.json patch /migration_mappings/{mapping_id} Update specific fields of a migration mapping. # Update an Outgoing Synctera Pay Transfer Source: https://docs.synctera.com/v2/reference/updatesyncterapaytransfer openapi-v2.json patch /synctera_pay/{id} Update an Outgoing Synctera Pay transfer > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. # Update a webhook Source: https://docs.synctera.com/v2/reference/updatewebhook openapi-v2.json put /webhooks/{webhook_id} Update a webhook # Wipeworkspace Source: https://docs.synctera.com/v2/reference/wipeworkspace openapi-v2.json post /wipe # Simulate receiving Wire transfer return Source: https://docs.synctera.com/v2/reference/wirereturnsimulation openapi-v2.json post /wires/transaction_simulations/receiving_return Use to simulate receiving a Wire transfer return in test environments. Creates an incoming Wire file with a single return entry based on a previously created outgoing transaction. The file gets automatically processed. # Simulate receiving Wire transaction Source: https://docs.synctera.com/v2/reference/wiretransactionsimulation openapi-v2.json post /wires/transaction_simulations/receiving_transaction Use to simulate receiving Wire transaction in test environments. Creates an incoming Wire file, which gets automatically processed. # A check was rejected. How can we find out the rejection reason? Source: https://docs.synctera.com/docs/a-check-was-rejected-how-can-we-find-out-the-rejection-reason In the Synctera console, open up the check transaction and on the left side there will be a banner which will state the reason for rejection. # ACH/Checks/Wires/Ledger Source: https://docs.synctera.com/docs/achcheckswiresledger PNG, JPEG, and TIFF formats are supported. When we receive wires that need manual intervention because a fraud alert has been raised, or an account number does not match an existing account in the system, name does not match or an incorrect transaction code has been used in the transaction ... There is essentially no benefit to you. The benefit is for the end-customer or the payroll provider, by having a direct deposit agreement they are allowed to send recurring credits to the same account with customer authorization. The main key bene... Generally this is not possible but in some cases Payroll providers send the ACH transfer two days early, (i.e they send an ACH transfer on the Aug 29 ACH file to be executed on Aug 31) For those, Synctera has a new future dated ACH webhook where y... Unfortunately, there is no way to verify this. The end-customer usually needs to provide a Direct Deposit form to their employer, Government or Payroll provider with the account information to process the deposit. You can assume that if a end-cust... The end-customer needs to obtain a direct deposit form from your corresponding sponsor bank and send it to the employer. The direct deposit form must include: Name, Address, Bank name, Account number, Routing number and Signature An individual ACH transaction can be reversed until it is sent to the network using our "Update a sent ACH transaction" endpoint You can see the cutoff times for same-day ACH in our guide here: [ach-guide](/docs/ach-guide) Same-day ACH payments will only settle the same business day if they were submitted before the “cutoff time” (4:45pm ET). If a same-day ACH is originated after the daily cutoff time, it will be sent as a same-day ACH the following business day. ACH files are sent during ACH Exchange Windows ([https://www.frbservices.org/resources/resource-centers/same-day-ach/fedach-processing-schedule.html](https://www.frbservices.org/resources/resource-centers/same-day-ach/fedach-processing-schedule.html)). Direct ACH payments typically take several business days to appear in the recipient's account. Some of our sponsor banks support receiving international wires, but not all. Sending international wires is not an available capability at the moment. If you'd like to know whether your account is eligible to receive international wires, please rea... MRDC checks are first sent to synctera. A pending transaction will be created for this check. Our operations team then approves or declines the check. Once the check is approved, then part of the funds will become available (how much is configured p... There are two types of statuses regarding an ACH transaction: The transaction status and the network status . Both of these statuses are reflected in the Platform Transaction view. Transaction status : The status of the transaction itself. Thi... For Incoming Credits/Debits, a network status will not be trackable. This is because Synctera is not the originator of the transaction so we do not have visibility into the status as it pertains to the file’s state in the network. There will be a decline reason present in the Platform. Common decline reasons include but are not limited to: Suspected fraud Insufficient Funds Fraud check failed (if so, there will be some details on the detail view regarding what fraud c...) If the file has been sent to the network we are not able to then revoke it - in this case a return has to be issued. If the account is frozen prior to the file being sent out, then the transaction can be canceled, but if after, it would have to be h... The check standards are as follows : Endorsement: "For mobile deposit at \[bank name]" and signed by account owner (if the signature is very clearly not the account owner, the check will not be accepted. Keep in mind we do not match signatures) ... Yes, all checks need to be reviewed & approved/declined after deposit. In the Synctera console, open up the check transaction and on the left side there will be a banner which will state the reason for rejection. You can view the reason for why the wire was returned in the Synctera console under the specific wire transaction. There will a banner on the left side that will state the reason. # An end customer has left our platform and the accounts need to be closed but there are still some funds in it. How can I proceed with the closure? Source: https://docs.synctera.com/docs/an-end-customer-has-left-our-platform-and-the-accounts-need-to-be-closed-but-there-are-still-some-funds-in-it-how-can-i-proceed-with-the-closure The funds needs to be returned back to the end-customer and once that has been done and the account balance is zero, the account can be closed. # An end customer is getting an Address Verification Service (AVS) failed error. How can this be resolved? Source: https://docs.synctera.com/docs/an-end-customer-is-getting-an-address-verification-service-avs-failed-error-how-can-this-be-resolved AVS looks at the end-customer’s street address and postal code, so the end-customer needs to be extra careful to ensure those match perfectly. The AVS decline details is shown in our UI and it is in the transaction API payload under .data.user\_data.address\_verification # An end-customer is unable to add a card to their Apple/Google Wallet, what is the reasoning behind this and how can this be resolved? Source: https://docs.synctera.com/docs/an-end-customer-is-unable-to-add-a-card-to-their-apple-wallet-what-is-the-reasoning-behing-this-and-how-can-this-be-resolved Mastercard, Apple, and/or Google can decline a customer’s ability to add their debit or credit card to their digital wallet. This occurs when the entities believe the fraud risk of the individual is higher than their threshold. **Apple / Google Pay** For Secure Element Tokens, the device, account, and phone number scores provide a summary of transaction and experience information for the specific device and Apple/Google account that are requesting provisioning. Apple/Google calculate these scores based on behavior across their lines of business and programs. They consider various factors in coming up with the score, including historic and recent transactions, anomalous behavior, and links to known bad actors or activity. The trust scoring modes are managed by their fraud team and adapted based on the latest fraud knowledge and trends. The device and account scores are presented as integers ranging from 1-5. The Device Score with a value of 1 should be declined. Below are the possible reasons that a customer is unable to add their card to a digital wallet: | Reason Code | Code Description | Additional Detail | | --------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | ACCOUNT\_TOO\_NEW\_SINCE\_LAUNCH | Account is considered new relative to the Payment App Provider service launch. | Apple ID was created 40 days or less prior to launch. | | ACCOUNT\_TOO\_NEW | Account is considered new relative to provisioning request. | Apple ID was created 40 days or less prior to provisioning request | | ACCOUNT\_CARD\_TOO\_NEW | Account/card is considered new relative to provisioning request. | Apple ID/Card pair is less than 20 days old. | | ACCOUNT\_RECENTLY\_CHANGED | Changes have recently been made to account data. | Changes have been made to the account settings for the Apple ID in prior 20 days. | | SUSPICIOUS\_ACTIVITY | Suspicious activity has been linked to this account. | Suspicious transactions linked to this account. | | INACTIVE\_ACCOUNT | Inactive account. | The account has not had activity in the last year. | | HAS\_SUSPENDED\_TOKENS | Device contains suspended tokens. | Suspended cards in the secure element. | | DEVICE\_RECENTLY\_LOST | Device has recently been reported lost. | The phone was put in lost mode in the last 7 days for longer than the duration threshold (1 hour). | | TOO\_MANY\_RECENT\_ATTEMPTS | Excessive recent tokenization attempts to this device. | The number of provisioning attempts for this card on this device in 72 hours exceeds the threshold (3 attempts). | | TOO\_MANY\_RECENT\_TOKENS | Excessive recent tokenization to this device. | There have been more than the threshold number of different cards attempted at provisioning to this phone in 24 hours (5 different cards). | | TOO\_MANY\_DIFFERENT\_CARDHOLDERS | Excessive non-matching Cardholder names within the device. | The card provisioning request contains a distinct name in excess of the permitted threshold (2 distinct names). | | LOW\_DEVICE\_SCORE | Low device score. | Device score is less than 3. | | LOW\_ACCOUNT\_SCORE | Low account score. | Account score is less than 4. | | OUTSIDE\_HOME\_TERRITORY | Non-domestic tokenization attempt. | Device provisioning location outside of Apple ID home country. | | UNABLE\_TO\_ASSESS | Non-domestic tokenization attempt. | Model rules not available at this time (in cases where back end systems time out). | | HIGH\_RISK | High fraud risk identified. Enhanced verification recommended. | Apple algorithm identified high fraud risk. Apple recommendation to DECLINE. | | LOW\_PHONE\_NUMBER\_SCORE | Low phone number score | Phone number score is less than 3. | # API Management Source: https://docs.synctera.com/docs/api-management Here's a guide to get around that: [/docs/webhooks-guide#3-create-a-webhook-subscription-for-events](/docs/webhooks-guide#3-create-a-webhook-subscription-for-events) # Are there any differences in the Plaid linking process depending on the specific bank or credit union? Source: https://docs.synctera.com/docs/are-there-any-differences-in-the-plaid-linking-process-depending-on-the-specific-bank-or-credit-union No, unless the bank/credit union is not supported by Plaid in which Synctera will have to do the micro deposits verification. # Can a end-customer change their shipping address after a card request has been made? If so, how? Who should be contacted? Source: https://docs.synctera.com/docs/can-a-end-customer-change-their-shipping-address-after-a-card-request-has-been-made-if-so-how-who-should-be-contacted You can reach out to Synctera Support on your end customer's behalf. We will then contact the card provider to attempt to change the shipping address. The provider can typically make the adjustment for an additional fee, which the end-customer will have to pay. However, we cannot guarantee that an order will be successfully adjusted. # Can accounts receive and send international USD wires? Source: https://docs.synctera.com/docs/can-accounts-receive-and-send-international-usd-wires Some of our sponsor banks support receiving international wires, but not all. Sending international wires is not an available capability at the moment. If you'd like to know whether your account is eligible to receive international wires, please reach out to your Implentation & Onboarding manager. # Can an end-customer cancel a card shipment? If so, how? Source: https://docs.synctera.com/docs/can-an-end-customer-cancel-a-card-shipment-if-so-how You can reach out to Synctera Support on the end-customer's behalf. We will then contact the card provider to attempt to cancel the shipment. The provider can typically pull the shipment for an additional fee, which the end-customer will have to pay. However, we cannot guaranteed that an order will be successfully cancelled. # Can an end-customer fund their card through an instant deposit with a payment app (Paypal, Venmo, etc) without declines? Source: https://docs.synctera.com/docs/can-an-end-customer-fund-their-card-through-an-instant-deposit-with-a-payment-app-paypal-venmo-etc-without-declines Yes, an end-customer can add their card to another payment app, and initiate a push of funds to the card from that app. # Can an end customer's rejected application be overridden? Source: https://docs.synctera.com/docs/can-an-end-customers-rejected-application-be-overrriden Depending on the nature of the rejected application, yes. If the application was rejected due to non-response, you can re-run KYC on our platform to generate a new case. If the end-customer's application was rejected for high risk concerns, we can ask for additional documentation, and have a conversation. Some end-customers who are known bad based on a track record across our system or bank partners may not be given a chance to appeal. # Can card orders be shipped internationally? Source: https://docs.synctera.com/docs/can-card-orders-be-shipped-internationally Yes they can be. # Can cards be shipped to PO boxes? Source: https://docs.synctera.com/docs/can-cards-be-shipped-to-po-boxes It is possible from our end, but it depends on your policy as our customer. # Can end customers outside of USA/Canada create accounts? If so, how? Source: https://docs.synctera.com/docs/can-end-customers-outside-of-usa-canada-create-accounts-if-so-how As long as the end-customer has an address that is in the list of your specific supported countries and passes KYC, an account can be created and associated with them. To find your specific list of supported countries, you can go to Supported Countries under Operations in the Synctera Console. # Can I customize my KYC rules? Source: https://docs.synctera.com/docs/can-i-customize-my-kyc-rules No, you cannot customize KYC rules, without approval from your sponsor bank. # Can purchases settle for an amount larger than the amount that was authorized? Source: https://docs.synctera.com/docs/can-purchases-settle-for-an-amount-larger-than-the-amount-that-was-authorized Yes, some charges (e.g. restaurant bills with tip) typically settle for a larger amount. # Can the end customer link multiple bank accounts via micro-deposit account verification? Source: https://docs.synctera.com/docs/can-the-end-customer-link-multiple-bank-accounts-via-micro-deposit-account-verification Yes, as long as it is not the same bank account multiple times. Synctera has a configuration which does not allow any end-customers across the customer to link the same external account, but this can be turned off at the your request and some customers have done that already. # Can we fail a KYC case if we believe it is a fraudulent user? Source: https://docs.synctera.com/docs/can-we-fail-a-kyc-case-if-we-believe-it-is-a-fraudulent-user If you believe that an end-user's signup is potentially fraudulent, we can either fail the user, or request additional documentation to make a determination. Ground Control may also fail users we believe to be fraudulent during the course of a normal investigation. If an end-user is failed due to concerns of fraud (identity theft, manipulated identity), we can reconsider this outcome if additional documentation is supplied later on. # Can we reverse an ACH? Source: https://docs.synctera.com/docs/can-we-reverse-an-ach An individual ACH transaction can be reversed until it is sent to the network using our "Update a sent ACH transaction" endpoint # Cards/AFT/OCT Source: https://docs.synctera.com/docs/cardsaftoct AVS looks at the end-customer's street address and postal code, so the end-customer needs to be extra careful to ensure those match perfectly. The AVS decline details is shown in our UI and it is in the transaction API payload under .data.user\_dat... If a merchant requires a US address and customer does not have one, they will not be able to use their card with that particular merchant. AVS only uses 1 address. If legal address is populated, it is used. If not, shipping address is used. We encourage you to pass the tracking number onto the end-customer so they can track where the package is. If there is an issue with delivery, you can reach out to Synctera support and we can follow-up with our partner, Arroweye, to check for any up... You can reach out to Synctera Support on the end-customer's behalf. We will then contact the card provider to attempt to cancel the shipment. The provider can typically pull the shipment for an additional fee, which the end-customer will have to pay... You can reach out to Synctera Support on your end customer's behalf. We will then contact the card provider to attempt to change the shipping address. The provider can typically make the adjustment for an additional fee, which the end-customer will ... In the Synctera console, we display merchant processors with an astrerick as following: PP \* = PayPal SQ \* = Square/Block VENMO\* Cash App\* SQ \* - Square/Block PRICELN \* FS \* - FastSpring" The end-customer should contact their issuing cards bank if they would like to dispute a card transaction. Yes, some charges (e.g. restaurant bills with tip) typically settle for a larger amount. ATM fees are typically charged by the ATM owner/operator. As our partner banks typically don't own/operate ATMs, all ATM transactions will have fees until we offer surcharge free ATMs. ATM fees vary, typically between 1.5 and 3% depending on the... Yes they can be. It is possible from our end, but it depends on your policy as our customer. Mastercard, Apple, and/or Google can decline a customer's ability to add their debit or credit card to their digital wallet. This occurs when the entities believe the fraud risk of the individual is higher than their threshold. Apple / Google Pay... You can delete the card and recreate it with correct info. Transaction declined: TabaPay returns a response on the transaction, but this response is an ERROR status caused by an unknown error Transaction declined by processor: TabaPay does not return a response on the transaction, but rather returns a cer... A posted transaction should be negated by either refunds by the merchant (end-customer takes it up with the merchant) or through a dispute. There are myriad of reasons. The list is always subject to change. In general, HTTP 400-499 are client side errors, that require you to remediate before reattempting the request. 500-599 constitutes server side errors, that can be retried later. ... You can gather this data by using our metabase that allows you to build reports on such data: [https://insights.synctera.com/dashboard/30-synctera-insights-customer-reporting](https://insights.synctera.com/dashboard/30-synctera-insights-customer-reporting) If you wish to customize your spending limits before launching, you should contact Synctera's Implementation and Onboarding team. However, if you wish to change these limits post-launch, you should contact our Synctera's Risk and Compliance team. Yes, an end-customer can add their card to another payment app, and initiate a push of funds to the card from that app. A contactless is any card that has the "Tap feature" enabled, allowing you to make purchases by simply tapping the card at the card terminal. The number of contactless transactions that can be made fall under the same limit as the card limits. If the end-customer has tried the card at multiple different POS terminals and the contactless feature is still not working. They can try inserting the card or using the magnetic strip to make purchases. If they would like to use the contactless f... # Customers/Accounts Source: https://docs.synctera.com/docs/customersaccountspersonsbusinesses If your end-customer's Account status is "Active", check to make sure that their Customer status is also "Active". Customer status overrides Acount status. You can find more information about Customer status in our API reference here: [https://dev](https://dev).... If a financial institution fails to acknowledge a routing number, it is most likely due to their validation system not utilizing the most recent edition of the Federal Reserve's bank routing directory. The instituion will need to update their record... In order to close an account successfully, you must ensure that the account balance is 0 dollars. To close an account within the Synctera console, go to the customers account and from there in the top right you will see an "Actions" button, click ... As long as the end-customer has an address that is in the list of your specific supported countries and passes KYC, an account can be created and associated with them. To find your specific list of supported countries, you can go to Supported Countr... It is reflected instantly. Account Balance is impacted only by posted transactions, but Available Balance is also impacted by pending transactions. Until a hold is fully posted, only the Available Balance is decreased by the amount of the hold. The Available Balance has a flo... It does not auto-suspend the card, but part of authorizing a transaction requires that the end-customer and account be in good standing. You should suspend cards when you wish to fully block all authorizations. Through the UI, if you freeze an end-customer, their accounts will also be frozen. Using the API you must make separate API calls to freeze the end-customer and each account. You can find more details on freezing accounts in our API guide here: ... The list of account statuses and their descriptions can be found in our API reference here: [listaccounts](/v2/reference/listaccounts) A force-post or charges that settle for a higher amount than authorized (e.g restaurant bills with a tip) can cause an account to go negative. In order to move the end-customer's funds, the account needs to be reverted to an unsuspended/unfrozen status. Once the funds have been returned to the end-customer, you can close the account. The funds needs to be returned back to the end-customer and once that has been done and the account balance is zero, the account can be closed. When an account goes into a negative balance this can be due to few typical use cases. When the settlement amount of a transaction is greater than the authorized amount e.g. force post or due to a late return Timing issue when the effect... When an end-customer requests to close a Savings account, the account needs to be moved to IN\_CLOSING status (i.e if a customer wants to close an account mid month on March 15, the account is moved to IN\_CLOSING on March 15). The Interest calculat... # Do all checks need to be reviewed & approved/declined manually after deposit? Source: https://docs.synctera.com/docs/do-all-checks-need-to-be-reviewed-approveddeclined-manually-after-deposit Yes, all checks need to be reviewed & approved/declined after deposit. # Fraud Source: https://docs.synctera.com/docs/fraud Transactions sometimes trigger a false positive if the end-customer attempts multiple transactions in a short period of time or spends outside of their normal activity (i.e. high dollar transactions, unusual merchants, high risk merchants, etc.). ... If an end-customer cannot make a payment, it could be for a number of reasons. If you are contacted about an end-customer unable to make a payment, you can review the Synctera console to determine if it was flagged for fraudulent behavior. If so, ... # How are merchant processors for merchants displayed in transactions? Source: https://docs.synctera.com/docs/how-are-merchant-processors-for-merchants-displayed-in-transactions In the Synctera console, we display merchant processors with an astrerick as following: PP \* = PayPal SQ \* = Square/Block VENMO\* Cash App\* SQ \* - Square/Block PRICELN \* FS \* - FastSpring" # How are micro-deposits monitored? Source: https://docs.synctera.com/docs/how-are-micro-deposits-monitored Micro-deposits are strictly monitored by Plaid, Synctera does not handle them. Plaid's bank pushes two credits and a debit to the end-customers account, and then in the Synctera app, via the Plaid UI, the end-customer can confirm that they saw it on their bank. # How can a customer pass AVS if they have different shipping and billing addresses? Does additional documentation need to be provided? Source: https://docs.synctera.com/docs/how-can-a-customer-pass-avs-if-they-have-different-shipping-and-billing-addresses-does-additional-documentation-need-to-be-provided AVS only uses 1 address. If legal address is populated, it is used. If not, shipping address is used. # How can an end-customer dispute a card transaction? Source: https://docs.synctera.com/docs/how-can-an-end-customer-dispute-a-card-transaction The end-customer should contact their issuing cards bank if they would like to dispute a card transaction. # How can I check the reason why an end customer was unable to make a payment? Source: https://docs.synctera.com/docs/how-can-i-check-the-reason-why-an-end-customer-was-unable-to-make-a-payment Given a declined transaction, the reason can be found using our Transactions API. If you're using v0, it can be found using the "Get a pending transaction" endpoint, under data->reason. If you're using v1, it can be found using the "Get a transaction by ID" endpoint, under decline->reason. # How can I create a list of all of my organization's customers using specific products my business offers via Synctera? Source: https://docs.synctera.com/docs/how-can-i-create-a-list-of-all-of-my-organizations-customers-using-specific-products-my-business-offers-via-synctera You can gather this data by using our metabase that allows you to build reports on such data: [https://insights.synctera.com/dashboard/30-synctera-insights-customer-reporting](https://insights.synctera.com/dashboard/30-synctera-insights-customer-reporting) # How can I customize end-customer spending limits? Source: https://docs.synctera.com/docs/how-can-i-customize-end-customer-spending-limits If you wish to customize your spending limits before launching, you should contact Synctera’s Implementation and Onboarding team. However, if you wish to change these limits post-launch, you should contact our Synctera’s Risk and Compliance team. # How can I find out why an application was denied? Can the end customer re-apply? Source: https://docs.synctera.com/docs/how-can-i-find-out-why-an-application-was-denied-can-the-end-customer-re-apply If an end-customer's sign up is denied, you will find notes from the Ground Control case giving the reasoning behind the rejection. Depending on the reason, the end-customer can re-apply. Questions regarding end-customer denied applications can be forwarded to [groundcontrol@synctera.com](mailto:groundcontrol@synctera.com) # How can I get more information on the reasons behind a declined AFT/OCT case? Source: https://docs.synctera.com/docs/how-can-i-get-more-information-on-the-reasons-behind-a-declined-aftoct-case Transaction declined: TabaPay returns a response on the transaction, but this response is an ERROR status caused by an unknown error Transaction declined by processor: TabaPay does not return a response on the transaction, but rather returns a certain error message (e.g., if we reach our aggregate daily limits with TabaPay, the processor returns a 429 error message, and we show the message transaction declined by processor). We currently have a change in development that aims to provide much more fine grained details about why transactions are declined when they occur. As it is, it is still a manual process to obtain these details, but you can reach out to Synctera Support with any inquiries for specific transactions and we can provide details # How can I know why an ACH transaction failed? Source: https://docs.synctera.com/docs/how-can-i-know-why-an-ach-transaction-failed There will be a decline reason present in the Platform. Common decline reasons include but are not limited to: * Suspected fraud * Insufficient Funds * Fraud check failed (if so, there will be some details on the detail view regarding what fraud check the transaction failed on) # How can we link our Operational and Reserve Accounts in the Synctera Console? Source: https://docs.synctera.com/docs/how-can-we-link-our-operational-and-reserve-accounts-in-the-synctera-console Only users with the ability to link external accounts can complete this process. The built-in **Restricted External Accounts** role allows this and can be assigned by any of your administrators within the [Console's User Management section](https://app.synctera.com/user-management/users). How to Link Your Account: # How do ATMs and ATM fees work at Synctera? Source: https://docs.synctera.com/docs/how-do-atms-and-atm-fees-work-at-synctera ATM fees are typically charged by the ATM owner/operator. As our partner banks typically don’t own/operate ATMs, all ATM transactions will have fees until we offer surcharge free ATMs. ATM fees vary, typically between 1.5 and 3% depending on the owner. These fees are charged to the cardholder as part of the transaction. # How do international customers provide a valid address if the merchant only allows entry of US addresses? Source: https://docs.synctera.com/docs/how-do-international-customers-provide-a-valid-address-if-the-merchant-only-allows-entry-of-us-addresses If a merchant requires a US address and customer does not have one, they will not be able to use their card with that particular merchant. # How do we enable case notifications for an employee? Source: https://docs.synctera.com/docs/how-do-we-enable-case-notifications-for-an-employee To enable case notifications for an employee: # How does Synctera handle end-customer errors on incoming wires? Source: https://docs.synctera.com/docs/how-does-synctera-handle-end-customer-errors-on-incoming-wires When we receive wires that need manual intervention because a fraud alert has been raised, or an account number does not match an existing account in the system, name does not match or an incorrect transaction code has been used in the transaction (i.e BTR), we take the following steps: If there is a “Fraud Notice” on the wire, the wire is reported to our compliance team for further review who will then decide whether to approve or decline the wire. If the beneficiary name and account number of the wire does not match the account name & number in our console, we return the wire and will notify you that a wire was received but it was returned and the reason behind the return. # How does the end customer ensure their check is deposited successfully? Source: https://docs.synctera.com/docs/how-does-the-end-customer-ensure-their-check-is-deposited-successfully MRDC checks are first sent to synctera. A pending transaction will be created for this check. Our operations team then approves or declines the check. Once the check is approved, then part of the funds will become available (how much is configured per bank) and part will be held (the amount of time it's held is configured per bank). # How does the interest payout process work when a Fintech customer requests to close their savings account? Source: https://docs.synctera.com/docs/how-does-the-interest-payout-process-work-when-a-fintech-customer-requests-to-close-their-savings-account When an end-customer requests to close a Savings account, the account needs to be moved to IN CLOSING status (i.e if a customer wants to close an account mid month on March 15, the account is moved to IN CLOSING on March 15). The Interest calculation service, at the end of the month will calculate interest owed to that account from the beginning of the month until the account has changed its status to IN CLOSING. In the example above, the last day of the month, we will calculate interest owed from March 1st to March 15 and perform the payout. You will then receives a webhook notification when the payout is performed. After the Payout is performed, you can can transfer the funds to the end-customers external account or any other account, up to the customer. After the Payout, the account has a zero balance and you can now CLOSE the account. # How long can a transaction be in pending status? Source: https://docs.synctera.com/docs/how-long-can-a-transaction-be-in-pending-status Most pending charges disappear in around 5 days or less, though some institutions ask cardholders to allow up to 7 days to process charges. While merchants typically clear their purchases daily, taking longer to process your purchase can contribute to extended pending times # How long does it take for an end customer's information (such as address) to reflect in the bank's database after modification? Source: https://docs.synctera.com/docs/how-long-does-it-take-for-an-end-customers-information-such-as-address-to-reflect-in-the-banks-database-after-modification It is reflected instantly. # I am subscribed to webhooks and have noticed that they are not always delivered in order. What is the best way to handle this? Source: https://docs.synctera.com/docs/i-am-subscribed-to-webhooks-and-have-noticed-that-they-are-not-always-delivered-in-order-what-is-the-best-way-to-handle-this Here's a guide to get around that: [webhooks-guide](/docs/webhooks-guide#3-create-a-webhook-subscription-for-events) # I would like to release a hold on a transaction for a customer, how can I do that? Source: https://docs.synctera.com/docs/i-would-like-to-release-a-hold-on-a-transaction-for-a-customer-how-can-i-do-that You can contact Synctera Support with the reason you would like to release the hold so we can investigate to see whether it is possible. # If an end customer's account status is suspended or frozen, how can I move the funds in order to close the account? Source: https://docs.synctera.com/docs/if-an-end-customers-account-status-is-suspended-or-frozen-how-can-i-move-the-funds-in-order-to-close-the-account In order to move the end-customer's funds, the account needs to be reverted to an unsuspended/unfrozen status. Once the funds have been returned to the end-customer, you can close the account. # Is there a limit for the number of contactless transactions that can be made in a day? Source: https://docs.synctera.com/docs/is-there-a-limit-for-the-number-of-contactless-transactions-that-can-be-made-in-a-day The number of contactless transactions that can be made fall under the same limit as the card limits. # Is there a way for us (the customer of Synctera) to know if a payment via direct deposit is on its way? Source: https://docs.synctera.com/docs/is-there-a-way-for-us-the-customer-of-synctera-to-know-if-a-payment-via-direct-deposit-is-on-its-way Generally this is not possible but in some cases Payroll providers send the ACH transfer two days early, (i.e they send an ACH transfer on the Aug 29 ACH file to be executed on Aug 31) For those, Synctera has a new future dated ACH webhook where you can see that the ACH has arrived and will be executed against the customer account in the future. The Webhook has the 'type' ACH.INCOMING.FUTURE\_DATED". # Is there any way for us to know if one of our end customers have set up direct deposit? Source: https://docs.synctera.com/docs/is-there-any-way-for-us-the-customer-of-synctera-to-know-if-one-of-our-end-customers-have-set-up-direct-deposit Unfortunately, there is no way to verify this. The end-customer usually needs to provide a Direct Deposit form to their employer, Government or Payroll provider with the account information to process the deposit. You can assume that if a end-customer has requested a Direct Deposit form they are going to give it to an employer, but this is is not guaranteed (i.e an end-customer can ask their bank for a Direct Deposit form but decide to use a different account for their payroll because their second bank gives them a better incentive or their payroll provider cannot recognize that institution) There are solutions in the market to switch existing direct deposits payroll like Pinwheel or Atomic which you may find interesting. # Is there any way to stop a pending transaction from processing? Source: https://docs.synctera.com/docs/is-there-any-way-to-stop-a-pending-transaction-from-processing There is not, a pending transaction needs to get posted first and the can be reversed after if funds are to be returned or the transaction can just expire natually. Additionally, we do not control the lifecycle of a card transaction once approved. Once approved, that is us promising the network that the merchant can take the funds from the bank. If they do, we have to respect it and pursue disputes if the end-customer claims it was fraudulent, or they have to take it up with the merchant. We have no control over how a merchant handles the authorization after the approval. # KYC/KYB Source: https://docs.synctera.com/docs/kyckyb If an end-customer's sign up is denied, you will find notes from the Ground Control case giving the reasoning behind the rejection. Depending on the reason, the end-customer can re-apply. Questions regarding end-customer denied applications can be... Depending on the nature of the rejected application, yes. If the application was rejected due to non-response, you can re-run KYC on our platform to generate a new case. If the end-customer's application was rejected for high risk concerns, we c... If you believe that an end-user's signup is potentially fraudulent, we can either fail the user, or request additional documentation to make a determination. Ground Control may also fail users we believe to be fraudulent during the course of a nor... Full legal name as it appears on government documents (no nicknames, include all last names if you have multiple, etc.) A valid US address that includes: Street Address Apartment number (if applicable) City State Zip code A valid Social Secu... No, you cannot customize KYC rules, without approval from your sponsor bank. # Synctera Learning Center Source: https://docs.synctera.com/docs/learning-center In-depth information about Synctera ## Synctera for building FinTech apps and embedded banking products Products and platform features for building financial products Onboard with Synctera and get ready to launch Use Synctera to manage your financial product post-launch Find answers to Frequently Asked Questions ## Synctera for Banks ### Contact Us # My end-customer's account status is Active, so why can't I send internal transfers to their Account? Source: https://docs.synctera.com/docs/my-end-customers-account-status-is-active-so-why-cant-i-send-internal-transfers-to-their-account If your end-customer's Account status is "Active", check to make sure that their Customer status is also "Active". Customer status overrides Account status. You can find more information about Customer status in our API reference here: [create-a-personal-customer](/docs/create-a-personal-customer#person-status-attributes) # Payments Source: https://docs.synctera.com/docs/payments Use the Transactions API. For v0, check the "Get a pending transaction" endpoint under data->reason. For v1, use the "Get a transaction" endpoint under data->decline\_reason. Micro-deposits are monitored by Plaid, not Synctera. Plaid pushes two credits and a debit to the end-customer's account. The end-customer confirms the deposits via the Plaid UI in the Synctera app. No, unless the bank/credit union is not supported by Plaid. In that case, Synctera will have to do the micro deposits verification. Yes, as long as it's not the same bank account multiple times. Synctera has a configuration to prevent linking the same external account across customers, but this can be turned off upon request. # Platform Reporting and Metrics Source: https://docs.synctera.com/docs/platform-reporting-and-metrics Introduction This document describes how we calculate the API Availability. We use this definition to create the Synctera Service Uptime SLA Monitoring (Link TBD). FOr more information about this, please contact [support@synctera.com](mailto:support@synctera.com) Definition... # Synctera Console Source: https://docs.synctera.com/docs/synctera-console Only users with the ability to link external accounts can complete this process. The built-in Restricted External Accounts role allows this and can be assigned by any of your administrators within the Console's User Management section. How to ... To enable case notifications for an employee: 1. Log into the Synctera Console. 2. Once you are in the Cases and Configuration. 3. From there, you can click on any case type and Update the default assignees you would like for any specific... You should have an admin set-up internally within your team and that admin will have the ability to grant and change access for all members of your team. The admin can do this within the Synctera Console here: [https://app.synctera.com/user-ma](https://app.synctera.com/user-ma)... # The contactless feature on an end-customers card is not working, how can this be resolved? Source: https://docs.synctera.com/docs/the-contactless-feature-on-an-end-customers-card-is-not-working-how-can-this-be-resolved If the end-customer has tried the card at multiple different POS terminals and the contactless feature is still not working. They can try inserting the card or using the magnetic strip to make purchases. If they would like to use the contactless feature again, it would be best to reissue the card. # The end customer initiated a same day ACH. Why hasn't it been posted in the account? Source: https://docs.synctera.com/docs/the-end-customer-initiated-a-same-day-ach-why-hasnt-it-been-posted-in-the-account Same-day ACH payments will only settle the same business day if they were submitted before the “cutoff time” (4:45pm ET). If a same-day ACH is originated after the daily cutoff time, it will be sent as a same-day ACH the following business day. # Transaction Status Source: https://docs.synctera.com/docs/transaction-status A pre-authorization is typically used to reserve funds with a reasonable estimate of how much will be cleared. An authorization is when the amount is known. Pre-authorizations are used in situations like Automated Fuel Dispensers (AFD), hotel rese ... There is not, a pending transaction needs to get posted first and the can be reversed after if funds are to be returned or the transaction can just expire natually. Additionally, we do not control the lifecycle of a card transaction once approved.... You can contact Synctera Support with the reason you would like to release the hold so we can investigate to see whether it is possible. Most pending charges disappear in around 5 days or less, though some institutions ask cardholders to allow up to 7 days to process charges. While merchants typically clear their purchases daily, taking longer to process your purchase can contribut... Outgoing debit ACHs have a 2 day hold on the funds that have been added to the account on Synctera's platform. Incoming checks have a configurable hold (both the amount of time until the hold expires and the amount of funds that are immediately re...) # Understanding ACH Subtypes Source: https://docs.synctera.com/docs/understanding-ach-subtypes #### **How can I interpret ACH subtypes on the Synctera Platform?** ACH transactions have unique subtypes that can be filtered for in Transaction Lists. What do they mean exactly? **Outgoing**: Synctera/Bank is ODFI
**Incoming**: Synctera/Bank is RDFI

Whether it is marked as debit/credit is within the frame of reference of the institution receiving the ACH (RDFI). E.g. * Outgoing debit: “I am debiting your account” * Incoming credit: “You are crediting my account” More concretely:

**Outgoing debit**: Originated with Synctera’s ACH API, pulling money from an external account into the Synctera account.
Balance impact: Debit to external account, Credit to Synctera account

**Outgoing credit**: Originated with Synctera’s ACH API, pushing money out of the Synctera account into an external account.
Balance impact: Debit to Synctera account, Credit to external account

**Incoming credit**: Originated at another institution, pushing money from the external account into the Synctera account.
Balance Impact: Debit to external account, Credit to Synctera account

**Incoming debit**: Originated at another institution, pulling money from the Synctera account into the external account.
Balance Impact: Debit to Synctera account, Credit to external account. # We have a few inactive end-customers who would like their accounts closed, what is the process to close their accounts? Source: https://docs.synctera.com/docs/we-have-a-few-inactive-end-customers-who-would-like-their-accounts-closed-what-is-the-process-to-close-their-accounts In order to close an account successfully, you must ensure that the account balance is 0 dollars. To close an account within the Synctera console, go to the customers account and from there in the top right you will see an "Actions" button, click on that and a drop-down menu will pop-up which will give you the option to "close account". You can select that option and the account will be closed. Once the account has been closed, you will be billed one last time for that account only for the month the account was closed on. # We have new employees joining, how do we give them access to the Synctera Console? Source: https://docs.synctera.com/docs/we-have-new-employees-joining-how-do-we-give-them-access-to-the-synctera-console You should have an admin set-up internally within your team and that admin will have the ability to grant and change access for all members of your team. The admin can do this within the Synctera Console here: 1. [https://app.synctera.com/user-management/users](https://app.synctera.com/user-management/users). # We know that direct deposit is a type of ACH. Is there any benefit or difference between setting up direct deposit vs the payer executing an ACH push? Source: https://docs.synctera.com/docs/we-know-that-direct-deposit-is-a-type-of-ach-is-there-any-benefit-or-difference-between-setting-up-direct-deposit-vs-the-payer-executing-an-ach-push-ie-time-for-payment-to-arrive-costs-etc There is essentially no benefit to you. The benefit is for the end-customer or the payroll provider, by having a direct deposit agreement they are allowed to send recurring credits to the same account with customer authorization. The main key benefit is reliability, and also the funds via payroll are considered “safer” since the payroll companies take the money from the employer a few days in advance. A random push of money from an employer is considered more risky. # What are the common reasons why an end customer might be mistakenly flagged as fraudulent? Source: https://docs.synctera.com/docs/what-are-the-common-reasons-why-an-end-customer-might-be-mistakenly-flagged-as-fraudulent Transactions sometimes trigger a false positive if the end-customer attempts multiple transactions in a short period of time or spends outside of their normal activity (i.e. high dollar transactions, unusual merchants, high risk merchants, etc.). These fraud rules are in place to protect customers from unauthorized activity. End-customers can contact you to disclose the purpose of their transaction to further troubleshoot. This will allow you to pair with Ground Control and help the transaction get through. # What are the cutoff times for same-day ACH? Source: https://docs.synctera.com/docs/what-are-the-cutoff-times-for-same-day-ach You can see the cutoff times for same-day ACH in our guide here: [ach-guide](/docs/ach-guide) # What are the different types of statuses for an ACH transaction on the Synctera platform, and how do they relate to the transaction and the network? Source: https://docs.synctera.com/docs/what-are-the-different-types-of-statuses-for-an-ach-transaction-on-the-synctera-platform-and-how-do-they-relate-to-the-transaction-and-the-network There are two types of statuses regarding an ACH transaction: The **transaction status** and the **network status**. Both of these statuses are reflected in the Platform Transaction view. **Transaction status**: The status of the transaction itself. This can be generally understood as the status as it relates to the Synctera ledger. There are three transaction status types you might see in the Platform when viewing an ACH transaction: * **PENDING**: A pending transaction represents a "hold" or "authorization" for the movement of funds in an account. Pending transactions are used whenever we need to guarantee the availability of funds for any multi-step payment flow. The Account Balance includes the Posted Transactions, whereas Available Balance includes pending debits. This means Available Balance is what can actively be spent right now. * **POSTED**: Posted to the Synctera ledger and reflected in both Account Balance and Available Balance. Once a transaction is "posted", it is then considered immutable and cannot be changed. Any adjustments (such as a reversal, for example) would require the creation of a new transaction. * **DECLINED**: ACH transfer failed transaction checks (fraud limits, watchlist, etc) done while in pending transaction state or failed due to a technical issue. This is a final transaction status. **Network status**: The status of the ACH file itself as it relates to the network. The lifecycle of the file itself has a flow that is represented by the following statuses: * **INIT**: The state used in the ledger while Synctera performs transaction checks, prior to sending out the file to the network. The risk\_info field holds details from Synctera’s fraud service and the payload will return with the result of the checks. If approved, the next network status is PENDING. If declined, the next network status will be DECLINED. * **PENDING**: This means that the ACH file has passed the checks from INIT but has not been sent out to the network. * **COMPLETE**: The ACH file has been sent out to the network. This is a final network status. * **DECLINED**: ACH transfer failed transaction checks (fraud limits, watchlist, etc) done while in INIT network state. This is a final network status. # What are the possible account statuses and what do they mean? Source: https://docs.synctera.com/docs/what-are-the-possible-account-statuses-and-what-do-they-mean The list of account statuses and their descriptions can be found in our API reference here: [listaccounts](/v2/reference/listaccounts) # What are the possible errors I might get when attempting to issue a card for an end-customer? Source: https://docs.synctera.com/docs/what-are-the-possible-errors-i-might-get-when-attempting-to-issue-a-card-for-an-end-customer There are myriad of reasons. The list is always subject to change. In general, HTTP 400-499 are client side errors, that require you to remediate before reattempting the request. 500-599 constitutes server side errors, that can be retried later. # What are the processing times for ACH files? Source: https://docs.synctera.com/docs/what-are-the-processing-times-for-ach-files ACH files are sent during ACH Exchange Windows (https://www.frbservices.org/resources/resource-centers/same-day-ach/fedach-processing-schedule.html). Direct ACH payments typically take several business days to appear in the recipient's account. # What are the validations/verifications that checks are subjected to before they are approved? Source: https://docs.synctera.com/docs/what-are-the-validationsverifications-that-checks-are-subjected-to-before-they-are-approved The check standards are as follows : * Endorsement: "For mobile deposit at \[bank name]" and signed by account owner (if the signature is very clearly not the account owner, the check will not be accepted. Keep in mind we do not match signatures) * Date: \<180days * Picture: Is it clear? There are cases where the picture is not clear, but will still come to us. In that case, we will have to reject. * Made out to one party (not signed over) # What can cause an end customer account to go negative? Source: https://docs.synctera.com/docs/what-can-cause-an-end-customer-account-to-go-negative A force-post or charges that settle for a higher amount than authorized (e.g restaurant bills with a tip) can cause an account to go negative. # What formats are accepted for check deposits? Source: https://docs.synctera.com/docs/what-formats-are-accepted-for-check-deposits PNG, JPEG, and TIFF formats are supported. # What happens if an end customer's account goes into a negative balance and how does Synctera handle such situations? Source: https://docs.synctera.com/docs/what-happens-if-an-end-customers-account-goes-into-a-negative-balance-and-how-does-synctera-handle-such-situations When an account goes into a negative balance this can be due to few typical use cases. 1. When the settlement amount of a transaction is greater than the authorized amount e.g. force post or due to a late return 2. Timing issue when the effective date of a transaction is greater than the posted date of the transaction 3. Stand in Processing - allows for the completion of certain transactions when authorization from the service provider is unavailable 4. Fraud - such as when a customer pulls funds, spends the pulled funds, initiates a return with their external bank resulting in a negative balance For Scenario 1, Synctera will monitor account balances on a daily basis. On the day the negative balance is realized, Synctera will debit your Operational account and hold this money in an Allocated Reserve Suspense Account. We will hold this in suspense to allow you to do one of the following: * Work with the end customer to recover the funds * Determine if the account should be closed or frozen * You can choose to cover the cost If the funds are recovered from the end customer, you should notify Synctera and once the funds are received, Synctera will reverse the entry from the Reserve Suspense account back to the Operational Account. If the funds are unable to be recovered after 7 days\* and/or the account is closed or frozen, the Synctera team will then write this off as a loss against the Operational account. You should monitor your Operational account balance and ensure that it is funded in line with your contractual terms on a daily basis. If the Operational account remains in deficit for 7 days, Synctera will instruct an ACH pull from your Operational account with the Bank. However if the Operational balance falls below 75% it must be topped up within 24 hours. \*exceptions to timeframe may apply # What information is required for an end customer to allow their employer to enable/authorize direct deposit? Source: https://docs.synctera.com/docs/what-information-is-required-for-an-end-customer-to-allow-their-employer-to-enableauthorize-direct-deposit The end-customer needs to obtain a direct deposit form from your corresponding sponsor bank and send it to the employer. The direct deposit form must include: Name, Address, Bank name, Account number, Routing number and Signature # What is a contactless card? Source: https://docs.synctera.com/docs/what-is-a-contactless-card A contactless is any card that has the "Tap feature" enabled, allowing you to make purchases by simply tapping the card at the card terminal. # What is the difference between an authorization and pre-authorization? And what are their hold times? Source: https://docs.synctera.com/docs/what-is-the-difference-between-an-authorization-and-pre-authorization-and-what-are-their-hold-times A pre-authorization is typically used to reserve funds with a reasonable estimate of how much will be cleared. An authorization is when the amount is known. Pre-authorizations are used in situations like Automated Fuel Dispensers (AFD), hotel reservations, car rentals, etc. Authorizations are used to reserve funds for a purchase where the merchant does not capture right away, like buying something on amazon where you authorize the amount of the purchase, then it is captured when it ships. Pre-authorizations can be captured for up to 30 days according to MC network rules. For Authorization, it can be up to 7 days. In the absence of any additional messages from the merchant, the hold will automatically be released after 7 or 30 days depending on what type of hold it is. # What is the full list of information to include for each KYC case type? Source: https://docs.synctera.com/docs/what-is-the-full-list-of-information-to-include-for-each-kyc-case-type Full legal name as it appears on government documents (no nicknames, include all last names if you have multiple, etc.) A valid US address that includes: Street Address Apartment number (if applicable) City State Zip code A valid Social Security Number (SSN) A valid email address A valid phone number # What is the process to reverse a card transaction that has already been created? Source: https://docs.synctera.com/docs/what-is-the-process-to-reverse-a-card-transaction-that-has-already-been-created A posted transaction should be negated by either refunds by the merchant (end-customer takes it up with the merchant) or through a dispute. # What should I do if an end-customer has not received their card shipment in the expected timeframe? Source: https://docs.synctera.com/docs/what-should-i-do-if-an-end-customer-has-not-received-their-card-shipment-in-the-expected-timeframe We encourage you to pass the tracking number onto the end-customer so they can track where the package is. If there is an issue with delivery, you can reach out to Synctera support and we can follow-up with our partner, Arroweye, to check for any updates. # What should I do if an end-customer uploads incorrect external card information to the platform, and Tabapay declines eligibility for AFT/OCT? Source: https://docs.synctera.com/docs/what-should-i-do-if-an-end-customer-uploads-incorrect-external-card-information-to-the-platform-and-tabapay-declines-eligibility-for-aftoct You can delete the card and recreate it with correct info. # What should I do if I find out that an end customer couldn't complete a payment because he was flagged for fraudulent behaviour? Source: https://docs.synctera.com/docs/what-should-i-do-if-i-find-out-that-an-end-customer-couldnt-complete-a-payment-because-he-was-flagged-for-fraudolent-behaviour If an end-customer cannot make a payment, it could be for a number of reasons. If you are contacted about an end-customer unable to make a payment, you can review the Synctera console to determine if it was flagged for fraudulent behavior. If so, please verify the transaction with the end-customer. You can add this verification to the fraud case details, which our Ground Control team will then review. Once a case is marked as not-fraudulent, the end-customer will be able to retry the transaction for a limited period of time. It is important to not reveal why fraud rules get fired, including the amount/threshold. This is important as we do not want to enable fraudsters to bypass our system. # What should we do if our end-customer reports that our routing number is not recognized by a third party? Source: https://docs.synctera.com/docs/what-should-we-do-if-our-end-customer-reports-that-our-routing-number-is-not-recognized-by-a-third-party If a financial institution fails to acknowledge a routing number, it is most likely due to their validation system not utilizing the most recent edition of the Federal Reserve's bank routing directory. The instituion will need to update their records in such cases. The best way to get this routing number updated is by contacting the institution directly as their customer. We recommend that your end-customers use the following template to send over to the financial institutions: *Hi \[Institution],* *I’m attempting to link my bank account through your service, but I’m getting an error message of \[insert error message]*. *It seems like your routing number validation system does not recognize the routing number \[insert routing number here]*. *This routing number is valid according to the Federal Reserve's e-payments routing number [directory](https://www.frbservices.org/EPaymentsDirectory/)*. *Could you please help me escalate this to your banking operations team and get this routing number updated?* *Thank you,* *\[your name here]* # When an end customer's account is frozen/suspended, does that automatically freeze his/her card? Source: https://docs.synctera.com/docs/when-an-end-customers-account-is-frozensuspended-does-that-automatically-freeze-hisher-card It does not auto-suspend the card, but part of authorizing a transaction requires that the end-customer and account be in good standing. You should suspend cards when you wish to fully block all authorizations. # When an end customer's customer status is frozen, does that automatically freeze their accounts? Source: https://docs.synctera.com/docs/when-an-end-customers-customer-status-is-frozen-does-that-automatically-freeze-their-accounts Through the UI, if you freeze an end-customer, their accounts will also be frozen. Using the API you must make separate API calls to freeze the end-customer and each account. You can find more details on freezing accounts in our API guide here: [create-a-personal-customer](/docs/create-a-personal-customer#person-status-attributes) # Which types of transactions are subject to holds and how long do the holds last? Source: https://docs.synctera.com/docs/which-types-of-transactions-are-subject-to-holds-and-how-long-do-the-holds-last Outgoing debit ACHs have a 2 day hold on the funds that have been added to the account on Synctera's platform. Incoming checks have a configurable hold (both the amount of time until the hold expires and the amount of funds that are immediately released vs held are configurable per bank). # Why do ACH files get sent out sometimes even when the account has been frozen and the transaction is still in pending status? Source: https://docs.synctera.com/docs/why-do-ach-files-get-sent-out-sometimes-even-when-the-account-has-been-frozen-and-the-transaction-is-still-pending-status If the file has been sent to the network we are not able to then revoke it - in this case a return has to be issued. If the account is frozen prior to the file being sent out, then the transaction can be canceled, but if after, it would have to be handled as a return.If the file has been sent to the network we are not able to then revoke it - in this case a return has to be issued. If the account is frozen prior to the file being sent out, then the transaction can be canceled, but if after, it would have to be handled as a return. # Why do I sometimes not see a network status on ACH transactions? Source: https://docs.synctera.com/docs/why-do-i-sometimes-not-see-a-network-status-on-ach-transactions For Incoming Credits/Debits, a network status will not be trackable. This is because Synctera is not the originator of the transaction so we do not have visibility into the status as it pertains to the file’s state in the network. # Why was our wire returned? Source: https://docs.synctera.com/docs/why-was-our-wire-returned You can view the reason for why the wire was returned in the Synctera console under the specific wire transaction. There will a banner on the left side that will state the reason. # Why would an end customer's account balance be different than the available balance? Source: https://docs.synctera.com/docs/why-would-an-end-customers-account-balance-be-different-than-the-available-balance Account Balance is impacted only by posted transactions, but Available Balance is also impacted by pending transactions. Until a hold is fully posted, only the Available Balance is decreased by the amount of the hold. The Available Balance and the Account Balance can both be negative. # Simulate balance inquiry Source: https://docs.synctera.com/v2/reference/simulatebalanceinquiry openapi-v2.json post /cards/transaction_simulations/financial/balance_inquiry Simulate a `pindebit.balanceinquiry` type transaction by sending a POST request to the `/simulate/financial/balanceinquiry` endpoint. # Create a cash deposit transaction simulation for a barcode Source: https://docs.synctera.com/v2/reference/simulatebarcodesdeposits openapi-v1.json post /cash/transaction_simulations/barcodes/deposits > ⚠️ Sandbox Only > This simulation endpoint is only available in sandbox environments and will not be available in production. Create a cash deposit transaction simulation for a barcode # Retrieve Store Information for Barcode Simulation Source: https://docs.synctera.com/v2/reference/simulatebarcodesstores openapi-v1.json get /cash/transaction_simulations/barcodes/stores > ⚠️ Sandbox Only > This simulation endpoint is only available in sandbox environments and will not be available in production. Retrieve store information for a barcode transaction simulation # Simulate clearing or refund Source: https://docs.synctera.com/v2/reference/simulateclearing openapi-v2.json post /cards/transaction_simulations/clearing Simulate an `authorization.clearing` type transaction by including the `original_transaction_token` and `amount` in your request. To simulate a refund type transaction, set the `is_refund` field to true. # Simulate a network dispute action Source: https://docs.synctera.com/v2/reference/simulatedisputeaction openapi-v2.json post /disputes/simulations/{dispute_id}/actions > 🚧 Beta > This is a Beta endpoint. Feedback from the community is welcome. Any breaking changes to this endpoint will be pre-announced. This endpoint is intended for use only in the testing environment to simulate a network action on a dispute. # Simulate financial Source: https://docs.synctera.com/v2/reference/simulatefinancial openapi-v2.json post /cards/transaction_simulations/financial A "financial" is a transaction message class that includes ATM transactions, PIN-debit transactions, and balance inquiries. Simulate a `pindebit` type transaction by including the `card_token` and `amount` in your request. # Simulate financial advice Source: https://docs.synctera.com/v2/reference/simulatefinancialadvice openapi-v2.json post /cards/transaction_simulations/financial/advice Simulate a financial advice by including the `original_transaction_token` and other authorization details in JSON format in the body of the request. # Simulate L2l3 Source: https://docs.synctera.com/v2/reference/simulatel2l3 openapi-v2.json post /cards/transaction_simulations/clearing/l2l3 > 🚧 Alpha > This is a Alpha endpoint. Feedback from the community is welcome. We may make breaking changes to this endpoint. Simulate a l2l3 type transaction by including the original_transaction_id and enhanced data in your request. L2L3 events enhance the data of a transaction with the `l2l3` details from your request. # Simulate OCT Source: https://docs.synctera.com/v2/reference/simulateoriginalcredit openapi-v2.json post /cards/transaction_simulations/financial/original_credit This Original Credit Transaction (OCT) enables the cardholder to receive funds on the specified card from an external source via the card network. Use this endpoint to simulate a transaction that is similar to a wire transfer and not linked to any purchase. Simulate an OCT by including the `card_token`, `amount`, `mid`, and `type` in your request. # Simulate reversal Source: https://docs.synctera.com/v2/reference/simulatereversal openapi-v2.json post /cards/transaction_simulations/reversal A reversal releases the hold that was placed on account funds by an authorization, thus returning the funds to the account. Simulate an `authorization.reversal` type transaction by including the `original_transaction_token` and `amount` in your request. # Simulate ATM withdrawal Source: https://docs.synctera.com/v2/reference/simulatewithdrawal openapi-v2.json post /cards/transaction_simulations/financial/withdrawal Simulate a `pindebit.atm.withdrawal` type transaction by including the `card_token` and `amount` in your request. # Account linking Source: https://docs.synctera.com/docs/account-linking-products Verify account ownership, identity and account balance when funding new accounts ## Synctera External Account Verification Before funding a new FinTech account via an electronic ACH payment, National Automated Clearing House Association (NACHA) rules require that accounts must be validated for ownership and use prior to processing the debit transaction. Synctera External Account Verification makes it easy for FinTechs to verify external accounts and comply with NACHA rules. ### Benefits **Increase conversion rates:** A seamless experience embedded directly within your app’s flow makes it easy for customers to instantly verify the account **Full visibility:** Track the verification status and view the external accounts customers used for funding **Reduce fraud:** Verify account ownership and identity for all external accounts as part of the customer signup and initial funding process **Remain compliant:** Streamline NACHA compliance to ensure ongoing access to the ACH payment network **Reduce payment errors:** Prevent misdirected and failed payments by ensuring payments are set up correctly and the external account has sufficient funds ### How it works With Synctera External Account Verification, the verification process is streamlined, automating the sequence of steps required to remain compliant and allowing you to easily track the verification status. 1. Validate the external account exists and can be used for ACH payments 2. To help reduce fraud, verify that the account owner information matches the information on file for the customer (if using [Synctera External Account Verification - Identity](/docs/account-linking-products#synctera-external-account-verification-identity)) 3. Confirm that the external account has sufficient funds 4. Create a record of customer information, external funding source, and proof of verification 5. Enforce mandatory re-linking if users update password or add multi-factor authentication criteria ## Synctera External Account Verification - Identity **Use account owner information for linked external accounts to verify customer identities** When you allow your customers to fund their accounts with you from external sources, you will want to take steps to verify that the customer actually owns the external account, and to verify that they are not using a fraudulent identity with you. Synctera External Account Verification - Identity can help prevent fraud and reduce account takeovers by comparing account owner information for linked external accounts to the information the customer gives you. It can help reduce failed, fraudulent, or invalid ACH transfers to and from an external account. In cases where fraud does occur, the account owner information provides an audit trail. NACHA recommends including the external account holder name in your ACH file to help reduce returns due to incorrectly entered account numbers. In cases when an ACH is sent to an external account for which the account number was incorrectly entered, the receiving bank will be able to reduce delays in crediting or debiting the account by using the customer name to match the transaction. ### Benefits * Reduce fraud and help prevent account takeovers: identity data can be used to help prevent an account takeover (ATO) or other transaction fraud, either during onboarding or when the source of funds is switched * Help determine when secondary security features like text message verification should be triggered Example of using Synctera External Account Verification - Identity to trigger secondary security features If a user tries to link an external account but the identity information for that account doesn't match what the user has provided you, you can send a text message to the phone number tied to the external account, or send an email to the address tied to the external account. This helps you confirm it's really the account owner linking the account, and not someone who has stolen their credentials. * Use to personalize forms for onboarding: auto-fill forms with identity data when users link their bank account * Provide a seamless customer experience and help customers link their accounts and start transacting with you faster ### Key features * Performs a check to get the name(s), email(s), address(es), and phone number(s) of the account owner of an external account, and compares the data to what is in the Synctera system in real time * Cannot be used on external accounts verified through microdeposits ## Synctera External Account Transactions **Access detailed transaction history for external accounts** Get up to 24 months of transaction history for external accounts. At your discretion, Synctera partners with either Finicity or Plaid to provide this product. ### Benefits Helps to deliver a seamless in-app experience. Allows your customers to monitor their external bank accounts without leaving your app. Allows you to support personal financial management tools. Allows you to understand customer spending patterns and mitigate risk. ### Key features For ongoing transaction history updates, Finicity updates this information nightly. Plaid updates it 4-6 times per day.  Plaid also supports on-demand transaction history refreshes. A user can refresh their transaction history to see if the transaction went through and is appearing in their history. Finicity also allows you to retrieve up to 24 months of historical statements for an external account in PDF format. Use this functionality to verify length of account history, historical balances, and account ownership. Cannot be used on external accounts verified through microdeposits. # Account management Source: https://docs.synctera.com/docs/account-management-products Our proprietary, flexible ledger serves as the operating infrastructure and single source of truth for your customer, account, and transaction data ## Synctera Ledger As the single source of truth, a ledger is a fundamental component of the technology stack for your bank-supported financial product or FinTech app. Most banks and FinTechs manage their accounting processes on inflexible banking systems or basic accounting programs—or they may not have a ledger at all. As a result, related processes like reconciliation can be highly manual and time-consuming. Building a ledger from scratch is complex and can take upwards of a year to complete, while out-of-the-box solutions can be expensive and may require customization. Designed specifically to for bank-supported financial products or FinTech apps, Synctera Ledger is a reliable, flexible, cost- effective alternative, serving as the operating infrastructure and book of record for customer, account, and transaction data. ### Benefits **No core integration required:** Our lightweight platform removes the complexity and costs associated with integrating into the bank’s core system **Complete transparency:** You and your bank partner can gain real-time visibility into your transactions and track the performance of the product(s) they are supporting **Easy reconciliation:** Access transaction information and automate workflows to simplify daily reconciliation processes **Cost-effective:** Compared to other options in the market, we offer the enterprise-grade capabilities that you need at an attractive price point **Accelerate time to market:** Get up and running quickly with easy API integration and system configuration **Ensure the health of your business:** Track your P\&L and account balances to better understand and report on your current position **Streamline operations:** Enable onboarding, support, and operations teams with the data they need to solve issues, serve customers, and reduce manual processes **Flexible:** Build your user interface flow without having to worry about back-end system orchestration ### Key features **Account creation:** Open customer accounts using a template, including valid account and routing numbers that are recognized by other banks and networks **FinTech ledger positions:** Track, display, and post balances across the lead ledger, sub-ledger, and general ledger **Statements:** Provide required data to generate account statements **Partner maintenance:** Define and maintain the relationship with your partner bank, including account setup **Transaction types:** Define transaction types to be posted against the ledger account, including ACH, P2P, internal transfers, and card transactions **Overdraft limits:** Define, assign and track overdraft limits at the customer or account level **Fees and pricing:** Charge fees and calculate interest **Virtual accounts:** Create virtual accounts to support various use cases, such as budgeting **Alerts:** Configure customer notifications for a range of ledger-related activities **Product templates:** Define and configure the features and constraints of a base product **Account lifecycle management:** Change, freeze, and close customer accounts, as required **Account balances:** Track debits and credits and calculate account balances **Operational account management:** Manage your operational account details **Reporting:** Track product health and other key operational metrics **Always-on data:** Engage in real-time with no batch windows, including next-day analytics and AML transaction monitoring ## Synctera Transaction Data Enhancement **Cleanse and enrich transaction data to give you and your customers better understanding and insights** Raw transaction data - such as merchant data for card transactions - is often incomplete and hard to understand. Synctera Transaction Data Enhancement cleanses and enriches financial transaction data to help your customers better understand and manage their spending. It also allows you to glean more customer insights from transaction data.  ### Benefits **Enhance customer experience:** Provide detailed, easy to understand transaction data to your customers so that they can quickly see what they purchased, when, and from where. Use classification categories to deliver relevant insights to your customers and power tools that allow them to better assess and manage their spending. **Gain customer insights:** Get a clear view of your customer's financial behaviors, and learn where and how they spend and manage their finances. **Inform marketing strategy:** Develop accurate customer segments and profiles, identify new areas of investment, and engage customers with relevant products and services. ### Key features * Supplements data from your card processor * Uses machine learning technologies and thousands of custom rules to clean and categorize transaction data, translating transactions and assigning relevant merchant data such as logos and location # Account Agreements and Disclosures Source: https://docs.synctera.com/docs/accountagreementsanddisclosures This guide captures the requirements for account agreements and disclosures. **Note your Sponsor Bank may have additional bank-specific requirements to comply with its bank policy. These will be covered during your implementation and final approval. *The below sections are intended as guidance and not legal advice.*** As with any program that offers banking products or services, Synctera’s bank partners require that certain disclosures and agreements be made available, and consented to, during the customer acquisition process. There are a few principles that must be followed for how these disclosures are presented and how a customer consents to them. Primarily, disclosures and agreements must be - * Clearly and conspicuously available, providing the customer a reasonable opportunity to review; * In a form the customer may keep; * In a form in which the customer is able to indicate clear and unequivocal acceptance. ## Consent to Electronic Disclosures (E-Sign) This establishes your ability to provide all disclosures and account information electronically through your platform. In terms of the overall flow of account opening, this should be the first disclosure a consumer views and consents to before moving forward in the customer acquisition process. * A customer must consent to this disclosure before you can share and receive consent for other disclosures with them electronically (such as the account agreement) * Synctera has provided a template for E-Sign consent ## Privacy At account opening, businesses offering financial products must provide consumers with a Privacy Notice explaining their privacy policies and practices. **Privacy Notices must be re-sent at least annually to consumers.** * This includes what information is collected, how it is used and shared, and how it is protected, as well as a statement of rights to opt out of certain types of sharing * Privacy disclosures must be clear, conspicuous, and in a language an average person can readily understand. * Synctera has provided several templates, which fintechs can select depending on their privacy practices. * Sponsor Bank Privacy Notice must also be included ## Terms of Service These are the general terms of service that apply to your platform. * This agreement is between your company and the customer, and it should not include banking terms and conditions. ## Deposit Account Agreement These terms govern the use of your deposit product * This agreement is between the sponsor bank and your end customer * Deposit account agreements should establish a contractual relationship between your bank and your end customer to open up a checking / savings account * Synctera or Sponsor Bank provides a template for deposit agreements * Interest-bearing products must also include a disclosure of the effective interest rate (particularly if it will change) ## Other Product Agreements Other product terms and conditions or agreements may exist depending on the product and services being offered. As an example, this may include a cardholder agreement or a secured deposit account agreement. ## Patriot Act KYC Notice This is a notice that explains the Sponsor Bank’s obligations under the USA Patriot Act. * This notice is required for consumer-oriented products and services, i.e. not any type of business account although separate language may be provided to business accounts. * Consent is not needed, but this notice should be displayed when gathering customer data for verification. # Accounts Source: https://docs.synctera.com/docs/accounts-for-fintechs The Accounts tab of the Synctera Console allows you to view all of your customers' accounts in one place, and to search among your customers' accounts. ## Overview Your operations team can use the Accounts tab to help them address customer service inquiries and fraud/AML investigations.  You can use the [Admin tab](/docs/permissions) to add/remove users from the list of those who can view/edit accounts. ## Accounts tab home page Search for accounts by account number, customer first name, or customer last name.  Filter accounts by account purpose or status. Click on an individual account to view more information. ## Information displayed after clicking on an individual account Account type: Saving, Checking, Line of Credit * For a Product that has fees, the types of fees can be: * Monthly, Annual, ATM\_Withdrawal, Overdraft, ACH, Wire * Currently Fintech is calculating Fees and using Synctera to post it. * For a product that has Interest rates: * You can mention Interest rate * Interest rate history is maintained so that based on the interest rate for a particular period, the respective interest rate will be calculated daily and applied monthly Account status Account balance Available balance Account owner Creation date Employees who have edit access to account data can: * Open an account for the user - by emulating the FinTech if the user has the permissions to do so * Change the overdraft limit on an account * Freeze / Unfreeze an account * Send funds to another account if the user has passed KYC * Receive funds from another account * Initiate ACH external transfer if the user has passed KYC Employees who have view access to account data can perform following activities specific to External accounts: * View the external accounts of a customer Employees who have edit access to account data can perform following activities specific to External accounts: * Link an external account to the user by providing Routing Number and other details of the account. ### Transactions sub-tab View the most recent pending, posted, and declined transactions.  Click on an individual transaction to view more information about that transaction. ### Cards sub-tab View the cards that have been issued to the account. You can issue a new physical/virtual card or re-issue a card. ### Details sub-tab Account purpose Bank ID Partner ID  Bank routing number ### Spend monitoring sub-tab The Spend Monitoring feature is described [here](/docs/spend-monitoring). # ACH transaction disputes Source: https://docs.synctera.com/docs/ach-transaction-dispute-cases This guide explains the ACH dispute process, how to initiate, manage and monitor until the dispute is resolved. \[Documentation coming soon] # Adding Sole Proprietorship Source: https://docs.synctera.com/docs/adding-sole-proprietorship This document is intended to list the general requirements from a product and risk and compliance perspective needed to begin supporting sole proprietors in your existing Business onboarding and accounts program with Synctera. ## Adding Sole Proprietorship to a Business Use Case ### Product If a user is using their account for commercial purposes, they are considered a Sole Proprietor. In this case they would be added as a person to the platform, using the [Create Person API](/v2/reference/createperson). Then they would add their business, with [Create Business](/v2/reference/createbusiness), and indicate that the **structure** is a **sole\_proprietorship**, and leave EIN empty ([unless the sole proprietorship has employees - see Risk and Compliance section](/docs/adding-sole-proprietorship#risk-and-compliance)). Then, the ownership of the business would have to be defined using the [Relationship API](/v2/reference/createrelationship) (Beneficial Owner Of). *the verifications API will **KYC** the owner of the sole proprietorship, and this will count as the result of the KYB as well.* ### Risk and Compliance If adding this use case as a net new request, please see our [Change Management Process](/docs/change-management-1). You will need to follow the steps outlined and fill out the form to ensure the correct documentation is passed to and approved by your sponsor bank. ### Commonly Asked Questions: Yes - although if the sole proprietor has employees, an EIN will need to be provided. See this documentation for details: [https://www.irs.gov/faqs/small-business-self-employed-other-business/form-ss-4-and-employer-identification-number-ein/form-ss-4-employer-identification-number-ein-1](https://www.irs.gov/faqs/small-business-self-employed-other-business/form-ss-4-and-employer-identification-number-ein/form-ss-4-employer-identification-number-ein-1) This may vary depending on the results of the KYC run, the state the sole prop is operating in, and how the business is structured. In addition, whether or not the sole prop has a DBA or fictitious name filed or not will impact what documentation the sole prop has been legally required to file and hence what documentation is available for them to provide. You will need to become familiar with state laws and regulations when reaching out to a customer to obtain additional documentation. If you are using Ground Control, our team will provide you with assistance in determining what documentation is needed for a final decision on the KYC. While a Sole proprietor will be onboarded in most cases with an SSN and verification will occur on the KYC level, rather than the KYB level, it is required to open a business account, rather than a consumer account, since the individual is using the account for commercial purposes. You will not need to include any net new policies, procedures or disclosures when adding support for sole proprietors to your existing business program. Generally speaking, sole proprietorships carry similar risk to other businesses, but when adding a new feature we recommend re-reviewing your **Risk Assessments** to ensure they reflect any increased risk that may come with adding sole prop support. **Account agreements** may need to be revisited to include language regarding any requirements from a general or state level for a sole proprietor to open an account. *This may vary depending on your use case, so please consult with the Synctera Risk and Compliance team if you have any questions about whether or not you should be updating your existing Risk Assessments or Account Agreements.* # Address Verification Service (AVS) Source: https://docs.synctera.com/docs/address-verification-service-avs Address Verification Service (AVS) is a method provided by issuers to help merchants detect potential card transaction fraud, especially for card-not-present (CNP) transactions (for example, online transactions). ## Overview ### What is AVS and how does it work? AVS is performed as part of the merchant's request for authorization of the transaction - a typical flow: * During checkout, customer enters their card billing address * As part of the transaction authorization request, this address is compared to the customer's address on file with the issuer * The AVS match response is sent back to the merchant as part of the authorization response - this could be a match, a partial match, a mismatch or validation not performed / data not present * Based on the response, the merchant either decides to accept or reject the transaction Other fraud detection methods AVS is one of several methods for detecting card transaction fraud. Examples of other methods are CVV validation and 3D Secure authentication. ### Synctera AVS Typically, a single address is used for AVS, which can cause friction for FinTechs that want to allow customers to have multiple billing/shipping addresses. With only one address used for AVS, legitimate transactions sometimes get declined due to AVS mismatch, resulting in bad user experience. An example is where customers onboards entering their home address, but the card is registered with the company's address as the billing/shipping address. With Synctera AVS, customers are allowed to add multiple addresses to their profile, rather than just a single address, for AVS. The main **benefits** of Synctera AVS include: * Increased transaction acceptance, which also means increased revenue * Improved user experience with less friction / declines during card usage, especially for online and other card-not-present purchases ## Implementation details Synctera AVS is enabled for all FinTechs. Multiple addresses can be stored on the customer's profile and used for AVS. #### New decline reason A new [decline reason](/docs/card-transactions#declined-transactions), `ADDRESS_VERIFICATION_FAILED`, is added for Synctera AVS. FinTechs may want to map to this decline reason in their UI. #### AVS in the Synctera Console In case of an AVS decline, the decline reason - *Address verification failed* - is shown on the declined transaction in the Synctera Console. AVS results are shown on the *Address verification* tab. #### AVS in the Transactions API AVS results are shown in the `user_data.address_verification` object of the Transactions API. The example below is from a [Get Pending Transaction](/v2/reference/getpendingtransactionbyid) response for a transaction that was declined due to AVS mismatch (the response for an authorized and cleared transaction would be listed under [Get Posted Transaction](/v2/reference/getpostedtransactionbyid)). ```json JSON theme={"system"} { "account_id": "7d943c51-e4ff-4e57-9558-08cab6b963c7", "account_no": "string", "created": "2024-06-20T14:06:34.970Z", "data": { "amount": 0, "...": "...", "history": [ { "...": "..." } ], "idemkey": "3ae35b74-fa4c-472e-bd8d-a61b98c07d9e", "memo": "", "network": "marqeta", "operation": "hold_decline", "reason": "ADDRESS_VERIFICATION_FAILED", "req_amount": 0, "risk_info": null, "status": "DECLINED", "subtype": "pos_purchase", "total_amount": 1000, "transaction_time": "2024-06-17T20:18:20Z", "type": "card", "user_data": { "...": "...", "address_verification": { "on_file": { "postal_code": "233120", "street_address": "116" }, "request": { "postal_code": "111101 ", "street_address": " " }, "response": { "additional_information": "Failed using address 58dde53c-27bf-4848-be01-9f80f91102bb", "memo": "postal code NO_MATCH, street address NO_DATA" } } } } } ``` # AML Cases Source: https://docs.synctera.com/docs/aml-cases ## Overview Synctera's AML transaction monitoring detects potentially unusual activity based on preconfigured rules that align with the bank's risk appetite and policies. When an abnormality is identified, the Synctera Console automatically generates AML cases for manual review. This feature also provides an audit trail to document all tasks associated with the AML alert outcomes. ### Data displayed in the AML case The AML case includes customer data, alerted rules, associated transactions, related cases, history, notes, and documentation. #### Customer This displays information about the customer. Click on the "View Customer" link to access full customer details. #### Rules This section displays the details of the rule/s that detected the activity. It includes the rule name, description, detection reason, and date. #### Transactions This section summarizes alerted activity, including the amount, type, and date. To view a transaction in more detail, select it or click on "View Transactions." #### Related Cases and History These options show related cases, which are historical cases linked to the same customer and history, including all status transitions of the AML case. #### Case assignment, notes, and document upload The AML case allows adding an assignee, entering notes, and providing supporting documentation to resolve the case review. [Assignees](/docs/get-ready-for-synctera-cases) receive email notifications regarding case activity and are used to request additional information from the Company and to notify the Bank of any escalations. ### Reviewing AML cases #### Mark case as In Review This feature allows a user to move a case from the New state, indicating to reviewers that it has been initially assessed and is under review, even if a final decision is pending. This distinction helps differentiate between newly created cases and those either undergoing an investigation or awaiting additional information before reaching a final resolution. #### Close Case or Mark Escalated Based on the investigation results, decide whether to close the AML case due to expected activity or escalate it to the Bank. # App store submissions Source: https://docs.synctera.com/docs/app-stores App stores are the primary means to get your app or product into the hands of your customers. Each app store has its own rules and guidelines for submission, as well as opportunities for marketing, exposure and customer engagement. ## General guidelines and considerations Here are some considerations that might not be immediately apparent, but require some thought and planning in advance: * App store product page content * App store product page screenshots and/or videos * App store Icons for your app * Keywords for SEO * Content and screenshots for each of the supported languages for your FinTech * Support for any customer feedback (some stores allow a response to any feedback) ## Apple App Store steps ### 1. Sign up for the Apple Developer Program * Go to this [link](https://developer.apple.com/programs/) and click on ‘Enroll’ in the top right corner * There is a cost attached (\~\$100) for this one year membership, however it will provide you with a number of helpful tools including the following. See [here](https://developer.apple.com/programs/whats-included/) for full list * Access to submit apps to App Stores on all Apple platforms * Access to [App Store Connect](https://appstoreconnect.apple.com/login), the management portal for the App Store * Testing tools like TestFlight (allows for a ‘Beta’ limited-release app) * Two free technical support events from Apple’s support engineers / year * App analytics ### 2. Prepare app for submission * Guidelines: Ensure that your App follows all of Apple’s App Store guidelines. We have summarized these below but please also refer to Apple’s complete guide [here](https://developer.apple.com/app-store/review/guidelines/). While the guidelines are pragmatic and somewhat predictable, we still advise that you review them to ensure that your App does not fail its Certification * The App will need to go through an App Certification Process, where a tester tests your App to ensure that it follows each guideline * Bug Testing: Ensure that the App is bug-free and crash-free. Try to test under strenuous conditions, such as low network connectivity, low storage conditions, older devices, etc. Essentially try to break the App! * Note: This can be done internally or externally, with Friends and Family. TestFlight, as mentioned above, can be used for a ‘Beta’ limited-release, where a gated version of the App is released for your network to help test * Synctera Requirements: Please ensure that you have completed all [Synctera Launch Checklist](/docs/fintech-launch-checklist) items for your initial launch * During Sign-Up, you will need to provide a URL link to your Privacy Policy. Please ensure that the version provided has been approved by our Compliance team and your Sponsor Bank ### 3. Complete [App Store Connect](https://appstoreconnect.apple.com/login) sign-up * Accept agreements, and enter tax and banking information * Add users and assign roles ### 4. Add your app to [App Store Connect](https://appstoreconnect.apple.com/login); upload build * From ‘My Apps’, click on the ‘Add’ button (+) in the top-left corner * ‘User Access’ refers to the roles that you have created for your team within App Store Connect * Click ‘Create’ and look for messages that indicate missing information * After you’ve added an App to your account, you can upload a build with one or several upload tools. The first time you upload a build, a beta version of the app is created in your account. However, the build needs to be processed in Apple’s system before it appears in App Store Connect. You’ll receive an email when this process is complete * Add your App icon, preview and screenshots * See [here](https://help.apple.com/app-store-connect/#/dev2cd126805) and [here](https://help.apple.com/app-store-connect/#/dev82a6a9d79) for additional detail ### 5. Test your app within TestFlight; address tester feedback * TestFlight beta testing allows you to distribute beta builds of your App to testers to collect final feedback. Only people explicitly invited will be able to test your App * Once a build is uploaded, it will be available for testing for a period of your choice, up to 90 days * Work with your technical team as well as Synctera’s InfoSec and Developer Relations teams (if necessary) to address tester feedback * See [here](https://help.apple.com/app-store-connect/#/devdc42b26b8) for additional detail ### 6. Publish your app to the App Store * Once you have completed the testing phase and have addressed all feedback, you are ready to publish your App to the App Store! The general workflow is: * Choose the build from your account that you wish to submit for review * Before you can submit an app, you’ll need to provide required metadata and choose the build for the version. * Builds for each platform can be submitted separately and the status of one platform’s build doesn’t affect the others. * Set pricing and availability * Submit your App for review * On average, 90% of submissions are reviewed in [less than 24 hours](https://developer.apple.com/app-store/review/#:~:text=On%20average%2C%2090%25%20of%20submissions,app%20for%20iPhone%20and%20iPad.) * Request promo codes * Allows for the limited distribution of your App to users before the App is available on the App Store. The way you distribute these codes is up to you * View your App status and resolve any review issues * [Reply to App Review messages](https://help.apple.com/app-store-connect/#/dev7f7f86006) * On average, 40% of unresolved issues are related to [App Completeness](https://developer.apple.com/app-store/review/#:~:text=On%20average%2C%2090%25%20of%20submissions,app%20for%20iPhone%20and%20iPad.), which covers things such as bugs, crashes, broken links, placeholder consent, incomplete info, privacy policy issues, unclear data access requests, inaccurate screenshots, substandard UI, misleading users, or submission by an incorrect entity * Approval! * Once your app is approved, it can take up to 24 hours to go live on the App Store ### 7. Ongoing app maintenance * [Measure App performance](https://help.apple.com/app-store-connect/#/dev5340bf481): App analytics, sales and trends, customer reviews, payments and financial reports * Download catalog reports * Create a new version * Change pricing and availability * Remove an App (if necessary) ### 8. Configure App Store features * [Manage agreements, tax and banking](https://help.apple.com/app-store-connect/#/devb6df5ee51) * [Receiving payment from Apple for proceeds for your App](https://help.apple.com/app-store-connect/#/dev6a92b6d7b) * App bundles / promo codes / in-app events / offer in-app purchases / configure game centre ## Google Play app store steps Many of the qualitative steps outlined in the Apple App Store section will apply for Google Play, e.g. preparing application for submission and ongoing application management. ### 1. Set up your [Google Developer Account](https://support.google.com/googleplay/android-developer/topic/7072535?hl=en\&ref_topic=16285)- Registration, payment methods and receipts * Add users and manage permissions * Create and manage your Account Group * Create or update your developer page ### 2. Review and adhere to submission requirements * End User Agreement * Privacy Policy * [Google Developer Policies](https://play.google.com/about/developer-content-policy/) * Technical requirements * [Prepare your App for review](https://support.google.com/googleplay/android-developer/answer/9859455) ### 3. Create and set up your App on the [Google Console](https://support.google.com/googleplay/android-developer/answer/9859152?hl=en\&ref_topic=7072031)- The Android App Bundle is the publishing format on Google Play. Publishing using app bundles helps to reduce the size of your app, simplify releases, and enable advanced distribution features * Using the app bundle explorer in Play Console, you can easily manage your app bundles and versions in one place. You can also access useful metadata, downloads, and insight into what Google Play generates for asset delivery. * Google Play uses app bundles to build and deliver APKs that are optimized for each device configuration, providing users with more efficient apps. This means you only need to build, sign, and upload a single app bundle to support optimized APKs for a wide variety of device configurations. Google Play then manages and serves your app's distribution APKs for you. * Key aspects: * Set up your App * Manage your App and App Bundles * Set up your store listing and settings * [Optimize your store listing with experiments](https://support.google.com/googleplay/android-developer/answer/12053285?visit_id=637974874496332729-2529813739\&rd=2) * [Inspect app versions with the app bundle explorer](https://support.google.com/googleplay/android-developer/answer/9844279?hl=en\&ref_topic=7072031) * [Use Play App Signing](https://support.google.com/googleplay/android-developer/answer/9842756?hl=en\&ref_topic=7072031) (enables Google to manage and protect your App’s signing key) ### 4. Publish a draft of your app * When you're ready to publish a draft app, you'll need to [roll out a release](https://support.google.com/googleplay/android-developer/answer/9859348#rollout). At the end of the release process, clicking Release will also publish your app * In certain instances, Google will take more time to thoroughly review your app * While the average review time is roughly two days, exceptional cases may result in review times of up to seven days or longer * Release Options: You may choose open testing (all), closed testing (limited number of external testers that you choose), internal testing (internal up to 100 testers), or full production * With a release, you can manage your App’s Android App Bundle and then roll out your App to a specific group of users * Once the App is reviewed, you will receive a notification on the Google Console Dashboard ### 5. Test your app * As mentioned above,  essentially try to break the App! Try to test under strenuous conditions, such as low network connectivity, low storage conditions, older devices, etc. * [Use a pre-launch report to identify issues](https://support.google.com/googleplay/android-developer/answer/9842757?hl=en\&ref_topic=7071528) * [Analyze statistics](https://support.google.com/googleplay/android-developer/topic/3450942?hl=en\&ref_topic=7071528) ### 6. List the app on the Google Play Store * Once you are satisfied with what feedback/changes, follow the following steps to release an additional version to either a further external group or full production launch: * Go to ‘App Releases’ section on left panel of Google Play Console * Choose ‘Manage (Production/Beta/Alpha)’ * Click on ‘Edit Release’ * Upload an App Bundle * Click on ‘Review’ to confirm the changes and send your app to the review by pressing ‘Start rollout to production’ * Once the App is reviewed, you will receive a notification on the Google Console Dashboard * Additional Notes: * To publish updates, work with your account owner to decide which of the following permissions you need to release to production/testing * Complete an App rating questionnaire (helps avoid being marked as ‘Unrated’, which could lead to app removal) * Able to find this on the top-left menu * Price the App * Product description * Screenshots ## Additional guidelines and resources [US Operating System Market Share (statscounter website)](https://gs.statcounter.com/os-market-share/all/united-states-of-america) ### Apple app store [App Store review guidelines](https://developer.apple.com/app-store/review/guidelines/) [App store product page guidelines](https://developer.apple.com/app-store/product-page/) [App store privacy practices and disclosures](https://developer.apple.com/app-store/app-privacy-details/) [General content](https://developer.apple.com/app-store/) ### Google Play store [Release overview](https://play.google.com/console/about/releasewithconfidence/) # Back office Source: https://docs.synctera.com/docs/back-office-products Achieve compliance and fight money laundering ## Synctera Anti-Money Laundering (AML) With an estimated [$800 million - $2 trillion](https://www.unodc.org/unodc/en/money-laundering/overview.html) laundered by criminals globally each year, money laundering is a serious concern for both FinTechs and their bank partners. Bank Secrecy Act (BSA) and anti-money laundering (AML) regulations aim to make it difficult for criminals to launder funds derived from criminal activities. To comply with these regulations, FinTechs and their bank partners must deploy a range of procedures, including monitoring transactions and reporting on suspicious activity. Failure to adequately do so can result in serious reputational damage for the FinTech and its bank partner, and regulatory fines for the bank partner. ### Benefits Synctera Anti-Money Laundering (AML) helps prevent and detect money laundering by enabling FinTechs to streamline AML programs with their bank partners, from AML checks and transaction monitoring to case management and report filing. **Remain compliant:** Ensure you fulfill your obligations with respect to AML regulations. **Manage risk:** Protect yourself and your bank partner by mitigating exposure to regulatory and reputational risk. **Increase operational efficiency:** Automate and streamline AML workflows. **Complete transparency:** You and your bank partner both have full visibility into all AML investigations and related actions across your customer base. **Scalable:** Our enterprise solution supports AML compliance as you scale. ### Key features **Configurable rules:** Define granular AML monitoring rules to meet the unique needs of both you and your bank partner **Cases:** A case workflow helps facilitate further investigation for any alerts **AML checks:** Automatically perform AML checks on your customers and accounts **Configurable workflow:** Define each step of the operational workflow, including users, permissions, escalations and scheduling **Alerts:** Notify the correct contact at your partner bank by email when a new AML case is created **Transaction monitoring:** Automatically screen transactions for suspicious activity **Suspicious Activity Reports (SARs):** As an AML regulatory requirement, submit SARs to the Financial Crimes Enforcement Network (FinCEN) ### How it works 1. You and your bank partner collaborate with Synctera to configure the appropriate AML monitoring rules and operational workflow according to your bank partner’s risk appetite and policies 2. Synctera aggregates customer, account, and transaction data and automatically sends a daily AML file to our AML partner for processing 3. Our partner’s platform automatically executes AML checks based on pre-defined rules and thresholds 4. When further investigation is required, a case is automatically created in the Synctera platform for review and action by your bank partner 5. The pre-defined AML analyst at your bank partner is notified by email when a new case is created and assigned 6. The AML analyst investigates and then sends to the bank’s AML officer for final review 7. The bank’s AML officer reviews the escalated cases and, if required, submits a SAR ## Synctera Cases **Manage compliance and operations in a fully-featured case management system** Managing compliance tasks as well as day-to-day interactions with your bank partner by email, shared drives, and spreadsheets is time-consuming and prone to human error. It also leaves a cumbersome audit trail for regulatory compliance and risk management purposes. With Synctera Cases, both you and your bank partner can oversee all interactions between you, your bank partner, and your customers from the Cases tab of the Synctera Console. Our case management solution also serves as a support portal where you and your bank partner can monitor questions, errors, and issues that arise. ### Benefits **Reduce manual work and human error:** Eliminate emails and manual tracking of bank and end-customer interactions with automated workflows, configurable assignments, and role-specific views/permissions. **Streamline and accelerate operations:** A centralized framework for creating, approving and resolving cases makes it easier for staff to manage a range of day-to-day customer onboarding, support, and compliance processes. **Gauge the health of your bank partnership:** Gain visibility across all types of interactions between you and your bank partner - at the user, account, and transaction level. **Maintain a clean audit trail:** Record all tasks associated with the partnership, including approvals for materials subject to Reg DD, UDAAP, privacy regulations, and more. ### Key features Stay engaged and take action on a range of cases, including: #### Risk and compliance **Know Your Customer (KYC)/Know Your Business (KYB**) - Keep track of follow ups on customers that your [KYC](/docs/id-verification-monitoring-products#synctera-know-your-customer-kyc)/[KYB](/docs/id-verification-monitoring-products#synctera-know-your-business-kyb) system flags as suspicious, at onboarding and throughout the customer lifecycle. **Customer alerts** - Take action on any alerts that come up for your customers and determine what to do with their accounts. These could be alerts like a customer being added to a watchlist or a business customer going bankrupt. **Anti-Money Laundering (AML)** - Keep track of follow ups on transactions that your [AML](/docs/back-office-products#synctera-antimoney-laundering-aml) system flags as potentially money laundering. You will also need to send these transactions to your bank partner. **Fraud** - Review transactions that your fraud monitoring system flags as potentially fraudulent, investigate them as necessary, and keep track of documentation and decisions.  #### Marketing and disclosures **Marketing materials** - Your bank partner will have to review most of the [marketing material](/docs/compliance-guidance-about-marketing) you plan to release to ensure it meets regulatory guidelines. You will be able to send them the material and let them know how, when, and where you plan on using it.   **Disclosures** - Depending on which products you offer, you will need to provide different disclosures to your customers. Synctera Cases will help track this for you, and if you miss a disclosure or two for a customer the system will let you know which disclosures were missed so that you can reach out to the customer. #### Customer service **Disputes and complaint**s - At times customers may want to dispute a transaction. When they do you will need to document the investigation process and timeline to show an auditable history of why the dispute was accepted or rejected. **Custom card review** - If you offer cards for which customers can provide a personal background image, you will have to review those images to ensure they meet specific guidelines. When a user provides an image, Synctera Cases will create a case for you to review and decide whether or not to allow the image to be printed on the customer’s card. #### Administrative **Reconciliation** - When you work with a bank partner to power your financial product’s accounts and money movement, on a daily basis your bank will need to [reconcile](/docs/back-office-products#synctera-reconciliation) your transaction history against both the bank’s general ledger (GL) and the various payments networks. When records don’t match, transactions must be traced back to identify and resolve discrepancies.  **Interest calculation** - This case type is related to interest-bearing accounts, which you may or may not offer. If an interest-bearing account receives a backdated inbound transaction with an effective date of more than 90 days in the past, a case is created for your operations team to manually post an interest correction to the customer’s account. **Billing and invoices** - Pay your Synctera bill, and receive your share of interchange revenue earned on your card program(s). Synctera Cases allows you to configure the accounts you would like to pay and get paid from so that funds movement can be automated. **Information requests** - When working with your bank partner and a FinTech platform like Synctera, you will need to get information from one or the other for things like what is required for offering a new product, or requests to make changes to configured fraud/AML/KYC/KYB rules. These requests can be created and tracked through the system rather than getting lost in email. ### How it works 1. Synctera Cases aggregates interactions across all services and solutions. 2. A summary of interactions is displayed in the Cases tab of the Synctera Console, comparing results against benchmarks, such as the total number of customers versus KYC checks completed. 3. Within each case, assigned users can take action, communicate with each other, update status and resolve issues. 4. Each case status and outcome is tracked for full visibility and compliance purposes. ## Synctera Reconciliation **Streamline account and transaction reconciliation processes** When you work with a bank partner to power your financial product’s accounts and money movement, on a daily basis you will need to reconcile your transaction history against both the bank’s general ledger (GL) and the various payments networks to ensure there are no missing transactions or funds. The bank has a fiduciary responsibility to ensure each transaction on their side matches your transaction history and the balances of the For Benefit Of (FBO) accounts, which hold the funds of your customers. When records don’t match, transactions must be traced back to identify and resolve discrepancies, which can be a tedious and time-consuming daily process. With Synctera Reconciliation, the process is automated. Our fast and efficient model properly processes and controls transactional, operational, and reference data. ### Benefits **Track money movement:** Use a bottom-up reconciliation process to easily track transactions **Enhance efficiency:** Automate manual reconciliation processes so banks can redeploy resources to value-added activities **Increase speed and accuracy:** Match FBO account and sub-ledger balances quickly and precisely **Manage exceptions:** Alerts and intuitive search capabilities make it easy to find and resolve exceptions ### How it works Synctera provides banks with your complete transaction history, enabling the bank to easily balance your FBO accounts and settle with the payment networks on your behalf. In the event of a discrepancy, the Synctera platform includes a streamlined case management workflow, matching methodology, and escalation process. 1. Transactions are automatically reconciled across files and providers. 2. Unique reconciliation identifiers are assigned for each transaction. 3. Probable matches are identified and exceptions manually updated to achieve reconciliation. # Business Onboarding Source: https://docs.synctera.com/docs/business-onboarding This diagram outlines the compliance requirements for a typical business DDA program as it pertains to the end user experience and development flow. Visit our [Business Customer Guide](/docs/create-a-business) for details and links to the required individual API Specs on developing your onboarding process with our APIs. For more information like this about KYC verification, check out our [Consumer Onboarding](/docs/consumer-onboarding) solution page. You can also find more details as to the exact compliance requirements and language for each step within the relevant (business-related) sections on our [CIP Page](/docs/cip), for example: * See details on typical Enhanced Due Diligence procedures [here](/docs/cip#enhanced-due-diligence-edd) * See details on what language we recommend when identifying and certifying a beneficial owner [here](/docs/cip#beneficial-ownership-controlmanaging-person). # Managing Debit Cards Source: https://docs.synctera.com/docs/card-management The Cards tab in the Synctera Console supports the ability to issue and manage cards. ## Features **Card Issuance:** This section covers the features and functionality related to card issuance, re-issuance and replacement **Card Activation:** This section covers the features and functionality related to initial card activation **Card Set PIN:** This section covers the features and functionality related to card PIN change ## Card Issuance Synctera Platform provides the ability to issue, re-issue and replace a card that can be initiated via an API request or from Synctera UI. All requests will be then submitted to the Marqeta application, which will handle the assignment of the PAN, CVV and Expiration Date. #### *Virtual Card Issuance:*