Skip to main content

Integration

Integrating with the Anchor Platform for facilitating cross-border payments involves implementing the following, at a mimimum:

  • GET /customer & PUT /customer KYC API endpoints to request & collect customers' KYC data
  • GET /rate RFQ API endpoint to provide FX rates between the on & off-chain assets supported
  • GET /transactions requests to fetch updates on the Anchor Platform's transactions' statuses (documentation coming soon)
  • PATCH /transactions requests to update the Anchor Platform's transactions' statuses

The following may also be required depending on your use case:

  • GET /fee if your business wants to provide senders the option to skip the quote creation step
  • GET /unique_address if your business uses a custody service for on-chain assets
  • DELETE /customer if your business wants or is required to allow senders to request deletion of customer data

Create a Business Server

First, lets create a business server and add it to our docker compose file.

version: "3.8"

services:
sep-server:
image: stellar/anchor-platform:latest
command: --sep-server
env_file:
- ./dev.env
volumes:
- ./config:/home
ports:
- "8080:8080"
depends_on:
- db
platform-server:
image: stellar/anchor-platform:latest
command: --platform-server
env_file:
- ./dev.env
volumes:
- ./config:/home
ports:
- "8085:8085"
depends_on:
- db

server:
build: .
ports:
- "8081:8081"
env_file:
- ./dev.env
db:
image: postgres:14
ports:
- "5432:5432"
env_file:
- ./dev.env

Next, create a simple web server using your preferred programming language and a Dockerfile that starts the server. docker compose up should successfully start all three services.

This guide does not provide an example implementation of the endpoints, but you can find more information about the request and response schemas in the Anchor Platform API Reference, and the sections below will expand on concepts important to understand when implementing the endpoints.

Customer Callback Endpoints

The Anchor Platform never stores your customers' PII, and instead acts as a proxy server between client applications and your business, forwarding requests and responses to the other party. Currently, requests and responses are almost identical to those defined in the SEP-12 KYC API specification.

Identifying Customers

Customers can be identified using two approaches.

The first approach uses a Stellar account and memo. When using the Anchor Platform for facilitating cross-border payments, the sending organization uses their own Stellar account, the one used to authenticate via SEP-10 Stellar Authentication, when registering customers with your business. Memos are used to distinguish unique customers originating from the same sending organization.

The second approach uses customer IDs generated by your service. For example, if a sending organization is registering a customer, your business will receive a PUT /customer request like the following:

{
"account": "GDJUOFZGW5WYBK4GIETCSSM6MTTIJ4SUMCQITPTLUWMQ6B4UIX2IEX47",
"memo": "780284017",
"type": "sep31-sender",
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]"
}

In this example, the GDJ...X47 public key identifies the sending organization, and the 780284017 memo identifies the customer. Memos are usually 64-bit integers, but they can also be other data types, so they should be saved as strings. In response, your business should return a customer ID.

{
"id": "fb5ddc93-1d5d-490d-ba5f-2c361cea41f7"
}

Your business server can use any identifer for customers as long as it is a string.

Following the registration of a customer, the sending organization can use either approach when checking the customer's status. For example, you may get a GET /customer request like the following:

/customer?account=GDJUOFZGW5WYBK4GIETCSSM6MTTIJ4SUMCQITPTLUWMQ6B4UIX2IEX47&memo=780284017&type=sep31-sender

Or, the sending organziation could use the identifier you returned when they originally registered the customer.

/customer?id=fb5ddc93-1d5d-490d-ba5f-2c361cea41f7&type=sep31-sender

Your business will need to maintain a mapping between the account & memo used to originally register the customer and the ID you return in the response, as well as the KYC data provided. In future iterations of the Anchor Platform, we may maintain this mapping for your business so you only have to work with the IDs you generate.

Customer Types

Your business likely requires different sets of KYC information depending on the type of customer. You can define the labels for each of these customer types in your dev.assets.yaml file, and your sending organizations will need to understand which label to use when registering or querying the status of customers.

In PUT /customer requests, you should use the type passed to evaluate whether the sender has provided all of the required fields. In GET /customer requests, you should use the type to determine the customer's status.

Test with the Demo Wallet

You can test your implementation with the Stellar Demo Wallet following the steps below.

  1. Select "Generate keypair for new account"
  2. Select "Create account"
  3. Select "Add Asset" and enter the asset code and the Anchor Platform's home domain, localhost:8080
  4. Select "Add trustline"
  5. Fund your account with a balance of the asset
  6. Select "SEP-31 Send" in the dropdown menu

You should see the demo wallet find your service URLs, authenticate, and check which KYC fields it needs to collect. It should then present a form for you to enter the KYC details for the sender and reciever.

