Swedish Swish payments are performed with the mobile Swish app and the BankID app. The Swish app can be started anonymously on the same device, or with a phone number specified for payment on any device with a matching setup – much the same way as the Swedish BankID login can be initiated with or without specifying a personal number. Two workflows exist: E-commerce (with phone number, any device) and M-commerce (without phone number, same device). E-commerce is suitable for web shops and M-commerce for mobile app integrations. For a detailed description over the differences see these graphics. All technical Swish documentation is found on developer.getswish.se/manuals. There you can also find the API reference. Notes:

  • New parameters: Validation of payerSSN and ageLimit will be available early 2019.
  • New use case: Swish pay out – /swishReimbursements will be available in Q3 2019. “Pay out” is a reversed standard payment flow with the money going from the merchant to the person. Technically it looks the same as /swishRefunds but without the originalPaymentReference parameter and without refund’s restrictions on the amount.

The prerequisites

  • For the merchant: Need to set up a bank account for receiving Swish payments, and also a certificate bound to the merchant’s name and finally set up callback endpoints on merchant side that will have the payment and refund results data POST:ed to.
  • For the user: The person needs to have a bank account connected to the swish service. Need to setup the Swish app and the BankID app on the same device. The Swish app will internally start up the BankID app on the same device for confirmation of the payment. Note: For testing of the swish service no swish app is needed – the swish server will answer with fabricated responses in the test environment.

API Calls

Payment initiation: POST to https://env.zignsec.com/v2/swishpayments Payment results: Callback or GET from https://env.zignsec.com/v2/swishpayments/{id} Refund initation: POST to https://env.zignsec.com/v2/swishrefunds Refund results: Callback or GET from https://env.zignsec.com/v2/swishrefunds/{id} … where env is api or test and id is the payment or refund request identifier retrieved from the initiation response’s location HTTP header.

Payment step 1. Create a payment request

Example of creating a payment request sent to a specific mobile phone number, 46776543210

POST https://test.zignsec.com/v2/swishpayments HTTP/1.1
Authorization: YOUR_KEY_HERE
Content-Type: application/json; charset=utf-8
Host: test.zignsec.com
Content-Length: 213
Connection: Keep-Alive

{
  "payerAlias": "46776543210",
  "payeePaymentReference": "235235076",
  "callbackUrl": "https://xyzcasino.com/callback",
  "amount": "100",
  "currency": "SEK",
  "message": "Kingston USB Flash Drive 8 GB"
}

Response Example (data in HTTP Headers)

Location: https://test.zignsec.com/v2/swishpayments/ADECC7EF970641B7A4325D87188D1BA1/

Payment request parameters

PropertyTypeDescriptionRequired
amountstringThe amount of money to pay. The amount cannot be less than 1 SEK and not more than 999999999999.99 SEK. Valid value has to be all numbers or with 2 digit decimalRequired
currencystringThe currency to use. Only supported value currently is SEK.Required
payeePaymentReferencestringInternal payment reference of the merchant’s. This could be an order id or similar. It should contain 1-35 characters.
payerAliasstringIf set the E-commerce workflow will run otherwise the M-commerce.
The registered Cell phone number of the person that makes the payment. It can only contain numbers and has to be at least 8 and at most 15 numbers. It also needs to match the following format in order to be found in Swish: country code + cell phone number (without leading zero). E.g.: 46712345678 If payerAlias is left out you must start swish app via the swish autostart url (= M-commerce workflow)
Build the start-url using the PaymentRequestToken from a header in the response to open the swish app, in the custom swish url scheme e.g.: swish://paymentrequest?token=f34DS34lfd0d03fdDselkfd3ffk21
messagestringA text description of the payment that will be presented to the paying person. Max 50 characters. Allowed characters are the letters a-o ̈, A-Ö, the numbers 0-9 and the special characters :;.,?!()”. For test environment this field is also used to trigger specific error responses – the errorCode as defined in section 0 can be set in the message property in order to simulate negative responses.
callbackUrlstringNeed not be used in production, since it is set through the merchant setting Swish_webhook_PROD The URL where Swish will notify the merchant of the outcome of the Payment request. The URL has to use HTTPS.
(payeeAlias)stringpayeeAlias should not be set: This is set statically for each merchant by Zignsec to swish number of the merchant, it is set in merchant setting Swish_PayeeAlias_TEST and Swish_PayeeAlias_PROD. “Swish number” is another name for a payeeAlias and it always starts with “123”. In test the Zignsec merchant’s payeealias of 1231181189 is automatically configured, and in prod Zignsec will set the payeeAlias when the agreement is signed and set up from the bank.
upcoming: payerSSNstringWill come first week in March 2019. For validation by Swish that this SSN-specified person is the one owning the payerAlias. The response error code when wrong SSN was used will be VR02.
upcoming: ageLimitintWill come first week in March 2019. For validation by Swish that the person paying has the given minimum age. The response error code when person was underage will be VR01.

