API Integration
Overview
Section titled “Overview”Sawfish Payment APIs are built in GraphQL (except the generate token and refresh token endpoints, which are REST).
To use the API integration, follow the User Flow Guide and refer to the API Reference.
Authentication & Headers
Section titled “Authentication & Headers”To obtain your x-client-id and x-api-key, please contact the Sawfish team.
These key-value pairs are required in specific requests to Sawfish’s RESTful and GraphQL APIs.
| Header name | Description | Required for | Example |
|---|---|---|---|
Content-Type |
Request content type | All requests | application/json |
Accept |
Expected response format | All requests | application/json |
x-client-id |
Client ID from App Integration settings | REST token endpoints | your-client-id |
x-api-key |
API Key | REST token endpoints | your-api-key |
x-jwt-token |
JWT token (expires after 10 minutes) | GraphQL requests | your-jwt-token |
Request Body Structure for GraphQL
Section titled “Request Body Structure for GraphQL”{ "query": "GraphQL query/mutation string", "variables": { "variable1": "value1", "variable2": "value2" }}Generate Token
Section titled “Generate Token”This generates an access token that is valid for 10 minutes. This endpoint should be called only once. After obtaining the refresh_token, use the /token/refresh-token API to get a new access token.
Endpoint: POST https://{{sawfish_domain}}/api/v2/accounting/token/generate-token
Headers:
x-client-idx-api-key
Sample success response:
{ "status": "SUCCESS", "data": { "token": "your_token", "refresh_token": "your_refresh_token", "expiration": 1691123100 }}Sample error response (error code can be 401 or 500):
{ "status": "ERROR", "message": "Sample error message"}Refresh Token
Section titled “Refresh Token”Endpoint: POST https://{{sawfish_domain}}/api/v2/accounting/token/refresh-token
Headers:
x-client-idx-api-key
Body params:
{ "refresh_token": "your_refresh_token"}Sample success response:
{ "status": "SUCCESS", "data": { "token": "your_token", "refresh_token": "your_refresh_token", "expiration": 1691123100 }}Sample error response (error code can be 401 or 500):
{ "status": "ERROR", "message": "Sample error message"}Fetch Payment Gateway Fees
Section titled “Fetch Payment Gateway Fees”Purpose: Get a list of fee calculations based on payment amount and card types.
GraphQL Query: paymentGatewayFeesCalc
query paymentGatewayFeesCalc($amount: Float!) { paymentGatewayFeesCalc(amount: $amount) { amount fees total_settlement_amount card_type }}Response structure:
interface PaymentGatewayFeesCalcResponse { amount: number; fees: number; total_settlement_amount: number; card_type: string;}// Returns: PaymentGatewayFeesCalcResponse[]Fetch Payment Gateway Fee of Credit Card
Section titled “Fetch Payment Gateway Fee of Credit Card”Purpose: Get a fee calculation based on the payment amount and the credit card details provided.
GraphQL Query: paymentCreditCardFeeCalc
query paymentCreditCardFeeCalc($amount: Float!, $credit_card: CreditCardInput!, $contact: ContactInput!) { paymentCreditCardFeeCalc(amount: $amount, credit_card: $credit_card, contact: $contact) { amount fees total_settlement_amount card_account_uid card_type }}Interfaces:
interface CreditCardInput { full_name: string; // required unless card_account_uid is provided card_number: string; // required unless card_account_uid is provided expiry_month: string; // 2 digits, e.g. "01" - required unless card_account_uid is provided expiry_year: string; // 2 digits, e.g. "30" for 2030 - required unless card_account_uid is provided cvv: string; // 3-4 digits - required unless card_account_uid is provided card_account_uid?: string; // pay with a previously returned card account instead of raw card details}
interface ContactInput { first_name: string; // required last_name: string; // required email: string; // required country?: string; address_line1?: string; city?: string; state?: string; zip?: string; phone?: string;}Response structure:
interface PaymentCreditCardFeeCalcResponse { amount: number; fees: number; total_settlement_amount: number; card_type: string; card_account_uid: string;}Process Payment
Section titled “Process Payment”Purpose: Processes payment via the Sawfish platform. It will try to validate the credit card details before processing the payment. An error may be returned regarding an invalid credit card to avoid processing the payment.
GraphQL Mutation: processPaymentRequest
mutation processPaymentRequest($input: ProcessPaymentInput!) { processPaymentRequest(input: $input) { amount payment_gateway_fee paid_at status { name } uuid }}Input interfaces:
interface ProcessPaymentRequestInput { credit_card: CreditCardInput; // required amount: number; // required, minimum 0.01 fees: number; // required, minimum 0 contact: ContactInput; // required payment_reference: PaymentReferenceInput; // required metadata?: object; // optional JSON, echoed back in the payment webhook}
interface PaymentReferenceInput { description: string; // required, max 1000 characters reference_no: string; // required, max 100 characters}CreditCardInput and ContactInput are the same as for fee calculation.
Response structure:
interface ProcessPaymentResponse { amount: number; payment_gateway_fee: number; paid_at: string; status: { name: string }; uuid: string;}Payment Webhook
Section titled “Payment Webhook”Purpose: After a payment is processed, the initial status simply confirms that the payment request has been initiated. Credit card transactions may take some time to fully process. To track the final status - whether the payment succeeds or fails - it is essential to register a webhook URL (contact the Sawfish team to configure this) where Sawfish can send status updates to your system.
Sample webhook URL: https://{{your_domain}}/webhook/payments
When the webhook is triggered, Sawfish will send a request containing the payment payload along with HTTP headers that include the webhook signing key and client ID.
Payload structure:
{ "type": "payment_update", "uuid": "payment-uuid-1234", "payment_gateway_fee": 1.75, "paid_at": "2025-09-17T08:35:00Z", "status": "completed", "total_amount": 100, "reference": null, "transaction_id": "100014223834147", "payment_brand": "visa", "metadata": null, "description": "invoice-1234", "failed_reason": null, "created_at": "2025-09-17T08:30:00Z", "updated_at": "2025-09-17T08:35:00Z"}Timestamps (paid_at, created_at, updated_at) are in UTC.
Error Handling
Section titled “Error Handling”General error structure:
{ "errors": [ { "message": "Error description", "extensions": { "reason": "ERROR_CODE" } } ]}Sample validation errors:
{ "errors": [ { "message": "Validation failed for the field [processPaymentRequest].", "extensions": { "validation": { "input.contact": ["Contact information is required."], "input.credit_card.expiry_year": ["Expiry year cannot be in the past."] }, "category": "validation" } } ]}Optional: Credit Card Validation (Work in progress)
Section titled “Optional: Credit Card Validation (Work in progress)”Purpose: This is an optional endpoint used to validate credit card details.
GraphQL Mutation: creditCardValidation