demo wallet after initiating a transaction

Once you've entered in the information requested, it will send that information to the Anchor Platform, which will send it to your business server. Once the demo wallet has the customers' IDs you generated, it will initiate a transaction which should fail.

Rate Callback Endpoint

Once the sending organization has registered the customers involved in the transaction, it will need to request a quote, or FX rate, from your business. The Anchor Platform requests this information from your business server using the GET /rate endpoint.

Firm vs. Indicative Quotes

Requests for quotes will have a type parameter that is either indicative or firm. If type=firm, your response must include the id & expires_at date-time field and reserve the liquidity needed to fulfil this quote until the quote expires. If type=indicative, do not return id or expires_at fields because the rate provided will not be used in a transaction.

Note that the client may request that the quote expires after a specific date-time using the expires_after parameter. Your business must honor this request by returning an expires_at value that is at or after the requested date-time or reject the request with a 400 Bad Request response, which will be forwarded to the client.

Using the Client ID

Requests may include a client_id parameter that identifies the sending organization requesting the rate. You can use this parameter to adhere to the commercial terms agreed upon with that sending organization, such as offering discounted rates. client_id may not be present for indicative requests, in which case your market price should be returned. Currently client_id will always be the Stellar public key the sending organization used to authenticate with the Anchor Platform.

Delivery Methods

It is common for businesses' rates and fees to differ depending on the payment rails used to send funds to the recipient. If your delivery methods are configured in your asset.yaml file, clients will always provide the payment rail they want your business to use for firm quote requests.

Because this endpoint is currently only used paying out remittances in off-chain assets, the buy_delivery_method will be used. If this endpoint is ever used in other transaction flows such as SEP-24 deposits, then sell_delivery_method may also be passed for business that support these types of transactions.

Fetching Transaction Status Updates

To facilitate cross-border payments, you'll need to be able to detect when a sending organization has sent your business an on-chain payment and determine which transaction that payment was meant to fulfil.

The easiest way to do that is to run the Stellar Observer, which will detect these payments and update the corresponding transaction record with information about the payment. Your business can then detect these updates by polling the GET /transactions Platform API endpoint.

Running the Stellar Observer

The Stellar Observer monitors the Stellar ledger for payments made to your account(s) and updates the corresponding transaction records with on-chain payment information. To run the observer, add the following to your docker compose file.

services:
...
observer:
image: stellar/anchor-platform:latest
command: --stellar-observer
env_file:
- ./dev.env
volumes:
- ./config:/home

Polling for Received Payments

The Stellar Observer makes PATCH /transactions requests to the Platform API whenever it detects payments received for transactions initiated by sending organizations, updating the transaction's transfer_received_at date-time. Your business should periodically poll the GET /transactions Platform API endpoint to detect these updates like so.

curl http://localhost:8080/transactions?sep=31&order_by=transfer_received_at&order=desc

The response will include a list of cross-border payment transactions initiated by sending organizations ordered by when a payment was received for that transaction. For each transaction returned, your business should check whether or not it has already detected the payment for that transaction. If it has, you have detected all payments made to your account(s).

Providing Transaction Status Updates

Once your business detects that it has received an on-chain payment for a specific transaction, it must make the off-chain payment to the recipient and update the transaction's status to completed via a PATCH /transactions request.

{
"transaction": {
"id": "<id>",
"status": "completed",
"message": "a deposit to the recipient's bank has been initiated"
}
}

Fee Callback Endpoint

Your business may want to offer sending organizations the option to skip the quote creation process, allowing your business to use a rate determined at the time funds are paid out to the recipient. In this case, the Anchor Platform will not make a GET /rate request, but you will still need to provide the fee your business will charge for these types of transactions using the GET /fee endpoint.

Configuration

You can enable these types of transactions by updating your assets.yaml file configuration:

assets:
- ...
sep31:
quotes_required: false

Unique Address Callback Endpoint

Businesses must provide a unique Stellar account and memo pair for each transaction requested by sending organizations so the Anchor Platform can identify and map the on-chain payment sent for the specific transaction. The Anchor Platform can generate these account & memo pairs itself, but most businesses use a custodial service to receive on-chain payments, in which case the business must request the custodian to generate the Stellar account & memo. This is done using the GET /unique_address endpoint.

Configuration

To configure the Anchor Platform to make these requests, add the following to your configuration:

# dev.env
SEP31_DEPOSIT_INFO_GENERATOR_TYPE=api
caution

This endpoint may be removed in future major version updates of the Anchor Platform when it adds support for connecting to custodial services and generating these addresses automatically.