Payment response fields

PropertyTypeDescription
LocationstringThe URL where to check payment status. The recommendation is to rely on the callback url instead, which will have results automatically POST:ed to.
PaymentRequestTokenstringMostly relevant for M-commerce. The PaymentRequestToken that is needed to open the swish app, binding the app to the specific payment request. Used with the custom URL scheme e.g.: swish://paymentrequest?token=f34DS34lfd0d03fdDselkfd3ffk21

Payment step 2. Retrieve payment results

Data will be sent to the webhook URL that set through ZignSec setting swish_webhook_test/swish_webhook_prod or through the callbackUrl parameter in the request call.

Callback example

{
  "id": "D8DB6C74849243C3B93F5A8213D41795",
  "payeePaymentReference": "0123456789",
  "paymentReference": "92BC9BA471B142B68A68B5FE4DB45ECA",
  "callbackUrl": "https://xyzcasino.com/callback",
  "payerAlias": "46776543210",
  "payeeAlias": "1231181189",
  "currency": "SEK",
  "message": "Kingston USB Flash Drive 8 GB",
  "errorMessage": "",
  "status": "PAID",
  "amount": "100",
  "dateCreated": "2019-01-24T09:19:36.373+0000",
  "datePaid": "2019-01-24T09:19:40.373+0000",
  "errorCode": null
}

Example of GET payment status

GET https://test.zignsec.com/v2/swishpayments/ADECC7EF970641A7A4325D81188D1BA1/ HTTP/1.1
Host: test.zignsec.com

Callback model and GET response model have almost the same structure, with following differences:

  • amount is string type in callback, but float type in GET response

Callback field Description

PropertyTypeDescription
idstringPayment request ID
payeePaymentReferencestringPayment reference of the payee, which is the merchant that receives the payment. This reference could be order id or similar.
paymentReferencestringPayment reference, from the bank, of the payment that occurred based on the Payment request. Only available if status is PAID.
callbackUrlstringURL that Swish will use to notify caller about the outcome of the Payment request. The URL has to use HTTPS.
payerAliasstringThe registered Cell phone number of the person that makes the payment. It can only contain numbers and has to be at least 8 and at most 15 numbers. It also needs to match the following format in order to be found in Swish: countrycode + cell phone number (without leading zero). E.g.:46712345678
payeeAliasstringThe Swish number of the payee
amountstringThe amount of money to pay. The amount cannot be less than 1 SEK and not more than 999999999999.99 SEK. Valid value have to be all numbers or with 2 digit decimal seperated with a period.
currencystringThe currency to use. Only supported value currently is SEK.
messagestringMerchant supplied message about the payment/order. Max 50 chars. Allowed characters are the letters a-ö, A-Ö, the numbers 0-9 and the special characters :;.,?!()”.
statusstringThe status of the transaction. Possible values: CREATED, PAID, DECLINED, ERROR.
dateCreatedstringThe time and date that the payment request was created.
datePaidstringThe time and date that the payment request was paid. Only applicable if status was PAID.
errorCodestringA code indicating what type of error occurred. Only applicable if status is ERROR.
errorMessagestringA descriptive error message (in English) indicating what type of error occurred. Only applicable if status is ERROR
additionalInformationstringAdditional information about the error. Only applicable if status is ERROR.

Refund step 1. Create a Refund request

Example of creating a Refund request for an earlier payment with id D8DB6C74849243C3B93F5A8213D41795

POST https://test.zignsec.com/v2/swishrefunds HTTP/1.1
Authorization: YOUR_KEY_HERE 
Content-Type: application/json; charset=utf-8
Host: test.zignsec.com
Content-Length: 322
Expect: 100-continue
Connection: Keep-Alive

{
  "payeeAlias": "46776543210",
  "payerPaymentReference": "0123456789",
  "originalPaymentReference": "D8DB6C74849243C3B93F5A8213D41795",
  "callbackUrl": "https://xyzcasino.com/callback",
  "amount": "100",
  "currency": "SEK",
  "message": "Refund for Kingston USB Flash Drive 8 GB"
}

