XML API for @handelsbanken

First of all, this information is provided by me @bjornsallarp as a result of my private investigations. Noone has assisted me or disclosed any details regarding the implementation at Handelsbanken. I have no association with Handelsbanken, in fact, I'm not even a customer with them.

Handelsbanken has not publically announced this API, this is the API they use for their iPhone application. I would really like for all banks to publish public APIs and let users access their own personal information.

Table of contents

  1. Security features of the API
  2. Offices
  3. Interest rates
  4. Authentication
  5. Accounts
  6. Credit cards
  7. Logging out

1 Security features of the API

Handelsbanken has not gone to great lengths to prevent us from using this API. They require three headers that must be sent with every request:

Device model doesn't nessesarily need to conform to this format, "hejsan!" worked as value when i tested. Their iPhone application also sends a custom User-Agent that propbably makes sense to conform to: Mobilbank/1.2 CFNetwork/548.0.3 Darwin/11.0.0.

When authentication is successful a token is returned together with a sessions cookie. For GET requests the authToken is passed in the URL and for POST requests it's passed along with the other form values. Content-Type for all POST requests is: application/x-www-form-urlencoded are

2.1 Office search

POST                  https://m.handelsbanken.se/app//office-search
TEXT SEARCH BODY    : searchParam=tranås&nearU=false
LOCATION SEARCH BODY: longitude=18.059718&latitude=59.349545&nearU=true&category=-1
            
RESPONSE:
<response code="000" label="OK"> 
	<offices> 
		<office> 
			<clearing>6648</clearing> 
			<name>Tranås</name> 
			<address>Storgatan 28</address> 
			<city>Tranås</city> 
			<phone>0140-385440</phone> 
			<open>må-on 9.30-16, to 9.30-18, fr 9.30-16</open> 
			<category>-2</category> 
			<latitude /> 
			<longitude /> 
			<distance /> 
		</office> 
	</offices> 
	<zoomSpan> 
		<longitudeDelta>0.01</longitudeDelta> 
		<latitudeDelta>0.01</latitudeDelta> 
	</zoomSpan> 
</response>
        

There are two possibilities here. Either search using free-text or by GPS location.
There's a category parameter when searching using GPS location. -1 means both offices and ATMs. 1 = Offices only. 2 = ATMs.

2.2 Office details

POST     https://m.handelsbanken.se/app//office-detail
BODY:    clearingNumber=6648

RESPONSE:
<response code="000" label="OK"> 
	<offices> 
		<office> 
			<clearing>6648</clearing> 
			<name>Tranås</name> 
			<address>Storgatan 28</address> 
			<city>Tranås</city> 
			<phone>0140-385440</phone> 
			<open>må-on 9.30-16, to 9.30-18, fr 9.30-16</open> 
			<category>1</category> 
			<latitude>58.03514099121094</latitude> 
			<longitude>14.976479530334473</longitude> 
			<distance>0.0</distance> 
		</office> 
		<office> 
			<clearing>6648-20</clearing> 
			<name>SHB</name> 
			<address>Storg 28</address> 
			<city>Tranås</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>58.03501510620117</latitude> 
			<longitude>14.97634506225586</longitude> 
			<distance>16.070812225341797</distance> 
		</office> 
		<office> 
			<clearing>6618-20</clearing> 
			<name>SHB</name> 
			<address>Bryggerigatan 12</address> 
			<city>Hultsfred</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>57.488033294677734</latitude> 
			<longitude>15.841794967651367</longitude> 
			<distance>79544.296875</distance> 
		</office> 
		<office> 
			<clearing>6672-20</clearing> 
			<name>SHB</name> 
			<address>Stora torget</address> 
			<city>Falköping</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>58.160736083984375</latitude> 
			<longitude>13.554816246032715</longitude> 
			<distance>84645.6953125</distance> 
		</office> 
		<office> 
			<clearing>6598-20</clearing> 
			<name>SHB</name> 
			<address>Bergslagsv 9</address> 
			<city>Finspång</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>58.70730209350586</latitude> 
			<longitude>15.774603843688965</longitude> 
			<distance>87989.9296875</distance> 
		</office> 
		<office> 
			<clearing>6593-80</clearing> 
			<name>SHB</name> 
			<address>Slåttergatan 106</address> 
			<city>Norrköping</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>58.60360336303711</latitude> 
			<longitude>16.144941329956055</longitude> 
			<distance>92953.21875</distance> 
		</office> 
		<office> 
			<clearing>6596-80</clearing> 
			<name>SHB</name> 
			<address>Hageby centrum</address> 
			<city>Norrköping</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>58.57255172729492</latitude> 
			<longitude>16.209123611450195</longitude> 
			<distance>93518.28125</distance> 
		</office> 
		<office> 
			<clearing>6707-20</clearing> 
			<name>SHB</name> 
			<address>Emmabodav 1</address> 
			<city>Nybro</city> 
			<phone /> 
			<open /> 
			<category>2</category> 
			<latitude>56.74229431152344</latitude> 
			<longitude>15.900981903076172</longitude> 
			<distance>153963.921875</distance> 
		</office> 
	</offices> 
	<zoomSpan> 
		<longitudeDelta>0.01</longitudeDelta> 
		<latitudeDelta>0.01</latitudeDelta> 
	</zoomSpan> 
