--- sidebar_label: 'External Payment Provider' sidebar_position: 2 --- # External Payment Provider :::note Information in this article is in preview status. Do not use information in this article without being in contact with Future Ordering. ::: This document defines the integration requirements for external payment providers (Partners) connecting to Future Ordering's payment infrastructure. It covers the API the Partner must implement, the event notifications the Partner must deliver, and the expected behavior for authentication, idempotency, and retries. - **External Payment API**: an HTTP endpoint the Partner exposes. Future Ordering calls this to initiate payment operations. - **Payment Notifications API**: an HTTP endpoint Future Ordering exposes. The Partner calls this to report the outcome of each operation. --- ## System Overview ![System Overview](external-payment-system-overview.svg) Future Ordering's Payment System initiates payment operations by calling the Partner's External Payment API. Each request is authenticated using a JWT bearer token issued by Future Ordering's Authorization Server, which the Partner must validate before processing the operation. For each accepted operation, the Partner must deliver an outcome event to Future Ordering's Payment Notifications API. To authenticate these requests, the Partner obtains a token from Future Ordering's Authorization Server using the OAuth 2.0 Client Credentials Flow and includes it as a bearer token when posting the event. --- ## External Payment API :::tip Quick Reference For a quick reference with the OpenAPI specification and endpoint basics, see the [External Payment Operations Endpoint](./external-payment-operations-endpoint) article. ::: ### Endpoint The Partner must expose a single HTTP endpoint to receive payment operations from Future Ordering. The URL is agreed upon during onboarding. Including the API version in the URL path (e.g. `/v1/payments`) is recommended to simplify transitions to future versions. The endpoint must be served over **HTTPS only** with a minimum TLS version of **TLS 1.2**. **Method:** `POST` **Content-Type:** `application/json` ### Authentication Incoming requests from Future Ordering carry a **JWT bearer token** issued by Future Ordering's Authorization Server. The Partner must validate the token's issuer, scope, and access rights on each request. ``` Authorization: Bearer ``` For details on token validation, refer to the [article on validing an access token](../exposing-custom-api/validating-access-tokens.md). #### Tenant Identification The tenant ID is conveyed through the JWT token's issuer claim. The Partner must extract the tenant identifier from the validated token and use it to scope the operation to the correct tenant. ### Idempotency Each request carries a UUID in the `Idempotency-Key` header. This value serves as the `operationId` in the resulting outcome events. If the key matches a previously processed request, the Partner must return the original response without reprocessing the operation. The Partner must retain idempotency keys for a minimum of **30 days**. ``` Idempotency-Key: 3fa85f64-5717-4562-b3fc-2c963f66afa6 ``` ### Operations A typical payment flow involves four operations: **Registration** → **Authorization** → **Capture** (or **Annulment**). Each operation is accepted asynchronously, and the Partner delivers the outcome via the [Payment Notifications API](#payment-notifications-api). The raw OpenAPI description for the endpoint is available here: [External Payment Operations OpenAPI specification](/assets/external-payment-provider/external-payment-provider-openapi-spec.json). Every operation targets a specific transaction, identified by a `transactionId` — a UUID assigned by Future Ordering that uniquely identifies a single payment. All operations within a payment flow share the same `transactionId`, linking Registration, Authorization, and the final Capture or Annulment to one transaction. > **Note:** Refunds are not supported in this version of the API. Support for refund operations may be introduced in a future version. Full request schemas are available in the API schema reference provided during onboarding. The Partner is responsible for delivering a [CloudEvents 1.0](https://cloudevents.io) outcome event for every accepted operation, regardless of downstream issues. If the outcome cannot be determined at the time of processing, for example, due to loss of connectivity with an underlying system, the Partner must resolve the outcome before delivering the event. This may involve querying the downstream system upon reconnection or other reconciliation mechanisms. An event must not be delivered until the actual outcome is known. #### Registration The first operation in the lifecycle. Initiates a transaction on the Partner's side, establishing the context for all subsequent operations. The Partner responds `202 Accepted` and later notifies Future Ordering of the outcome. Registration is the designated point for all actions that must occur before the payment can proceed, including user-facing interactions such as redirect flows or strong customer authentication (SCA) challenges. Future Ordering will not proceed to Authorization until a successful Registration notification has been received, and assumes that no further interactive steps are required after that point. #### Authorization Sent after a successful Registration, requesting the Partner to reserve funds against the registered transaction. The Partner responds `202 Accepted` and later notifies Future Ordering of the outcome. While the meaning of Authorization may differ across integrations, a successful outcome always indicates that funds are reserved and a Capture or Annulment can follow. #### Capture Sent after a successful Authorization, requesting the Partner to settle the reserved funds. The Partner responds `202 Accepted` and later notifies Future Ordering of the outcome. Only one Capture may be issued per Authorization, and it must be for the full authorized amount. Partial captures are currently not supported. #### Annulment Sent after a successful Authorization, in place of a Capture, requesting the Partner to release the reserved funds without charging the customer. The Partner responds `202 Accepted` and later notifies Future Ordering of the outcome. #### Operation Timeouts The timeout for completing subsequent operations such as Capture or Annulment is configurable and agreed upon during onboarding. If Future Ordering does not receive an outcome event within the configured timeframe, it considers the operation failed. ### Response Codes The Partner must respond with one of the following status codes. For specifications, refer to the API schema reference. | Code | Meaning | |------|---------| | `202 Accepted` | Operation accepted for processing | | `400 Bad Request` | Malformed request (invalid JSON, missing required field) | | `401 Unauthorized` | Authentication failed | | `403 Forbidden` | Authorization failed | | `408 Request Timeout` | Server did not receive the complete request in time | | `429 Too Many Requests / 5xx Server Error` | Transient failure | `400 Bad Request`, `429 Too Many Requests`, and `5xx Server Error` error responses must include a body following [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457) with `Content-Type: application/problem+json`. Responses for `401 Unauthorized`, `403 Forbidden`, and `408 Request Timeout` do not require an RFC 9457 body. A `202 Accepted` response indicates the Partner has received the operation and will process it asynchronously. It does not imply the operation will succeed. All operation outcomes, including business rule violations such as invalid state transitions, are delivered as outcome events. The Partner must not perform synchronous validation against the underlying payment service provider. Pre-flight checks are limited to request structure and access control (authentication and authorization). ### Retries When the Partner API returns `408`, `429`, or a `5xx` response, Future Ordering retries the request. Each retry carries the same `Idempotency-Key`, and the Partner must use this to suppress duplicate processing. --- ## Payment Notifications API ### Endpoint | Environment | URL | |-------------|-----| | Test | `https://api-test.futureordering.com/payment-providers/external/events` | | Production | `https://api.futureordering.com/payment-providers/external/events` | **Method:** `POST` **Content-Type:** `application/json` The endpoint is served over **HTTPS only** with a minimum TLS version of **TLS 1.2**. ### Versioning ``` X-Api-Version: 0 ``` This header specifies the Payment Notifications API contract version. Requests without a supported version may be rejected. ### Authentication The Partner must authenticate using the **OAuth 2.0 Client Credentials Flow** against Future Ordering's Authorization Server. ``` Authorization: Bearer ``` For more information, see the sections on [obtaining tokens, token caching requirements](../using-the-api/authentication.md), and [available endpoints](/api). **Required OAuth scope:** `fo:payment` ### Events Events must conform to the [CloudEvents 1.0](https://cloudevents.io) specification and cover the following outcome categories: successful completion, failure, and cancellation by the user. ![Operation outcome events](external-payment-operation-events.svg) Event type values follow the pattern `payment.external.transaction._.v1`. Full event schemas and the complete list of type values are available in the API schema reference provided during onboarding. #### Example Event ```json { "specversion": "1.0", "id": "550e8400-e29b-41d4-a716-446655440000", "type": "payment.external.transaction.registration_succeeded.v1", "source": "https://partner.example.com/v1/payments", "subject": "transaction/3fa85f64-5717-4562-b3fc-2c963f66afa6", "time": "2024-01-15T10:30:05.6458455Z", "datacontenttype": "application/json", "data": { "operationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", ... } } ``` | Field | Value | |-------|-------| | `specversion` | `"1.0"` | | `id` | UUID identifying the event | | `type` | Event type URI. See the API schema reference for defined values | | `source` | URI identifying the origin of the event | | `subject` | `transaction/{transactionId}` where `transactionId` is the identifier provided by Future Ordering in the operation request | | `time` | UTC timestamp of when the event occurred | | `datacontenttype` | `"application/json"` | | `data` | Event-specific payload. See the API schema reference for details | ### Response Codes | Code | Meaning | |------|---------| | `200 OK` | Event accepted | | `400 Bad Request` | Malformed event, do not retry | | `401 Unauthorized` | Authentication failed, do not retry | | `403 Forbidden` | Authorization failed, do not retry | | `408 Request Timeout` | Server did not receive the complete request in time | | `429 Too Many Requests / 5xx Server Error` | Transient failure, retry with exponential backoff | `400 Bad Request`, `429 Too Many Requests`, and `5xx Server Error` responses include a body following [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457) with `Content-Type: application/problem+json`. Responses for `401 Unauthorized`, `403 Forbidden`, and `408 Request Timeout` do not include an RFC 9457 body. ### Retries The Partner must retry event delivery on transient failures (`408`, `429`, `5xx`). The same event `id` must be included on each retry attempt. Future Ordering's Payment Notifications endpoint is idempotent. If the Partner delivers the same event `id` more than once, the duplicate is ignored. The Partner is therefore safe to retry without risk of double-processing. #### Immediate Retries The first three retry attempts should occur in quick succession using exponential backoff with jitter. These are designed to handle brief transient failures and may be implemented in-process (e.g. an HTTP resilience policy). | Parameter | Value | |-----------|-------| | Attempts | 3 | | Base delay | 1 second | | Strategy | Exponential backoff with jitter | | Timeout per request | 20 seconds | #### Durable Retries If immediate retries are exhausted, the Partner must persist the event and continue delivery attempts from a durable mechanism that survives process restarts (e.g. a message queue or outbox pattern). An in-process retry policy alone is not sufficient. | Parameter | Value | |-----------|-------| | Delivery obligation | 24 hours from first attempt | | Strategy | Scheduled intervals with jitter | | Intervals | 1m, 5m, 15m, 30m, 1h, then every 2h | | Timeout per request | 20 seconds | If the Partner receives a `429` response with a `Retry-After` header, the indicated delay takes precedence over the backoff schedule. #### Exhausted Retries If all delivery attempts fail within the 24-hour window, the Partner must persist the undelivered event and surface the failure through its operational monitoring. Reconciliation procedures will be agreed upon during onboarding. If Future Ordering does not receive an event within the expected timeframe, it considers the operation failed. Late-arriving events are processed as reconciliation updates. ---