Refund response example (data in HTTP Headers)

Location:https://test.zignsec.com/v2/swishrefunds/ADECC7EF970641A7A4325D81188D1BA1/

Refund request parameters

Note that the contents of payerAlias and payeeAlias are reversed during a Refund call. So it is the recipient’s mobile number that should be put in payeeAlias now.. The payerAlias field is the merchant’s swish number, and need not be set since is a static merchant configuration.

PropertyTypeDescriptionRequired
originalPaymentReferencestringPayment reference to the original payment that this refund is for.Required
currencystringThe currency to use. Only supported value currently is SEK.Required
amountstringThe amount of money to pay. The amount cannot be less than 1 SEK and not more than 999999999999.99 SEK. Valid value have to be all numbers or with 2 digit decimal seperated with a period.Required
payeeAliasstringThe registered Cell phone number of the person that makes the refund. It can only contain numbers and has to be at least 8 and at most 15 numbers. It also needs to match the following format in order to be found in Swish: countrycode + cell phone number (without leading zero). For example 46712345678Required
payerPaymentReferencestringPayment reference of the payee, which is the merchant that receives the payment. This reference could be order id or similar. 
messagestringMerchant supplied message about the payment/order. Max 50 chars. Allowed characters are the letters a-ö, A-Ö, the numbers 0-9 and the special characters :;.,?!()”. 
callbackUrlstringNeed not be used in production, since it is set through the merchant setting Swish_Webhook_Refund_PROD The URL where Swish will notify the merchant of the outcome of the Refund request. The URL has to use HTTPS. 
(payerAlias)stringpayerAlias should not be set: During a Refund the payerAlias equals the Merchant’s swish number – the static configuration in Swish_PayeeAlias_TEST and Swish_PayeeAlias_PROD

Refund step 2. Retrieve refund results

The webhook url which will receive the refund results is set in ZignSec setting Swish_Webhook_Refund_{env} or in the callbackUrl parameter in the refund request.

Callback example

{
  "amount": "100.00",
  "originalPaymentReference": "D8DB6C74849243C3B93F5A8213D41795",
  "dateCreated": "2019-01-30T09:44:15.296+0000",
  "datePaid": "2019-01-30T09:44:23.381+0000",
  "payerPaymentReference": null,
  "payerAlias": "1231181189",
  "callbackUrl": "https://xyzcasino.com/callback",
  "currency": "SEK",
  "id": "5B71F1BF4B3C4DF09DD084A22806F32F",
  "payeeAlias": "4671234768",
  "message": "Refund for Kingston USB Flash Drive 8 GB",
  "status": "PAID"
}

GET status of a Refund

GET https://test.zignsec.com/v2/swishrefunds/{SESSION_IDENTIFIER}/ HTTP/1.1
Host: test.zignsec.com

Callback model and GET response model have almost the same structure, with following differences:

  • amount is string type in callback, but float type in GET response

Callback field Description

PropertyTypeDescription
payeePaymentReferencestringPayment reference of the payee, which is the merchant that receives the payment. This reference could be order id or similar.
callbackUrlstringURL that Swish will use to notify caller about the outcome of the Payment request. The URL has to use HTTPS.
payerAliasstringThe registered Cell phone number of the person that makes the payment. It can only contain numbers and has to be at least 8 and at most 15 numbers. It also needs to match the following format in order to be found in Swish: countrycode + cell phone number (without leading zero). E.g.:n46712345678
payeeAliasstringThe Swish number of the payee
amountstringThe amount of money to pay. The amount cannot be less than 1 SEK and not more than 999999999999.99 SEK. Valid value have to be all numbers or with 2 digit decimal seperated with a period.
currencystringThe currency to use. Only supported value currently is SEK.
messagestringMerchant supplied message about the payment/order. Max 50 chars. Allowed characters are the letters a-ö, A-Ö, the numbers 0-9 and the special characters :;.,?!()”.
idstringPayment request ID
paymentReferencestringPayment reference, from the bank, of the payment that occurred based on the Payment request. Only available if status is PAID.
statusstringThe status of the transaction. Possible values: CREATED, PAID, DECLINED, ERROR.
dateCreatedstringThe time and date that the payment request was created.
datePaidstringThe time and date that the payment request was paid. Only applicable if status was PAID.
errorCodestringA code indicating what type of error occurred. Only applicable if status is ERROR.
errorMessagestringA descriptive error message (in English) indicating what type of error occurred. Only applicable if status is ERROR
additionalInformationstringAdditional information about the error. Only applicable if status is ERROR.