</response>
        

The list is shortened here because it's damn long!

3. Interest rates

GET https://m.handelsbanken.se/app//interests
        
RESPONSE:
<response code="000" label="OK"> 
	<validTo>2011-10-29</validTo> 
	<rates> 
		<rate period="3 månader" value="4,39%" /> 
		<rate period="1 år" value="4,39%" /> 
		<rate period="2 år" value="4,20%" /> 
		<rate period="3 år" value="4,32%" /> 
		<rate period="5 år" value="4,79%" /> 
		<rate period="8 år" value="5,03%" /> 
		<rate period="10 år" value="5,20%" /> 
	</rates> 
	<maxRateBind>5 år</maxRateBind> 
	<maxRateCurrent>4,82%</maxRateCurrent> 
	<maxRateTop>5,75%</maxRateTop> 
	<maxRateUpdate>3</maxRateUpdate> 
</response>
        

4. Authentication

POST  https://m.handelsbanken.se/app//login
BODY: username=8209250000&pin=1234&deviceid=f8280cf34708c7b5a8bd2ed93dcd3c814800000

RESPONSE HEADER: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2; Path=/;Secure;HttpOnly
RESPONSE:
<response code="000" label="OK"> 
	<authToken>ecfdd82164e954ae57711f7969e13155</authToken> 
</response>
        

Oh happy day! The token and cookie needed for authenticating other requests!

5.1 List accounts

GET     https://m.handelsbanken.se/app//accounts?authToken=ecfdd82164e954ae57711f7969e13155
HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2

RESPONSE:
<response code="000" label="OK"> 
	<accounts> 
		<account> 
			<accountId>1</accountId> 
			<accountName>Allkonto</accountName> 
			<accountNumber>00000000</accountNumber> 
			<accountNumberModified>53 *** 018</accountNumberModified> 
			<typeAccount>1</typeAccount> 
			<accountAmount>1 125,43</accountAmount> 
			<accountBalance>1 125,43</accountBalance> 
		</account> 
		<account> 
			<accountId>2</accountId> 
			<accountName>Allkonto</accountName> 
			<accountNumber>00000000</accountNumber> 
			<accountNumberModified>165 *** 212</accountNumberModified> 
			<typeAccount>1</typeAccount> 
			<accountAmount>1 125,32</accountAmount> 
			<accountBalance>1 125,32</accountBalance> 
		</account> 
		<account> 
			<accountId>3</accountId> 
			<accountName>Sparkonto</accountName> 
			<accountNumber>00000000</accountNumber> 
			<accountNumberModified>254 *** 378</accountNumberModified> 
			<typeAccount>1</typeAccount> 
			<accountAmount>1 125,00</accountAmount> 
			<accountBalance>1 125,00</accountBalance> 
		</account> 
	</accounts> 
