# FinDock Payment API The FinDock Payment API is a REST API for handling one-time and recurring payments. The API abstracts Salesforce and FinDock configuration details, providing instead informational endpoints. You can use these to build dynamic front-end application that are independent of a specific configuration. If you are just starting to work with the API, we recommend reading the following guides: * [How the Payment API works](/api/how-the-payment-api-works.md) * [Getting started with the Payment API](/api/getting-started-with-the-payment-api-v2.md) * [How to use the Payment API](/api/how-to-use-the-payment-api-v2.md) ## Salesforce objects, record types and fields The API is for Salesforce implementations, so there are some Salesforce-specific aspects to take into account. Alongside primitive data types such as `string`, the Payment API uses several data types that might be unfamiliar to you if you have not worked with Salesforce. These data types are Salesforce objects (sObjects), record types and fields. ### sObjects sObjects are objects that can be stored as records in the Salesforce database. The records are persistent representations of data in the database. Some API resources accept, or even require, sObjects. The Payer object, for example, requires sObjects such as Contact and Account. The API allows you to define these objects in payloads. FinDock sObjects like Inbound Report can be included as well, but they require you to specify the object fields as Salesforce fields. ### Accounts, Contacts, Person Accounts Salesforce provides two objects to indicate a Payer: - Account: usually an organization - Contact: an individual Added to that simple split is [Person Account](https://help.salesforce.com/s/articleView?id=sf.account_person.htm&type=5), which stores information about individual people by combining certain account and contact fields into a single record. It is not its own object, but can be stored as an Account with a specific Record Type (see below). Some features of Salesforce - for instance Fundraising as used in NonProfit Cloud (NPC) - **require** an Account to be available. This means that when you have an individual payer you need to send a Person Account instead of a Contact. These features will only work with a Contact object when an Account object is also sent. Make sure to always check with your Salesforce admin whether they are enabled and / or used! To send Person Accounts to the FinDock API use an Account object with a `RecordTypeName` (API name) of a Record Type that is of the type Person Account. By default this is `PersonAccount` but there is a high chance this was customized or an environment has multiple Person Account Record Types, so always consult your Salesforce admin. Whether it's an Account or Contact record, you always need to take into consideration how the payer is deduplicated. Every organization has [configured deduplication rules](/docs/@production/reconciliation/processing-and-reconciling-online-payments.md#configuring-deduplication) that define the information the payment intent message needs to include for deduplication, bearing in mind that the more data points you have, the more effective deduplication is. ```json { "Account":{ "RecordTypeName": "person-account-record-type", "SalesforceFields":{ "Name":"Test Payer", "BillingStreet":"Any Street", "BillingCity":"Any City", "BillingPostalCode":"00000" } } } ``` ### Record types Record types let Salesforce administrators offer specific business processes, picklist values, and page layouts to different users. Organizations can, for example, differentiate between `Account` object records by assigning them an `Organization` or `Household` record type. This facilitates the application of different types of page layouts or possible field values based on what record type an `Account` is. Please note: when the Person Accounts feature is enabled in the environment Record Types are especially important. More information on Person Accounts can be found below. ### Salesforce fields Next to the out-of-the-box Salesforce data model, Salesforce allows administrators to add custom fields to objects in Salesforce. All fields can be seen in the Salesforce Object Manager of the Salesforce org setup. Also, different implementations of Salesforce can use different fields for a value like `email`. The API allows you to send Salesforce fields, and their corresponding values, as attributes in requests to the API. Custom fields for **standard Salesforce objects** like `Contact` and `Account` are passed with "__c" at the end. For illustration, we have added the standard fields `FirstName` and `LastName` and the custom field `TwitterHandle` to the Salesforce `Contact` object. ```json { "Payer":{ "Contact":{ "SalesforceFields":{ "FirstName":"Test", "LastName":"Payer", "TwitterHandle__c": "@TestPayerFamily" } } } } ``` Custom fields for **custom FinDock objects** like `Installment` and `Recurring Payment` can also be passed in a `SalesforceFields` object. `SalesforceFields` passed in the `OneTime` object are copied to the `Installment` record in Salesforce and `SalesforceFields` passed in the `Recurring` object are copied to the `Recurring` object in Salesforce. What `Recurring` object the values are stored to depends on whether you use a Source Connector. ```json { "OneTime":{ "Amount": 10.0, "SalesforceFields": { "Sales_Invoice__c": "a506E0000009TfL" } } } ``` ### Custom field exceptions For Person Accounts the following exceptions for (custom) field notations apply: - Standard Account Fields can be passed as regular fields: `"BillingStreet":"Any Street"`. - Custom Account Fields can be passed with the regular `__c` suffix: `"Custom_Street__c":"Any Street"`. - Standard Contact Fields need to be prefixed with `Person`, with the exception of FirstName, LastName, Salutation which can be passed as regular fields: `"PersonEmail" : "test@findock.com"`. - Custom Contact Fields need to be suffixed with `__pc`: `"Custom_email__pc":"test@findock.com"` The fields and their correct notations can be found in the Salesforce Setup > Object Manager for Account. ```json { "Account":{ "RecordTypeName": "PersonAccount", "SalesforceFields":{ "FirstName": "John", "LastName": "Payer", "PersonEmail": "test@findock.com", "BillingStreet": "Any Street", "Custom_account_field__c": "Apartment Name", "Custom_contact_field__pc": "Middle Name" } } } ``` For the FinDock for Fundraising source connector used with NonProfit Cloud (NPC), for example, the following exception applies: Since the "Recurring" object (Gift Commitment) is split in two objects (Gift Commitment & Gift Commitment Schedule), a prefix `GiftCommitment` is required to set SalesforceFields on this object. Fields without prefix are assumed to be set on the Gift Commitment Schedule object. Example: `GiftCommitment.GiftVehicle`. You can check which Source Connectors are available in the environment by performing a GET operation on the [Source Connector](/api/payment-api-v2/source-connectors) endpoint. ## Authentication Authentication is accomplished through an [Oauth2.0 authorization flow](https://help.salesforce.com/articleView?id=remoteaccess_oauth_web_server_flow.htm&type=5). Each Salesforce environment requires its own token. A [refresh token](https://help.salesforce.com/articleView?id=remoteaccess_oauth_flows.htm&type=5) can be used to acquire a new access token if the current token has expired. Read more on how to authenticate to Salesforce in the [Salesforce developer guide](https://help.salesforce.com/articleView?id=remoteaccess_oauth_flows.htm&type=5). Both `client_id` and `client_secret` can be acquired from the Salesforce 'Setup' from a 'Connected App'. - The `Authorization` token can be passed as a Bearer token in the request Header. - To Acquire a new `Authorization` token with the returned `Refresh` token, please make sure to pass the right `grant_type`, `client_id`, `client_secret` and `refresh_token` as specified in the Salesforce documentation referenced above. To get up and running quickly, use the (unofficial-but-provided-by) [Salesforce Postman Collection](https://github.com/scolladon/postman-salesforce-apis), as explained in this [blog](https://developer.salesforce.com/blogs/2020/03/explore-the-salesforce-apis-with-a-postman-collection.html) and look for the 'auth' folder. ## Error and response codes When the API was not called successfully, you will receive a HTTP Status Code `4xx` or `500`. Specifically a `422` code is returned when the message was well-formed, but could not be processed because of - for instance - wrong data. In the response you will find additional information on how to prevent or handle the error through an array of `Errors` with an `error_code` and `error_message`. Example of an error that is returned whenever an incorrect request is sent: ```json { "Errors": [ { "error_message": "Amount can't be 0 or negative", "error_code": "200" } ] } ``` Below is a collection of possible error codes: | Code | Description | | --- | --- | | 010 | Malformed request: missing one or more mandatory core parameter(s) | 011 | Malformed request: missing one or more mandatory Payment Processor parameters | 012 | Malformed request: missing one or more mandatory SourceConnector parameters | 200 | Invalid data: the supplied data is incorrect (e.g. an invalid e-mail address). | 201 | Sort code or bank account is invalid (Bacs Direct Debit). | 202 | IBAN _<your-IBAN>_ is not valid. | 203 | The provided IBAN is not in SEPA geographical zone. | 204 | BIC is required to collect SEPA Direct Debit from a non-EAA country bank account. | 205 | Street, Housename or Number, Zip code and City are required to collect SEPA Direct Debit from a non-EEA country bank account. | 206 | Clearing number and/or bank account invalid (Sweden). | 998 | An object is missing and no default is specified in the org. | 999 | Error without specific category: consult the `error_message` for details. For more information on errors and response codes and debugging the API, please see [Troubleshooting the Payment API](/api/troubleshooting-the-payment-api-v2). ## Webhook events and notifications To receive updates on payments created with the `/PaymentIntent` endpoint: - pass an endpoint URL in the `WebhookURL` parameter in the request body. - add your URL to the [Remote Site Setting](https://help.salesforce.com/articleView?id=configuring_remoteproxy.htm&type=5) of the Salesforce environment. FinDock sends you notifications for the following events around your API call: | Event | Description | | ----- | ------------ | |`paymentIntent.created` | When the processing of your API call has started in the Salesforce environment. |`paymentIntent.processed` | When the processing of your API call has finished successfully. Note: this does not mean that the payment has been collected! |`paymentIntent.in_review` | When the processing of your API call has stalled and manual intervention from Salesforce side has been requested. Note: this will not stop the customer from completing the payment flow! |`paymentIntent.failed` | When the processing of your API call has failed and needs to be handled in the Salesforce environment. Note: this will not stop the customer from completing the payment flow! |`installment.created` | When an Installment (expected one-time payment) is created. |`installment.status_change` | If the `status` of the One Time Payment (Installment record in Salesforce) changes, either by an update from a PSP or manually No specific events are sent for recurring payments other than the `paymentIntent` which contains the Salesforce Id of the recurring record. For more information about processing online payments, please [Processing online payments](/docs/@production/reconciliation/processing-and-reconciling-online-payments.md). ### Webhook content For `paymentIntent` you receive notifications with the following body. Each event contains a `type` and a `data` object with further details. Check out the [PaymentIntent object schema](/api/payment-api-v2/payment-intent) for definitions. ```json { "type": "paymentIntent.processed", "data": { "Status": "Matched", "Recurring": { "Url": "/services/data/v63.0/sobjects/cpm__Recurring_Payment__c/a0V3X00000S7b5YUAR", "Type": "cpm__Recurring_Payment__c", "Id": "a0V3X00000S7b5YUAR" }, "Payer": { "Contact": { "Url": "/services/data/v63.0/sobjects/Contact/0033X00003H9uZPQAZ", "Type": "Contact", "Id": "0033X00003H9uZPQAZ", "Name": "Test Payment" }, "Account": { "Url": "/services/data/v63.0/sobjects/Account/0013X00002bZPGIQA4", "Type": "Account", "Id": "0013X00002bZPGIQA4", "Name": "Payment Family" } }, "OneTime": { "Url": "/services/data/v63.0/sobjects/cpm__Installment__c/a083X00001mFTBAQA4", "Type": "cpm__Installment__c", "Id": "a083X00001mFTBAQA4", "Status": "Pending" }, "Id": "pi_6cazikr7625yqt9mf" } } ``` For `installment` you receive a notification with the following body. ```json { "type": "installment", "data": { "Url": "/services/data/v63.0/sobjects/cpm__Installment__c/a083X00001kJynLQAS", "Type": "cpm__Installment__c", "Id": "a083X00001kJynLQAS", "Target": "Adyen1", "Status": "Collected", "RecordTypeName": "Receivable", "PayUrl": "https://link.dev.findock.com/pay/3xxxxmuai2/8897b4da-e48a-7ff3-90dd-ecb65094802c", "Payments": [ { "Url": "/services/data/v63.0/sobjects/cpm__Payment__c/a0R3X00000V1sutUAB", "Type": "cpm__Payment__c", "Id": "a0R3X00000V1sutUAB", "PaymentProcessor": "PaymentHub-Adyen", "PaymentMethod": "CreditCard", "CollectionDate": "2020-11-26", "Amount": 15 } ], "PaymentProcessor": "PaymentHub-Adyen", "PaymentMethod": "CreditCard", "PaymentIntentId": "pi_5jthokq7z8som0w6o", "AmountOpen": 0, "Amount": 15 } } ``` API reference specification. Last updated on 2024-03-13. Version: v2 License: FinDock ## Servers Salesforce ``` https://{instance}.my.salesforce.com/services/apexrest/cpm/v2 ``` Variables: - `instance`: The instance value for your org. Default: "demo" ## Security ### Salesforce_Production The Payment API uses [the Salesforce OAuth2.0 web server flow](https://help.salesforce.com/articleView?id=remoteaccess_oauth_web_server_flow.htm&type=5) for production orgs. The required flow and scope depends on the specific operation. For further information, see [Authentication](/#authentication). Type: oauth2 ### Salesforce_Sandbox The Payment API uses [the Salesforce OAuth2.0 web server flow](https://help.salesforce.com/articleView?id=remoteaccess_oauth_web_server_flow.htm&type=5) for sandbox orgs. The required flow and scope depends on the specific operation. For further information, see [Authentication](/#authentication). Type: oauth2 ## Download OpenAPI description [FinDock Payment API](https://docs.findock.com/_bundle/api/payment-api-v2.yaml) ## Payment Intent The `/PaymentIntent` endpoint supports handling both one-time and recurring payments. For recurring payments, a Recurring block replaces, or is added alongside, the OneTime block in the request. Some Payment Service Providers (PSPs) require or optionally support an initial payment (a OneTime block) AND recurring payment in the same request for authorization. You can find out the initial payment details for a given PSP using `GET /PaymentMethods`. Please see the specific [payment processor articles](/docs/@production/payment-processors/index.md) for further details. When using the endpoint to initiate new payments, check the org configuration and make sure you have the correct details by querying the [Payment Method](/api/payment-api-v2/payment-methods) and [Source Connectors](/api/payment-api-v2/source-connectors) endpoints. Some payment methods enable or require further [Package Actions](/api/payment-api-v2/package-actions). Be sure to also include these in the payment intent request. In addition to setting up new one-time or recurring payments, you can pay existing one-time payments (installments) and update existing recurring payments. To pay an existing installment, simply exclude the Payer block and add the Id of the installment to the OneTime block. We recommend first checking the details of the installment using `GET /Installment` with the GUID or record Id. To update the payment method, processor or other details of a recurring payment, remove the Payer block and add the identifier of the recurring payment to the Recurring block along with a PaymentMethod block that includes the details to be changed. As with installments, we recommend first checking current details by using `GET /Recurring` with the GUID or record Id. The endpoint also supports checking the status of payment intent inbound report processing. Use `GET /PaymentIntent/{ID}` where ID is payment intent Id of the one-time or recurring payment. ### Create, pay or update payments - [POST /PaymentIntent](https://docs.findock.com/api/payment-api-v2/payment-intent/paymentintent.md): The /PaymentIntent endpoint supports four POST operations: (1) create a new one-time payment, (2) create a new recurring payment, (3) pay an existing installment, and (4) update an existing recurring payment. All actions automatically update Salesforce data accordingly. ### Check inbound report status - [GET /PaymentIntent/{ID}](https://docs.findock.com/api/payment-api-v2/payment-intent/paymentstatus.md): Use this operation to get the status of the inbound report of a payment intent along with information about the related installment or recurring payment (Recurring Payment, Gift Commitment or Recurring Donation object record). To get details of the related records themselves, use the /Installment and /Recurring endpoints. ## Installment The `/Installment` endpoint allows you to retrieve detailed information about an existing [Installment](/docs/@production/data-model/installment.md), the FinDock equivalent of a one-time payment intent. [Payment](/docs/@production/data-model/payment.md) records in FinDock represent actual cash flow, so a single installment can have one or more related payments made with the same or different processors and payment methods. One-time payment intents created through the Payment API become installments. These and all other installments installments created through other channels can be queried through the `/Installment` endpoint. The response includes a list of all Payment records (cash movements) related to the queried installment. ### Get installment details - [GET /Installment/{ID}](https://docs.findock.com/api/payment-api-v2/installment/installmentdetails.md): This endpoint returns detailed information of an Installment record in Salesforce, including status and related Payment records. ## Recurring The `/Recurring` endpoint allows you to retrieve information about an existing recurring payments. These can be records for the FinDock Recurring Payment object or records for source-specific Salesforce objects such as Recurring Donation (NPSP) and Gift Commitment (Fundraising). The response includes a full list of details about the recurring payment which can be used to confirm and update, for example, the payment method and processor for future installment collections. ### Get recurring payment details - [GET /Recurring/{ID}](https://docs.findock.com/api/payment-api-v2/recurring/recurringdetails.md): This endpoint returns detailed information of a recurring payment in Salesforce. The record is source-specific, so you need to ensure you are referencing the correct object record. The object may be the FinDock Recurring Payment or Salesforce objects like Recurring Donation or Gift Commitment. ## Payment Methods This is an informational resource endpoint that returns a list of all available payment [processors](/docs/@production/payment-processors/index.md) and [methods](/docs/@production/payment-processors/payment-methods/payment-methods-overview.md). An org can have many method-processor combinations enabled. If there are multiple processors (PSPs) available for a payment method, one may be set to be the default processor for that method. ### Get payment methods and processors - [GET /PaymentMethods](https://docs.findock.com/api/payment-api-v2/payment-methods/getpaymentmethods.md): This endpoint returns a complete list of activated payment methods in the Salesforce org and the payment processors configured to process those methods. ## Source Connectors This is an informational resource endpoint that returns the [source connector](/docs/@production/source-connectors/index.md) used in a specific Salesforce org. There is always a default source, but an org can have more than one source connector enabled. The source connector determines which payment-related objects FinDock needs to create and update in Salesforce when an action is initiated through the Payment API. ### Get available sources - [GET /SourceConnector](https://docs.findock.com/api/payment-api-v2/source-connectors/getsourceconnectors.md): This endpoint returns the configured source connectors in the Salesforce org. ## Package Actions Informational resource endpoint that returns the package actions possible and/or required for a certain Salesforce environment. Package actions are additional actions that can be performed for a specific FinDock package, like a payment extension or source connector. These additional actions can be included in payment intent calls to the Payment API. If package actions are available, please refer to the specific [processor](/docs/@production/payment-processors/index.md) or [source connector](/docs/@production/source-connectors/index.md) documentation for further information. The [Gift Aid](/docs/@production/source-connectors/how-gift-aid-works.md) package, for example, has [package actions for declarations](/docs/@production/source-connectors/for-admins-and-sis-gift-aid-setup.md#using-the-payment-api-for-gift-aid-declarations). ### Get details of package-specific actions - [GET /PackageActions](https://docs.findock.com/api/payment-api-v2/package-actions/getpackageactions.md): This endpoint returns a list of unique actions that specific to a given source connector or payment extension.