Possible HTTP status codes after Payment

HTTP status codesReturned scenarios
201 CreatedReturned when Payment request was successfully created. Will return a Location header and if it is M-Commerce case, it will also return PaymentRequestToken header.
400 Bad RequestReturned when the Create Payment Request operation was malformed. Can return an Array of Error Objects.
401 UnauthorizedReturned when there are authentication problems with the certificate. Or the Swish number in the certificate is not enrolled. Will return nothing else.
403 ForbiddenReturned when the payeeAlias in the payment request object is not the same as Merchants Swish-number.
415 Unsupported Media TypeReturned when Content-Type header is not “application/json”. Will return nothing else.
422 Unprocessable EntityReturned when there are validation errors. Will return an Array of Error Objects.
500 Internal Server ErrorReturned if there was some unknown/unforeseen error that occurred on the server, this should normally not happen. Will return nothing else.

List of possible error codes

List of possible error codes for Status Code 422

Error codesDescriptionPossible return in callback
FF08PayeePaymentReference is invalidN
BE18Payer alias is invalid. Note: Configuration error payer not well formed.N
PA02Amount value is missing or not a valid numberN
AM06Amount value is too lowN
AM02Amount value is too largeN
AM03Invalid or missing CurrencyN
RP02Wrong formatted message Note: Not expected, covered by error code ZS501N
RP06Another active ongoing PaymentRequest already exists for this payerAlias. Only applicable for E-Commerce. Note:The request will be canceled with this error code. The ongoing PaymentRequest will be active for 3 minutes when it reaches timeout or if the payer ends it within this timeframe.N
ACMT03Payer not EnrolledY
ACMT01Counterpart is not activated. Note:The payer’s app has been deactivated by the payer by activating the service on another unit or the bank has deactivated the app or terminated the service.Y
ACMT07Payee not Enrolled. Note: Phone number not configured with Swish.Y
RF07Transaction declinedY
BANKIDCLPayer cancelled BankId signingY
FF10Bank system processing errorY
TM01Swish timed out before the payment was startedY
DS24Swish timed out waiting for an answer from the banks after payment was started. Note: If this happens Swish has no knowledge of whether the payment was successful or not. The Merchant should inform its consumer about this and recommend them to check with their bank about the status of this payment.Y
BANKIDONGOINGBankID already in use.Y
BANKIDUNKNBankID is not able to authorize the payment.Y
(RP03)(Callback URL is missing or does not use Https) Handled by ZS103 and ZS104N
(RP01)(Payee alias is missing or empty) Handled by ZS105N
(PA06)(Upcoming, parameter payerSSN invalid, bad formatted SSN validation parameter.)N
(PA08)(Upcoming, parameter ageLimit invalid, not valid value of ageLimit parameter.)N
(VA02)(Upcoming, payerSSN-validation – the payerAlias owner not same SSN.)N
(VA01)(Upcoming, ageLimit validation – the payerAlias owner is under the ageLimit.)N

List of possible error codes for Status Code 400

Error codesDescriptionPossible return in callback
ZS100Authorization header is missingN
ZS101Authorization header is invalidN
ZS102No Merchant found with Authorization headerN
ZS103Callback URL is invalid or missingN
ZS104Callback URL HTTPS is requiredN
ZS105Swish_PayeeAlias not configured on ZignSec sideN
ZS106Swish_CertificateThumbprint not configured on ZignSec sideN
ZS107Swish_RootCAThumbprint not configured on ZignSec sideN
ZS108Client Certificate not configured on ZignSec sideN
ZS200payeeAlias field should be empty Note: Parameter not in use – a Zignsec merchant must preconfigure a payeeAlias.N
ZS201Payment session ID is not foundN
ZS300Payment with following originalPaymentReference not found in refundN
ZS301Refund session ID is not foundN
ZS500Unknown Exception – {Additional information}N
ZS501The request JSON is not well formedN

Error response

400 or 422 Status code – Returned when there are errors. Will return an Array of Error Objects

Sample of Error Response

{
  "errors": [
    {
      "code": "PA02",
      "description": "Amount value is missing or not a valid number"
    },
    {
      "code": "AM03",
      "description": "Invalid or missing Currency"
    },
    {
      "code": "RF08",
      "description": "Amount value is too large or amount exceeds the amount of the original payment minus any previous refunds"
    }
  ]
}