</response>
        

Response information (such as account numbers etc) has been altered to anonymize it.

5.2 List transactions

POST    https://m.handelsbanken.se/app//transactions
HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2
BODY:   authToken=ecfdd82164e954ae57711f7969e13155&type=1&account=1&accountType=1

RESPONSE:
<response code="000" label="OK"> 
	<account> 
		<accountId>1</accountId> 
		<accountName>Allkonto</accountName> 
		<accountNumber>00000000</accountNumber> 
		<accountNumberModified>53 *** 018</accountNumberModified> 
		<typeAccount>1</typeAccount> 
		<accountAmount>1 399,43</accountAmount> 
		<accountBalance>1 399,43</accountBalance> 
	</account> 
	<transactions> 
		<transactionCardTransactions>false</transactionCardTransactions> 
		<transaction> 
			<transactionDate> 2011-10-29</transactionDate> 
			<transactionAmount>-130,00</transactionAmount> 
			<transactionDescription>Prel kortköp</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-29</transactionDate> 
			<transactionAmount>-75,35</transactionAmount> 
			<transactionDescription>Prel kortköp</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-29</transactionDate> 
			<transactionAmount>-398,00</transactionAmount> 
			<transactionDescription>Prel kortköp</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-28</transactionDate> 
			<transactionAmount>-159,00</transactionAmount> 
			<transactionDescription>Prel kortköp</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-28</transactionDate> 
			<transactionAmount>-317,54</transactionAmount> 
			<transactionDescription>Prel kortköp</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-28</transactionDate> 
			<transactionAmount>-150,00</transactionAmount> 
			<transactionDescription>RÄDDA BARNEN</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-25</transactionDate> 
			<transactionAmount>120,00</transactionAmount> 
			<transactionDescription>ELIN PRESENT</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-22</transactionDate> 
			<transactionAmount>-104,10</transactionAmount> 
			<transactionDescription>HEMKOP</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-20</transactionDate> 
			<transactionAmount>-358,00</transactionAmount> 
			<transactionDescription>KICKS FALTOVER</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-20</transactionDate> 
			<transactionAmount>-63,11</transactionAmount> 
			<transactionDescription>VIDEOMIX</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
		<transaction> 
			<transactionDate> 2011-10-14</transactionDate> 
			<transactionAmount>-500,00</transactionAmount> 
			<transactionDescription>SANGRIA TAPAS</transactionDescription> 
			<transactionType>1</transactionType> 
		</transaction> 
	</transactions> 
</response>
        

The list is shortened here because it's damn long!
Response information (such as account numbers etc) has been altered to anonymize it.

5.3 List accounts to transfer money between

GET     https://m.handelsbanken.se/app//transfer?authToken=ecfdd82164e954ae57711f7969e13155
HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2

RESPONSE:
<response code="000" label="OK"> 
	<control href="transfer-status" /> 
	<fromAccounts> 
		<accounts> 
			<account> 
				<accountId>0</accountId> 
				<accountName>Allkonto</accountName> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>53 *** 018</accountNumberModified> 
				<typeAccount>1</typeAccount> 
				<accountAmount>1 125,43</accountAmount> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>1</accountId> 
				<accountName>Allkonto</accountName> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>165 *** 212</accountNumberModified> 
				<typeAccount>1</typeAccount> 
				<accountAmount>1 125,32</accountAmount> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>2</accountId> 
				<accountName>Sparkonto</accountName> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>254 *** 378</accountNumberModified> 
				<typeAccount>1</typeAccount> 
				<accountAmount>1 125,00</accountAmount> 
				<accountBalance /> 
			</account> 
		</accounts> 
	</fromAccounts> 
	<toAccounts> 
		<accounts> 
			<account> 
				<accountId>0</accountId> 
				<accountName>Allkonto</accountName> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>53 *** 018</accountNumberModified> 
				<typeAccount>1</typeAccount> 
				<accountAmount /> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>1</accountId> 
				<accountName>Allkonto</accountName> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>165 *** 212</accountNumberModified> 
				<typeAccount>1</typeAccount> 
				<accountAmount /> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>2</accountId> 
				<accountName>Sparkonto</accountName> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>254 *** 378</accountNumberModified> 
				<typeAccount>1</typeAccount> 
				<accountAmount /> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>3</accountId> 
				<accountName /> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>53 *** 018</accountNumberModified> 
				<typeAccount /> 
				<accountAmount /> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>4</accountId> 
				<accountName /> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>165 *** 212</accountNumberModified> 
				<typeAccount /> 
				<accountAmount /> 
				<accountBalance /> 
			</account> 
			<account> 
				<accountId>5</accountId> 
				<accountName /> 
				<accountNumber>000000</accountNumber> 
				<accountNumberModified>254 *** 378</accountNumberModified> 
				<typeAccount /> 
				<accountAmount /> 
				<accountBalance /> 
			</account> 
		</accounts> 
	</toAccounts> 
</response>
        

5.4 Transfer money between accounts

This is a two step rocket.

  1. POST     https://m.handelsbanken.se/app//transfer-status
    HEADER:  Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2
    BODY:    authToken=ecfdd82164e954ae57711f7969e13155&annotation=Björn testar&accountFromNr=1&message=Meddelande test&amount=100&accountToNr=0
    
    RESPONSE:
    <response code="000" label="OK"> 
    	<commit href="transfer-result" /> 
    </response>
                    

    This sets up the transfer for confirmation. I'm transfering 100 SEK from account 1 to account 0. The message is "Meddelande test" and shows up with the money on the incoming account. The annotation text "Björn testar" shows up with the withdrawl in the outgoing account.

  2. GET      https://m.handelsbanken.se/app//transfer-result?authToken=ecfdd82164e954ae57711f7969e13155
    HEADER:  Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2
    
    RESPONSE:
    <response code="000" label="OK"> 
    </response>
    

    Money transfered!

6.1 List credit cards

GET     https://m.handelsbanken.se/app//card-list?authToken=ecfdd82164e954ae57711f7969e13155
HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2

RESPONSE:
<response code="000" label="OK"> 
	<cards> 
		<card> 
			<cardName>Bankkort VISA</cardName> 
			<queueNumber>01</queueNumber> 
			<cardNumber>4263 **** **** 9112</cardNumber> 
			<accountNumber>53 *** 018</accountNumber> 
			<accountName /> 
			<cardStatusInternet>1</cardStatusInternet> 
			<cardStatusAbroad>1</cardStatusAbroad> 
		</card> 
	</cards> 
</response>
        

6.2 Update credit card settings

POST    https://m.handelsbanken.se/app//card-list
HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2
BODY:   authToken=ecfdd82164e954ae57711f7969e13155&queueNumber=01&toggleAbroad=true&toggleInternet=false

RESPONSE:
<response code="000" label="OK"> 
	<cards> 
		<card> 
			<cardName>Bankkort VISA</cardName> 
			<queueNumber>01</queueNumber> 
			<cardNumber>4263 **** **** 9112</cardNumber> 
			<accountNumber>53 *** 018</accountNumber> 
			<accountName /> 
			<cardStatusInternet>1</cardStatusInternet> 
			<cardStatusAbroad>0</cardStatusAbroad> 
		</card> 
	</cards> 
</response>
        

Obviously the toggleAbroad and toggleInternet parameters turns either on or off the functionality. The response is updated credit card information.

7 Logging out

GET    https://m.handelsbanken.se/app//logout?authToken=ecfdd82164e954ae57711f7969e13155
HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2

RESPONSE:
<response code="000" label="OK"> 
	<loggedIn>false</loggedIn> 
</response>