Feedback
api_help@qiwi.com
NAV Navbar
cURL PHP Python Request/Response

Introduction

Last update: 2020-07-28 | Edit on GitHub

QIWI Wallet API makes it easy to automate getting info on your account's state in QIWI Wallet service and making financial operations.

API uses HTTPS requests and JSON-formatted responses.

API methods are accessible after the user is registered in QIWI Wallet service.

Service data

Parameter Description Type
token Token to authorize API requests. Token is valid within one month after its issuing. String

API Access

Main URL address to call API methods (unless explicitly stated):

https://edge.qiwi.com

To make a successful request of API methods, you need:

Authorization

Authorization data

QIWI Wallet API implements OAuth 2.0 open authorization protocol specification. A user registers or authenticates on https://qiwi.com QIWI Wallet site and requests a token with a certain scopes. Token issue is confirmed by SMS code.

How to get a token

  1. Open https://qiwi.com/api page in your browser. You will need to register or authenticate on QIWI Wallet service. Token Issue
  2. Click on Выпустить новый токен (please note, interface is Russian only). Select token scopes in the pop-up window:
  3. Click Продолжить, confirm a token issuing and enter confirmation code from SMS. Token Accept
  4. Copy token string and save it in secure place. Use the token in all QIWI Wallet API requests which require authorization.

Token

Authorization example

user@server:~$ curl "server address"
  --header "Authorization: Bearer jMyN22DQxMjM6NDUzRmRnZDQ0Mw11212e"

U1QtOTkwMTAyLWNud3FpdWhmbzg3M

Authorization: Bearer U1QtOTkwMTAyLWNud3FpdWhmbzg3M

User's Profile API

Last update: 2020-07-28 | Edit on GitHub

The API returns information about your profile - a set of user data and settings of your QIWI Wallet.

Request → GET

user@server:~$ curl "https://edge.qiwi.com/person-profile/v1/profile/current?authInfoEnabled=false" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9"
GET /person-profile/v1/profile/current HTTP/1.1
Accept: application/json
Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9
Content-type: application/json
Host: edge.qiwi.com
import requests

# User profile
def get_profile(api_access_token):
    s7 = requests.Session()
    s7.headers['Accept']= 'application/json'
    s7.headers['authorization'] = 'Bearer ' + api_access_token
    p = s7.get('https://edge.qiwi.com/person-profile/v1/profile/current?authInfoEnabled=true&contractInfoEnabled=true&userInfoEnabled=true')
    return p.json()
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# Full info
profile = get_profile(api_access_token)

# Blocking status
profile['contractInfo']['blocked']

# Identification level
profile['contractInfo']['identificationInfo'][0]['identificationLevel']

# Linked email
profile['authInfo']['boundEmail']
Parameter Type Description
authInfoEnabled Boolean Flag to get authorization settings.
By default, true
contractInfoEnabled Boolean Flag to get your QIWI wallet data.
By default, true
userInfoEnabled Boolean Flag to get other user data.
By default, true

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "authInfo": {
    "boundEmail": "m@ya.ru",
    "ip": "81.210.201.22",
    "lastLoginDate": "2017-07-27T06:51:06.099Z",
    "mobilePinInfo": {
      "lastMobilePinChange": "2017-07-13T11:22:06.099Z",
      "mobilePinUsed": true,
      "nextMobilePinChange": "2017-11-27T06:51:06.099Z"
    },
    "passInfo": {
      "lastPassChange": "2017-07-21T09:25:06.099Z",
      "nextPassChange": "2017-08-21T09:25:06.099Z",
      "passwordUsed": true
    },
    "personId": 79683851815,
    "pinInfo": {
      "pinUsed": true
    },
    "registrationDate": "2017-01-07T16:51:06.100Z"
  },
  "contractInfo": {
    "blocked": false,
    "contractId": 79683851815,
    "creationDate": "2017-01-07T16:51:06.100Z",
    "features": [
      ...
    ],
    "identificationInfo": [
      {
        "bankAlias": "QIWI",
        "identificationLevel": "SIMPLE"
      }
    ]
  },
  "userInfo": {
    "defaultPayCurrency": 643,
    "defaultPaySource": 7,
    "email": null,
    "firstTxnId": 10807097143,
    "language": "string",
    "operator": "Beeline",
    "phoneHash": "lgsco87234f0287",
    "promoEnabled": null
  }
}

Successful JSON-response has the following fields:

Field Type Description
authInfo Object Current authorization settings. The object may be missing, depending on the authInfoEnabled parameter in the request.
authInfo.personId Number Wallet number
authInfo.registrationDate String QIWI Wallet date/registration time (via website/mobile app, or otherwise)
authInfo.boundEmail String E-mail linked to your QIWI wallet. If not, null
authInfo.ip String IP address of the last user session
authInfo.lastLoginDate String The date/time of the last session in QIWI Wallet service
authInfo.mobilePinInfo Object PIN data of the mobile app
mobilePinInfo.mobilePinUsed Boolean Flag of using a PIN-code (actually means that the mobile app is being used)
mobilePinInfo.lastMobilePinChange String The date/time of the last time of the PIN change in the mobile app
mobilePinInfo.nextMobilePinChange String The date/time of the next (planned) change of the PIN in the mobile app
authInfo.passInfo Object Password usage data on the qiwi.com site
passInfo.passwordUsed Boolean Flag of using password (actually means using the site qiwi.com)
passInfo.lastPassChange String The date/time of the last password change on qiwi.com
passInfo.nextPassChange String The date/time of the next (planned) password change on qiwi.com
authInfo.pinInfo Object PIN usage data to the wallet app on the self-service kiosks
pinInfo.pinUsed Boolean Flag of using a PIN for the terminal (actually means using the wallet app on the self-service kiosk)
contractInfo Object Information about the wallet. The object may be missing, depending on the contractInfoEnabled parameter in the request.
contractInfo.blocked Boolean Flag of wallet block
contractInfo.contractId Number Wallet number
contractInfo.creationDate String The date/time to create a wallet (via website/mobile app, either at first topup or otherwise)
contractInfo.features Array[Object] Service info
contractInfo.identificationInfo Array[Object] User's identification data
identificationInfo[].bankAlias String String's acronym of the system, in which the user has received the identification::
QIWI - QIWI Wallet.
identificationInfo[].identificationLevel String Current level of the wallet identification. Possible values:
ANONYMOUS - no identification;
SIMPLE, VERIFIED - simplified identification;
FULL - full identification.
userInfo Object Other user data. The object may be missing, depending on the userInfoEnabled parameter in the request.
userInfo.defaultPayCurrency Number Default wallet balance currency code (number-3 ISO-4217)
userInfo.defaultPaySource Number Service info
userInfo.email String User's e-mail
userInfo.firstTxnId Number Identifier of the first transaction after registration
userInfo.language String Service info
userInfo.operator String Name of the mobile operator of the user's number
userInfo.phoneHash String Service info
userInfo.promoEnabled String Service info

Identification API

Use methods of this API to identify and check identification status of your wallet in QIWI Wallet service. You need identification to get access to increased limits for balances and transactions.

Identification details (in Russian)

User identification

This request allows you to start the identification of your QIWI Wallet.

To obtain Main wallet status, you must provide the following data about the owner of the wallet:

To identify your wallet, you must send your name, series/passport number and date of birth. If the data has been verified, the answer will show your TIN and simplified wallet identification will be established. If the data has not been verified, the wallet remains in the status of "No Identification."

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/identification/v1/persons/79111234567/identification" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9" \
  -d '{ \
  "birthDate": "1998-02-11", \
  "firstName": "Иван", \
  "inn": "", \
  "lastName": "Иванов", \
  "middleName": "Иванович", \
  "oms": "", \
  "passport": "4400111222", \
  "snils": "" \
}'
POST /identification/v1/persons/79111234567/identification HTTP/1.1
Accept: application/json
Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9
Content-type: application/json
Host: edge.qiwi.com

{
  "birthDate": "1998-02-11",
  "firstName": "Иван",
  "inn": "",
  "lastName": "Иванов",
  "middleName": "Иванович",
  "oms": "",
  "passport": "4400111222",
  "snils": ""
}
import requests

def get_identification(api_access_token, my_login):
    s = requests.Session()
    s.headers['authorization'] = 'Bearer ' + api_access_token
    res = s.get('https://edge.qiwi.com/identification/v1/persons/'+my_login+'/identification')
    return res.json()
Parameter Type Description
birthDate String Date of birth (in "YYYY-MM-DD" format)
firstName String User's first name
middleName String User's surname
lastName String User's last name
passport String Series / Passport No. (only digits)
inn String User's TIN
snils String User's SNILS
oms String User's medical insurance number (OMS)

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "birthDate": "1996-03-18",
  "firstName": "Иван",
  "id": 79111234567,
  "inn": "7710000001",
  "lastName": "Иванов",
  "middleName": "Иванович",
  "oms": "",
  "passport": "1122333000",
  "snils": "",
  "type": "VERIFIED"
}
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'
print(get_identification(api_access_token, mylogin))

{'birthDate': '1984-01-09',
 'firstName': 'Иванов',
 'id': 79262111317,
 'inn': 'xxxxxxx',
 'lastName': 'Иванов',
 'middleName': 'Иванович',
 'oms': None,
 'passport': 'xxxx xxxxxx',
 'snils': None,
 'type': 'FULL'}

Successful JSON response confirms wallet identification data:

Parameter Type Description
id Number User's QIWI wallet number
type String Current identification level of the wallet:
SIMPLE - no identification, wallet status "MINIMAL".
VERIFIED - wallet status "MAIN" (identification data has been successfully verified).
FULL – the wallet already got "FULL" status by the provided personally verified name, passport and date of birth.
birthDate String Date of birth
firstName String User's first name
middleName String User's surname
lastName String User's last name
passport String Series / Passport No. (only digits)
inn String User's TIN. If the parameter is returned but not present in the original request, then the wallet identification is established
snils String User's SNILS
oms String User's medical insurance number (OMS)

Identification data

Use the request to get masked private data and identification status of your QIWI Wallet.

Request → GET

user@server:~$ curl -X GET "https://edge.qiwi.com/identification/v1/persons/79111234567/identification" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9"
GET /identification/v1/persons/79111234567/identification HTTP/1.1
Accept: application/json
Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9
Host: edge.qiwi.com

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "birthDate": "1996-03-18",
  "firstName": "Иван",
  "id": 79111234567,
  "inn": "77***01",
  "lastName": "Иванов",
  "middleName": "Иванович",
  "oms": "",
  "passport": "43***11",
  "snils": "",
  "type": "VERIFIED"
}

Successful JSON response contains masked data used for the wallet identification:

Parameter Type Description
id Number User's QIWI wallet number
type String Current identification level of the wallet:
SIMPLE - no identification, status "MINIMAL".
VERIFIED - status "MAIN" (identification data has been successfully verified).
FULL – "FULL" status, the wallet already got full identification by the provided name, passport and date of birth.
birthDate String Date of birth
firstName String User's first name
middleName String User's surname
lastName String User's last name
passport String Series / Passport No. (first and last two digits)
inn String User's TIN (first and last two digits)
snils String User's SNILS (first and last two digits)
oms String User's medical insurance number (OMS) (first and last two digits)

QIWI Wallet Limits API

By using this API, you can get current limits for operations in your QIWI wallet. Limits apply on amount of the operations.

Request → GET

user@server:~$ curl "https://edge.qiwi.com/qw-limits/v1/persons/79115221133/actual-limits?types%5B0%5D=TURNOVER" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"
GET /qw-limits/v1/persons/79115221133/actual-limits?types%5B0%5D=TURNOVER HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
import requests

def limits(login, api_access_token):
    types = [ 'TURNOVER', 'REFILL', 'PAYMENTS_P2P', 'PAYMENTS_PROVIDER_INTERNATIONALS', 'PAYMENTS_PROVIDER_PAYOUT', 'WITHDRAW_CASH']
    s = requests.Session()
    s.headers['Accept']= 'application/json'
    s.headers['Content-Type']= 'application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token
    parameters = {}
    for i, type in enumerate(types):
        parameters['types[' + str(i) + ']'] = type
    b = s.get('https://edge.qiwi.com/qw-limits/v1/persons/' + login + '/actual-limits', params = parameters)
    return b.json()
Parameter Type Description
types Array[String] A list of the types of operations that limits are requested for. Each type is numbered by an array element, starting from zero (types[0], types[1], etc.). Acceptable types of transactions:
REFILL - balance in the account
TURNOVER - turnover per month
PAYMENTS_P2P - transfers to other wallets per month
PAYMENTS_PROVIDER_INTERNATIONALS - payments to foreign companies per month
PAYMENTS_PROVIDER_PAYOUT - transfers to bank accounts and cards, wallets of other systems
WITHDRAW_CASH - cash withdrawals per month.
At least one type of operation must be specified.

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "limits":{
      "RU" :[
        {
            "type": "TURNOVER",
            "currency": "RUB",
            "rest": 200.00,
            "max": 40000.00,
            "spent": 39800.00,
            "interval": {
                "dateFrom": "2019-11-01T:00:00",
                "dateTill": "2019-12-01T00:00"
            }
        },
        ...
    ]
  }
}
# wallet number like 79992223344
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# list of all limits
limits = limits(mylogin,api_access_token)['limits']['RU']

# turnover limit
turnoverInfo = [x for x in limits if x['type'] == 'TURNOVER']
turnoverLimit = turnoverInfo[0]['rest']

Successful JSON response contains an array of limits for your QIWI wallet operations:

Parameter Type Description
limits Object Limits data
limits[].'RU' Array[Object] An array of limits for operations
type String Operation type where the limit is applied
currency String Currency of the operation
max String Value of the limit
spent String Amount already spent in the operations
rest Boolean The rest of the limit which can be used in the given period (see interval field)
interval Object Details of the limit's period
interval.dateFrom, interval.dateTill String Period's start and end, as YYYY-MM-DDTHH:MM:SStmz string

Payments History API

Last update: 2020-07-28 | Edit on GitHub

The API gives access to the history of transactions in your QIWI wallet.

List of payments

The request provides a list of payments and top-ups of your wallet. You can use the filter by number, ID and date (date interval) of transactions.

Interactive API

Request → GET

Example 1. Last 10 payments

user@server:~$ curl "https://edge.qiwi.com/payment-history/v2/persons/79112223344/payments?rows=10" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"

Example 2. Payments for 10.05.2017

user@server:~$ curl "https://edge.qiwi.com/payment-history/v2/persons/79112223344/payments?rows=50&startDate=2017-05-10T00%3A00%3A00%2B03%3A00&endDate=2017-05-10T23%3A59%3A59%2B03%3A00" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"

Example 3. Continuing payments list (parameters nextTxnId=9103121 and nextTxnDate=2017-05-11T12:35:23+03:00 returned in the previous history request)

user@server:~$ curl "https://edge.qiwi.com/payment-history/v2/persons/79112223344/payments?rows=50&nextTxnId=9103121&nextTxnDate=2017-05-11T12%3A35%3A23%2B03%3A00" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"

Example 4. Last 10 payments from the ruble account and from the linked card

GET /payment-history/v2/persons/79112223344/payments?rows=10&operation=OUT&sources%5B0%5D=QW_RUB&sources%5B1%5D=CARD HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

Example 5. Payments for 10.05.2017 from the ruble account

GET /payment-history/v2/persons/79112223344/payments?rows=50&sources%5B0%5D=QW_RUB&startDate=2017-05-10T00%3A00%3A00%2B03%3A00&endDate=2017-05-10T23%3A59%3A59%2B03%3A00 HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

Example 6. Continuing payments list for 10.05.2017 (see Example 2, parameters nextTxnId=9103121 и nextTxnDate=2017-05-11T12:35:23+03:00 returned)

GET /payment-history/v2/persons/79112223344/payments?rows=50&nextTxnId=9103121&nextTxnDate=2017-05-11T12%3A35%3A23%2B03%3A00 HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
import requests

# Payments history - the most recent and next n payments
def payment_history_last(my_login, api_access_token, rows_num, next_TxnId, next_TxnDate):
    s = requests.Session()
    s.headers['authorization'] = 'Bearer ' + api_access_token  
    parameters = {'rows': rows_num, 'nextTxnId': next_TxnId, 'nextTxnDate': next_TxnDate}
    h = s.get('https://edge.qiwi.com/payment-history/v2/persons/' + my_login + '/payments', params = parameters)
    return h.json()
Parameter Type Description
rows Integer The number of payments in response to break down the report into chunks. It must be from 1 to 50. The request returns a specified number of payments in reverse chronological order, starting from the current date or date in the startDate option. Required
operation String The type of operations in the report, for selection. Acceptable values:
ALL - all transactions,
IN - only top-ups,
OUT - only payments,
QIWI_CARD - only payments from QIWI cards (QVC, QVP).
By default, ALL is used
sources Array[String] A list of payment sources for the filter. Each source is numbered from scratch (sources[0], sources[1] etc). Acceptable values:
QW_RUB - ruble account of your QIWI wallet,
QW_USD - USD account of your QIWI wallet,
QW_EUR - euro account of your QIWI wallet,
CARD - cards linked to the wallet and other credit cards,
MK - the corresponding account on the mobile operator. If not specified, all sources are considering
startDate DateTime URL-encoded The initial date for the search for payments. It is only used with endDate. The maximum allowable interval between startDate and endDate is 90 calendar days. By default, equal to the daily shift from the current date to Moscow time. The date can be specified in any time zone TZD (in YYYY-MM-DD'T'hh:mm:ssTZD format), but it must coincide with the time zone in the endDate parameter. Timezone designation: +hh:mm or -hh:mm (time shift from GMT).
endDate DateTime URL-encoded The final date for the search for payments. It is only used with startDate. The maximum allowable interval between startDate and endDate is 90 calendar days. By default, equal to current date/time in Moscow time. The date can be specified in any time zone TZD (in YYYY-MM-DD'T'hh:mm:ssTZD format), but it must coincide with the time zone in the startDate parameter. Timezone designation: +hh:mm or -hh:mm (time shift from GMT).
nextTxnDate DateTime URL-encoded The transaction date to start the report (should be equal to nextTxnDate in the previous report). Used only with nextTxnId
nextTxnId Long The transaction number to start the report (should be equal to nextTxnId in the previous report). Used only with nextTxnDate

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{"data":
  [{
    "txnId":9309,
    "personId":79112223344,
    "date":"2017-01-21T11:41:07+03:00",
    "errorCode":0,
    "error":null,
    "status":"SUCCESS",
    "type":"OUT",
    "statusText":"Успешно",
    "trmTxnId":"1489826461807",
    "account":"0003***",
    "sum":{
        "amount":70,
        "currency":"RUB"
        },
    "commission":{
        "amount":0,
        "currency":"RUB"
        },
    "total":{
        "amount":70,
        "currency":"RUB"
        },
    "provider":{
      ...
    },
    "source": {},
    "comment":null,
    "currencyRate":1,
    "extras":null,
    "chequeReady":true,
    "bankDocumentAvailable":false,
    "bankDocumentReady":false,
    "repeatPaymentEnabled":false,
    "favoritePaymentEnabled": true,
    "regularPaymentEnabled": true
  }],
  "nextTxnId":9001,
  "nextTxnDate":"2017-01-31T15:24:10+03:00"
}
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# last 20 payments
lastPayments = payment_history_last(mylogin, api_access_token, '5','','')

# date and time of the next payment (to use in the next request)
nextTxnDate = lastPayments['nextTxnDate']

# transaction id of the next payment (to use in the next request)
nextTxnId = lastPayments['nextTxnId']

# the most recent and next n payments
orderedPayments = payment_history_last(mylogin, api_access_token, '5', nextTxnId, nextTxnDate)

Successful JSON-response contains a list of payments corresponding to the request's filter:

Field Type Description
data Array[Object] A list of Transaction objects.
Number of items in the list less or equals to rows value from the request
nextTxnId Number(Integer) Next transaction ID, in the complete list of your transactions
nextTxnDate DateTime Next transaction date/time, in the complete list of your transactions, Moscow time (in YYYY-MM-DD'T'hh:mm:ss+03:00)

Statistics

This request is used to obtain aggregate statistics on the amount of payments for a given period.

Interactive API

Request → GET

user@server:~$ curl "https://edge.qiwi.com/payment-history/v2/persons/79112223344/payments/total?startDate=2017-03-01T00%3A00%3A00%2B03%3A00&endDate=2017-03-31T11%3A44%3A15%2B03%3A00" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"
GET /payment-history/v2/persons/79112223344/payments/total?startDate=2017-03-01T00%3A00%3A00%2B03%3A00&endDate=2017-03-31T11%3A44%3A15%2B03%3A00 HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
import requests

# Sum of payments for a range of dates
def payment_history_summ_dates(my_login, api_access_token, start_Date, end_Date):
    s = requests.Session()
    s.headers['authorization'] = 'Bearer ' + api_access_token
    parameters = {'startDate': start_Date,'endDate': end_Date}
    h = s.get('https://edge.qiwi.com/payment-history/v2/persons/' + my_login + '/payments/total', params = parameters)
    return h.json()
Parameter Type Description
startDate DateTime URL-encoded Start date of the period, in any time zone TZD (date format YYYY-MM-DD'T'hh:mm:ssTZD). Time zone must coincide with endDate time zone. Designation TZD: +hh:mm or -hh:mm (time shift from GMT). Required
endDate DateTime URL-encoded Final date of th period, in any time zone TZD (date format YYYY-MM-DD'T'hh:mm:ssTZD). Time zone must coincide with startDate time zone. Designation TZD: +hh:mm or -hh:mm (time shift from GMT). Required
operation String Operations to take into account when accumulating statistics. Possible values:
ALL - all operations,
IN - only top-ups,
OUT - only payments,
QIWI_CARD - only payments from QIWI cards (QVC, QVP).
Default value is ALL.
sources Array[String] Payment sources to filter data. Each source is enumerated starting from zero (sources[0], sources[1] and so on). Possible values of each source:
QW_RUB - ruble QIWI Wallet account,
QW_USD - USD QIWI Wallet account,
QW_EUR - euro QIWI Wallet account,
CARD - credit cards, both linked to QIWI Wallet and others,
MK - mobile operator account. If not specified, all sources are collected.

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
 "incomingTotal":[
  {
  "amount":3500,
  "currency":"RUB"
  }],
 "outgoingTotal":[
  {
  "amount":3497.5,
  "currency":"RUB"
  }]
}
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# Payments amount from April 12 till July 11
print(payment_history_summ_dates(mylogin, api_access_token, '2019-04-12T00:00:00Z','2019-07-11T23:59:59Z'))

{'incomingTotal': [{'amount': 3.33, 'currency': 840},
  {'amount': 3481, 'currency': 643}],
 'outgoingTotal': [{'amount': 3989.98, 'currency': 643},
  {'amount': 3.33, 'currency': 840}]}

Successful JSON-response contains statistics data for a specified period:

Field Type Description
incomingTotal Array[Object] Incoming payments (top-ups) data. Each object corresponds to a specific currency
incomingTotal[].amount Number(Decimal) Top-ups amount for the period
incomingTotal[].currency String Currency of the operations
outgoingTotal Array[Object] Payments data. Each object corresponds to a specific currency
outgoingTotal[].amount Number(Decimal) Payments amount for the period
outgoingTotal[].currency String Currency of the operations

Transaction details

The request returns details on a specific transaction from your payments history.

Interactive API

Request → GET

user@server:~$ curl "https://edge.qiwi.com/payment-history/v2/transactions/9112223344" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"
GET /payment-history/v2/transactions/9112223344 HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
import requests

# Transaction details
def payment_history_transaction(api_access_token, transaction_id, transaction_type):
    s = requests.Session()
    s.headers['authorization'] = 'Bearer ' + api_access_token  
    parameters = {'type': transaction_type} # transaction_type 'IN' 'OUT'
    h = s.get('https://edge.qiwi.com/payment-history/v1/transactions/'+transaction_id, params = parameters)
    return h.json()

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "txnId": 11233344692,
    "personId": 79161122331,
    "date": "2017-08-30T14:38:09+03:00",
    "errorCode": 0,
    "error": null,
    "status": "WAITING",
    "type": "OUT",
    "statusText": "Запрос обрабатывается",
    "trmTxnId": "11233344691",
    "account": "15040930424823121081",
    "sum": {
        "amount": 1,
        "currency": 643
    },
    "commission": {
        "amount": 0,
        "currency": 643
    },
    "total": {
        "amount": 1,
        "currency": 643
    },
    "provider": {
        "id": 1,
        "shortName": "MTS",
        "longName": "MTS",
        "logoUrl": null,
        "description": null,
        "keys": null,
        "siteUrl": null,
        "extras": []
    },
    "source": {
        "id": 7,
        "shortName": "QIWI Wallet",
        "longName": "QIWI Wallet",
        "logoUrl": null,
        "description": null,
        "keys": "мобильный кошелек, кошелек, перевести деньги, личный кабинет, отправить деньги, перевод между пользователями",
        "siteUrl": null,
        "extras": []
    },
    "comment": null,
    "currencyRate": 1,
    "extras": [],
    "chequeReady": false,
    "bankDocumentAvailable": false,
    "bankDocumentReady": false,
    "repeatPaymentEnabled": false,
    "favoritePaymentEnabled": false,
    "regularPaymentEnabled": false
}
# wallet number like 79992223344
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# Transaction ID 11181101215 details
transactionInfo = payment_history_transaction(api_access_token, '11181101215', 'OUT')

# Transaction number 5 details
lastPayments = payment_history_last(mylogin, api_access_token, '20','','')
last_txn_id = lastPayments['data'][5]['txnId']
last_txn_type = lastPayments['data'][5]['type']

transactionInfo = payment_history_transaction(api_access_token, str(last_txn_id), last_txn_type)

Successful JSON-response contains Transaction object.

Payment receipt

The request returns electronic receipt for a certain transaction in PDF/JPEG format, either as binary file or via e-mail to specified address.

Receipt file

Interactive API

Request → GET

user@server:~$ curl "https://edge.qiwi.com/payment-history/v1/transactions/9112223344/cheque/file?type=IN&format=PDF" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"
GET /payment-history/v1/transactions/9112223344/cheque/file?type=IN&format=PDF HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
import requests

# Get receipt text in file
def payment_history_cheque_file(transaction_id, transaction_type, filename, api_access_token):
    s = requests.Session()
    s.headers['Accept'] ='application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token
    parameters = {'type': transaction_type,'format': 'PDF'}
    h = s.get('https://edge.qiwi.com/payment-history/v1/transactions/'+transaction_id+'/cheque/file', params=parameters)
    h.status_code
    with open(filename + '.pdf', 'wb') as f:
        f.write(h.content)

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

[
  ""
]

Successful JSON-response contains binary file.

Receipt sending

Interactive API

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/payment-history/v1/transactions/9112223344/cheque/send?type=IN" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{"email": "my@example.com"}'
POST /payment-history/v1/transactions/9112223344/cheque/send?type=IN HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Content-type: application/json
Host: edge.qiwi.com

{"email": "my@example.com"}
import requests

# Send receipt to email
def payment_history_cheque_send(transaction_id, transaction_type, email, api_access_token):
    s = requests.Session()
    s.headers['content-type'] ='application/json'
    s.headers['Accept'] ='application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token
    postjson = {'email':email}
    h = s.post('https://edge.qiwi.com/payment-history/v1/transactions/' + transaction_id + '/cheque/send?type=' + transaction_type, json = postjson)
    h.status_code
Parameter Type Description
email String Email address

Response ←

HTTP/1.1 201 Created
Content-Type: application/json
# wallet number like 79992223344
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

lastPayments = payment_history_last(mylogin, api_access_token, '20','','')
last_txn_id = lastPayments['data'][5]['txnId']
last_txn_type = lastPayments['data'][5]['type']

# Send receipt to email
payment_history_cheque_send(str(last_txn_id), last_txn_type, 'mmd@yandex.ru', api_access_token)

Successful JSON-response contains HTTP result code of file sending operation.

API data models

Transaction class

Object contains information about existing QIWI Wallet transaction.

Parameter Type Description
txnId Integer Transaction ID in QIWI Wallet processing
personId Integer Wallet number
date DateTime For payments history reports - Payment date/time, in the request time zone (see startDate parameter). Date format YYYY-MM-DD'T'hh:mm:ss+03:00
For transaction details - Payment date/time, in Moscow time zone (date format: YYYY-MM-DD'T'hh:mm:ss+03:00)
errorCode Number(Integer) Payment error code
error String Error description
type String Payment type. Possible values:
IN - top-up,
OUT - payment,
QIWI_CARD - payment from QIWI card (QVC, QVP).
status String Payment status. Possible values:
WAITING - payment is processing,
SUCCESS - successful payment,
ERROR - payment error.
statusText String Text description of the status
trmTxnId String Transaction's client ID (assigned on the client device)
account String For payments, recipient's account number. For top-ups, sender's number, terminal's number or top-up agent name
sum Object Payment's amount data.
sum.amount Number(Decimal) amount,
sum.currency String currency
commission Object Payment's commission data
commission.amount Number(Decimal) amount,
commission.currency String currency
total Object Total amount of transaction.
total.amount Number(Decimal) amount, it is sum.amount plus commission.amount,
total.currency String currenc
provider Object Provider's data
provider.id Integer Provider ID in QIWI Wallet system,
provider.shortName String Provider's short name,
provider.longName String Provider's extended name,
provider.logoUrl String Provider's logo URL,
provider.description String Provider's description (in HTML),
provider.keys String Provider's keywords list,
provider.siteUrl String Provider's site
comment String Comment to the payment
currencyRate Number(Decimal) Currency exchange rate (if applied to transaction)
extras Object Service information
chequeReady Boolean Service information
bankDocumentAvailable Boolean Service information
bankDocumentReady Boolean Service information
repeatPaymentEnabled Boolean Service information
favoritePaymentEnabled Boolean Service information
regularPaymentEnabled Boolean Service information

Wallet Balances API

Last update: 2020-07-28 | Edit on GitHub

API provides methods to control balances of your QIWI wallet.

List of balances

The request provides current balances of your QIWI Wallet.

Interactive API

Request → GET

user@server:~$ curl "https://edge.qiwi.com/funding-sources/v2/persons/79115221133/accounts" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"
GET /funding-sources/v2/persons/79115221133/accounts HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
import requests

# QIWI Wallet balances
def balance(login, api_access_token):
    s = requests.Session()
    s.headers['Accept']= 'application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token  
    b = s.get('https://edge.qiwi.com/funding-sources/v2/persons/' + login + '/accounts')
    return b.json()

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "accounts": [
        {
            "alias": "mc_beeline_rub",
            "fsAlias": "qb_mc_beeline",
            "bankAlias": "QIWI",
            "title": "MC",
            "type": {
                "id": "MC",
                "title": "Счет мобильного кошелька"
            },
            "hasBalance": false,
            "balance": null,
            "currency": 643
        },
        {
            "alias": "qw_wallet_rub",
            "fsAlias": "qb_wallet",
            "bankAlias": "QIWI",
            "title": "WALLET",
            "type": {
                "id": "WALLET",
                "title": "QIWI Wallet"
            },
            "hasBalance": true,
            "balance": {
                "amount": 8.74,
                "currency": 643
            },
            "currency": 643
        }
    ]
}
# wallet number as 79992223344
mylogin = '79999999999'
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# All balances
balances = balance(mylogin,api_access_token)['accounts']

# Ruble account balance
rubAlias = [x for x in balances if x['alias'] == 'qw_wallet_rub']
rubBalance = rubAlias[0]['balance']['amount']

Successful response is JSON array of all active balances of your QIWI wallet used for payment funding:

Response field Type Description
accounts Array[Object] Array of balances
accounts[].alias String User balance alias
accounts[].fsAlias String Bank account alias
accounts[].bankAlias String Bank alias
accounts[].title String Wallet account name
accounts[].hasBalance Boolean Flag of actual QIWI Wallet balance (not a linked card or cell phone balance or something like that)
accounts[].currency Number Currency of the balance (number-3 ISO-4217). Only balances in following currencies are returned: 643 - Russian ruble, 840 - USD, 978 - Euro
accounts[].type Object Account information
type.id, type.title String Account title
accounts[].balance Object Balance data.
If null is returned and accounts[].hasBalance is true, repeat the request with additional parameters:
timeout=1000 and alias="accounts[].alias" (alias of that balance).
For example
GET /funding-sources/v2/persons/79115221133/accounts?timeout=1000&alias=qw_wallet_rub
balance.amount Number Текущий баланс данного счета
balance.currency Number Код валюты баланса (number-3 ISO-4217)

Creating balance

The request creates a new account and its balance in your QIWI wallet. List of account types which you can create is provided by other request.

Interactive API

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/funding-sources/v2/persons/79115221133/accounts" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{  "alias": "qw_wallet_eur"}'
POST /funding-sources/v2/persons/79115221133/accounts HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Content-type: application/json
Host: edge.qiwi.com

{ "alias": "qw_wallet_eur" }
Parameter Type Description
alias String Alias of the new account (taken from Available accounts)

Response ←

HTTP/1.1 201 Created
Content-Type: application/json

Successful response contains HTTP code 201.

Available accounts

The request provides all possible account aliases for your QIWI wallet.

Interactive API

Request → GET

user@server:~$ curl -X GET "https://edge.qiwi.com/funding-sources/v2/persons/79115221133/accounts/offer" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu"
GET /funding-sources/v2/persons/79115221133/accounts/offer HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{ { "alias": "qw_wallet_eur", "currency": 978 }, {} }

Successful JSON response contains a list of accounts available for creation:

Response field Type Description
{} Object List of accounts
Object.alias String Alias of the account
Object.currency Integer Account's currency ID

Default balance

The request sets up default account in your QIWI wallet for funding all payments. The account must be in the list of available accounts

Interactive API

Request → PATCH

user@server:~$ curl -X PATCH "https://edge.qiwi.com/funding-sources/v2/persons/79115221133/accounts/qw_wallet_usd" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ "defaultAccount": true }'
PATCH /funding-sources/v2/persons/79115221133/accounts/qw_wallet_usd HTTP/1.1
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Content-type: application/json
Host: edge.qiwi.com

{ "defaultAccount": true }
Parameter Type Description
defaultAccount Boolean Flag of default account

Response ←

HTTP/1.1 204 Modified

Successful response has HTTP code 204.

Payments API

Last update: 2020-07-28 | Edit on GitHub

Commission rates

Use the method to get total commission amount for the payment by the given payment requisites.

Request → POST

user@server:~$ curl -X POST 'https://edge.qiwi.com/sinap/providers/99/onlineCommission' \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "account":"380995238345", \
        "paymentMethod":{ \
          "type":"Account", \
          "accountId":"643" \
        },\
        "purchaseTotals":{ \
          "total":{ \
            "amount":10, \
            "currency":"643" \
          } \
        } \
  }'
POST /sinap/providers/99/onlineCommission HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "account":"380995238345",
  "paymentMethod":{
    "type":"Account",
    "accountId":"643"
  },
  "purchaseTotals":{
    "total":{
      "amount":10,
      "currency":"643"
    }
  }
}
import requests

# Тарифные комиссии
def get_commission(api_access_token, to_account, prv_id, sum_pay):
    s = requests.Session()
    s.headers = {'content-type': 'application/json'}
    s.headers['authorization'] = 'Bearer ' + api_access_token  
    postjson = {"account":"","paymentMethod":{"type":"Account","accountId":"643"}, "purchaseTotals":{"total":{"amount":"","currency":"643"}}}
    postjson['account'] = to_account
    postjson['purchaseTotals']['total']['amount'] = sum_pay
    c_online = s.post('https://edge.qiwi.com/sinap/providers/'+prv_id+'/onlineCommission',json = postjson)
    return c_online.json()['qwCommission']['amount']
Parameter Type Description
account String User's identifier (phone number, card/account number, and other entity depending on provider)
paymentMethod Object Object defining payment processing by QIWI Wallet. Includes the following parameters:
paymentMethod.type String Payment method, Account only
paymentMethod.accountId String QIWI Wallet account identifier, 643 only.
purchaseTotals Object Object with payment requisites
purchaseTotals.total Object Payment amount data:
total.amount Number Amount (rubles and kopeks, divided by .). Positive number, rounded down to 2 decimals. If you send more decimals, value will be rounded down to kopeks.
total.currency String Currency (643 only, that is rubles)

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "providerId": 99,
    "withdrawSum": {
        "amount": 1011.01,
        "currency": "643"
    },
    "enrollmentSum": {
        "amount": 1001,
        "currency": "643"
    },
    "qwCommission": {
        "amount": 10.01,
        "currency": "643"
    },
    "fundingSourceCommission": {
        "amount": 0,
        "currency": "643"
    },
    "withdrawToEnrollmentRate": 1
}
api_access_token = '975efd8e8376xxxb95fa7cb213xxx04'

# QIWI wallet transfer commission
print(get_commission(api_access_token,'+380000000000','99',5000))
# Card transfer commission
print(get_commission(api_access_token,'4890xxxxxxxx1698','22351',1000))

Commission rate returns in qwCommission.amount field of the JSON response.

Payment form autofilling

The request provides autofilled payment form on qiwi.com site.

Link example (click to see the form)

If you don't want to show your wallet number, use transfer to wallet nickname:

Link example for nickname transfer (click to see the form)

To get payments to your QIWI Wallet, you can use also P2P-form.

Request → GET

GET /payment/form/99?extra%5B%27account%27%5D=79991112233&amountInteger=1&amountFraction=0&extra%5B%27comment%27%5D=test123&currency=643 HTTP/1.1
Host: qiwi.com

Parameter Type Description Form field Required
amountInteger Integer Integer part of the payment amount (in rubles). If absent, "Amount" field will be empty. The number not greater than 99 999 (payment amount limit) Anmount -
amountFraction Integer Fractional part of the payment amount (kopeks). If absent, Дробная часть суммы платежа (копейки). Если параметр не указан, "Amount" field will be empty. Сумма -
currency Constant string, 643 Payment currency code. Required if you send the payment amount in the link - +
extra['comment'] URL-encoded string Payment comment. Use it only for ID=99 Comment to the transfer -
extra['account'] URL-encoded string Field format is the same as fields.account of the corresponding payment request: for provider 99 - recipient's wallet number; for mobile network operators - phone number for top-up (without international prefix); for card transfer - recipient's card number without spaces, for other providers - user's identifier. For provider 99999 use nickname or number of the wallet and use appropriate value of extra['accountType'] parameter. Wallet number, phone number, user ID. -
blocked Array[String] Name of blocked (inactive) form field. User will not be able to change this field. Each parameter corresponds to respective form field and should be numbered starting from zero (blocked[0], blocked[1], and so on). If absent, user can change all form fields. Possible values:
sum - "Payment amount" field,
account - "Phone number/Account number" field,
comment - "Comment" field.
Example (for payment amount field): blocked[0]=sum
- -
extra['accountType'] URL-encoded string Use only for ID=99999. The value determines transfer to QIWI wallet by nickname or wallet number. If you don't want to show your wallet number, use transfer to wallet nickname.
phone - for transfer to wallet number
nickname - for transfer to wallet nickname.
   

How to get your wallet nickname

Use the following request:

Request → GET

user@server:~$ curl -X GET "https://edge.qiwi.com/qw-nicknames/v1/persons/79111234567/nickname" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9"
GET /qw-nicknames/v1/persons/79111234567/nickname HTTP/1.1
Accept: application/json
Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9
Host: edge.qiwi.com

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "canChange": true,
  "canUse": true,
  "description": "",
  "nickname": "NICKNAME"
}

Successful response contains nickname of your wallet in JSON field nickname.

QIWI wallet transfer

Request → POST

user@server:~$ curl -X POST 'https://edge.qiwi.com/sinap/api/v2/terms/99/payments' \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"11111111111111", \
        "sum": { \
          "amount":100, \
          "currency":"643" \
        }, \
        "paymentMethod": { \
          "type":"Account", \
          "accountId":"643" \
        },
        "comment":"test", \
        "fields": { \
          "account":"+79121112233" \
        } \
      }'
POST /sinap/api/v2/terms/99/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
 "id":"11111111111111",
 "sum": {
  "amount":100.50,
  "currency":"643"
 },
 "paymentMethod": {
  "type":"Account",
  "accountId":"643"
 },
 "comment":"test",
 "fields": {
	"account":"+79121112233"
 }
}
import requests
import time

# QIWI wallet transfer
def send_p2p(api_access_token, to_qw, comment, sum_p2p):
    s = requests.Session()
    s.headers = {'content-type': 'application/json'}
    s.headers['authorization'] = 'Bearer ' + api_access_token
    s.headers['User-Agent'] = 'Android v3.2.0 MKT'
    s.headers['Accept'] = 'application/json'
    postjson = {"id":"","sum":{"amount":"","currency":""},"paymentMethod":{"type":"Account","accountId":"643"}, "comment":"'+comment+'","fields":{"account":""}}
    postjson['id'] = str(int(time.time() * 1000))
    postjson['sum']['amount'] = sum_p2p
    postjson['sum']['currency'] = '643'
    postjson['fields']['account'] = to_qw
    res = s.post('https://edge.qiwi.com/sinap/api/v2/terms/99/payments',json = postjson)
    return res.json()
Parameter Type Description Required
fields.account String Wallet number of the recipient +

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": "150217833198900",
    "terms": "99",
    "fields": {
        "account": "79121238345"
    },
    "sum": {
        "amount": 100,
        "currency": "643"
    },
    "transaction": {
        "id": "11155897070",
        "state": {
            "code": "Accepted"
        }
    },
    "source": "account_643",
    "comment": "test"
}
print(send_p2p(mylogin,api_access_token,'+79261112233','comment',99.01))

{'comment': 'comment',
 'fields': {'account': '+79261112233'},
 'id': '1514296828893',
 'source': 'account_643',
 'sum': {'amount': 99.01, 'currency': '643'},
 'terms': '99',
 'transaction': {'id': '11982501857', 'state': {'code': 'Accepted'}}}

Successful response contains JSON-object PaymentInfo with accepted payment data.

Conversion

API method to transfer funds to currency account in QIWI wallet with conversion from your QIWI wallet ruble account. Two transactions are created: conversion between accounts of your QIWI wallet, and transfer to another wallet. You can get currency rates from another API method.

Request → POST

user@server:~$ curl -X POST 'https://edge.qiwi.com/sinap/api/v2/terms/1099/payments' \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"11111111111111", \
        "sum": { \
          "amount":100, \
          "currency":"398" \
        }, \
        "paymentMethod": { \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "comment":"test", \
        "fields": { \
          "account":"+79121112233" \
        } \
      }'
POST /sinap/api/v2/terms/1099/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"11111111111111",
  "sum": {
		"amount":10.00,
		"currency":"398"
	},
	"paymentMethod": {
		"type":"Account",
		"accountId":"643"
	},
	"comment":"test",
	"fields": {
	 	"account":"+79121112233"
	}
}
import requests
import time

# Conversion in QIWI wallet (currency as currency integer code as String)
def exchange(api_access_token, sum_exchange, currency, to_qw):
    s = requests.Session()
    currencies = ['398', '840', '978']
    if currency not in currencies:
      print('This currency not available')
      return
    s.headers = {'content-type': 'application/json'}
    s.headers['authorization'] = 'Bearer ' + api_access_token
    s.headers['User-Agent'] = 'Android v3.2.0 MKT'
    s.headers['Accept'] = 'application/json'
    postjson = {"id":"","sum":{"amount":"","currency":""},"paymentMethod":{"type":"Account","accountId":"643"}, "comment":"'+comment+'","fields":{"account":""}}
    postjson['id'] = str(int(time.time() * 1000))
    postjson['sum']['amount'] = sum_exchange
    postjson['sum']['currency'] = currency
    postjson['fields']['account'] = to_qw
    res = s.post('https://edge.qiwi.com/sinap/api/v2/terms/1099/payments',json = postjson)
    return res.json()
Parameter Type Description Required
fields.account String Wallet number for the conversion +

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": "150217833198900",
    "terms": "99",
    "fields": {
        "account": "79121238345"
    },
    "sum": {
        "amount": 100,
        "currency": "398"
    },
    "transaction": {
        "id": "11155897070",
        "state": {
            "code": "Accepted"
        }
    },
    "source": "account_643",
    "comment": "test"
}

Successful response contains JSON-object PaymentInfo with accepted payment data.

Currency rates

API method returns current QIWI Bank currency rates and cross-rates.

Request → GET

user@server:~$ curl "https://edge.qiwi.com/sinap/crossRates" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9"
GET /sinap/crossRates HTTP/1.1
Accept: application/json
Authorization: Bearer 5c4b25xx93aa435d9cb8cd17480356f9
Content-type: application/json
Host: edge.qiwi.com
import requests

# Currencies rate (currency pair codes in String)
def exchange(api_access_token, currency_to, currency_from):
    s = requests.Session()
    s.headers = {'content-type': 'application/json'}
    s.headers['authorization'] = 'Bearer ' + api_access_token
    s.headers['User-Agent'] = 'Android v3.2.0 MKT'
    s.headers['Accept'] = 'application/json'
    res = s.get('https://edge.qiwi.com/sinap/crossRates')

    # all rates
    rates = res.json()['result']

    # requested rate
    rate = [x for x in rates if x['from'] == currency_from and x['to'] == currency_to]
    if (len(rate) == 0):
        print('No rate for this currencies!')
        return
    else:
        return rate[0]['rate']

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "result": [
        {
            "set": "General",
            "from": "398",
            "to": "643",
            "rate": 6.22665
        },
        {
            "set": "General",
            "from": "398",
            "to": "756",
            "rate": 412.0174305
        },
        ...,
        {
            "set": "General",
            "from": "980",
            "to": "978",
            "rate": 31.4680914
        }
    ]
}

Successful response containt JSON array of currency rates in result field. An element of the list corresponds to currency pair:

Parameter Type Description
from String Base currency
to String Quote currency
rate Number Rate

Mobile network payment

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/1/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"11111111111111", \
        "sum": { \
          "amount":100, \
          "currency":"643" \
        }, \
        "paymentMethod": { \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "fields": { \
          "account":"9161112233" \
        } \
      }'
POST /sinap/api/v2/terms/1/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
        "account":"9161112233"
  }
}
import requests
import time

# Cell phone topup
def send_mobile(api_access_token, prv_id, to_account, comment, sum_pay):
    s = requests.Session()
    s.headers['Accept'] = 'application/json'
    s.headers['Content-Type'] = 'application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token
    postjson = {"id":"","sum": {"amount":"","currency":"643"},"paymentMethod": {"type":"Account","accountId":"643"},"comment":"","fields": {"account":""}}
    postjson['id'] = str(int(time.time() * 1000))
    postjson['sum']['amount'] = sum_pay
    postjson['fields']['account'] = to_account
    postjson['comment'] = comment
    res = s.post('https://edge.qiwi.com/sinap/api/v2/terms/'+prv_id+'/payments', json = postjson)
    return res.json()
Parameter Type Description
fields.account String Cell phone number to topup (without 8 prefix)

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
    "id": "21131343",
    "terms": "1",
    "fields": {
          "account": "9161112233"
    },
    "sum": {
         "amount": 1000,
         "currency": "643"
    },
    "source": "account_643",
    "transaction": {
         "id": "4969142201",
         "state": {
            "code": "Accepted"
          }
    }
}
send_mobile(api_access_token,'2','9670058909','123','1')

Successful response contains JSON-object PaymentInfo with accepted payment data.

Card money transfer

This request makes money transfer to Visa, MasterCard, or MIR credit cards. Preliminary check card system provider ID.

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/1963/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"21131343", \
        "sum":{ \
          "amount":1000, \
          "currency":"643" \
        }, \
        "paymentMethod":{ \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "fields": { \
          "account":"4256********1231" \
        } \
      }'
user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/1960/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"21131343", \
        "sum":{ \
          "amount":1000, \
          "currency":"643"
        }, \
        "paymentMethod":{ \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "fields": { \
          "account": "402865XXXXXXXXXX", \
          "rec_address": "Ленинский проспект 131, 56", \
          "rec_city": "Москва", \
          "rec_country": "Россия", \
          "reg_name": "Виктор", \
          "reg_name_f": "Петров", \
          "rem_name": "Сергей", \
          "rem_name_f": "Иванов" \
        } \
      }'
POST /sinap/api/v2/terms/1963/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
        "account":"4256XXXXXXXX1231"
  }
}
POST /sinap/api/v2/terms/1960/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
      "account": "402865XXXXXXXXXX",
      "rec_address": "Ленинский проспект 131, 56",
      "rec_city": "Москва",
      "rec_country": "Россия",
      "reg_name": "Виктор",
      "reg_name_f": "Петров",
      "rem_name": "Сергей",
      "rem_name_f": "Иванов"
  }
}
import requests
import time

# Card money transer
def send_card(api_access_token, payment_data):
    # payment_data - dictionary with all payment data
    s = requests.Session()
    s.headers['Accept'] = 'application/json'
    s.headers['Content-Type'] = 'application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token
    postjson = {"id":"","sum": {"amount":"","currency":"643"},"paymentMethod": {"type":"Account","accountId":"643"},"fields": {"account":""}}
    postjson['id'] = str(int(time.time() * 1000))
    postjson['sum']['amount'] = payment_data.get('sum')
    postjson['fields']['account'] = payment_data.get('to_card')
    prv_id = payment_data.get('prv_id')
    if payment_data.get('prv_id') in ['1960', '21012']:
        postjson['fields']['rem_name'] = payment_data.get('rem_name')
        postjson['fields']['rem_name_f'] = payment_data.get('rem_name_f')
        postjson['fields']['reg_name'] = payment_data.get('reg_name')
        postjson['fields']['reg_name_f'] = payment_data.get('reg_name_f')
        postjson['fields']['rec_city'] = payment_data.get('rec_address')
        postjson['fields']['rec_address'] = payment_data.get('rec_address')
        
    res = s.post('https://edge.qiwi.com/sinap/api/v2/terms/' + prv_id + '/payments', json = postjson)
    return res.json()
Parameter Type Description
fields.account String Recipient's card number (no spaces)
fields.rem_name String Sender's first name. Required for ID 1960, 21012 only
fields.rem_name_f String Sender's last name. Required for ID 1960, 21012 only
fields.rec_address String Sender's address (no zip code, only text). Required for ID 1960, 21012 only
fields.rec_city String Sender's city. Required for ID 1960, 21012 only
fields.rec_country String Sender's country. Required for ID 1960, 21012 only
fields.reg_name String Recipient's first name. Required for ID 1960, 21012 only
fields.reg_name_f String Recipient's last name. Required for ID 1960, 21012 only

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "21131343",
  "terms": "1963",
  "fields": {
          "account": "4256********1231"
    },
    "sum": {
         "amount": 1000,
         "currency": "643"
    },
    "source": "account_643",
    "transaction": {
         "id": "4969142201",
         "state": {
            "code": "Accepted"
          }
    }
}
payment_data = {'prv_id': '1963', 'to_card' : '41548XXXXXXXX008', 'sum': 100}

jss = send_card(token, payment_data)

Successful response contains JSON-object PaymentInfo with accepted payment data.

Bank money transfer

To make money transfer to bank cards/accounts of persons opened in Russian banks, use the following methods.

Card nunmber transfer

The request makes money transfer to cards issued by Russian banks.

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/464/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"21131343", \
        "sum": { \
          "amount":1000, \
          "currency":"643" \
        }, \
        "paymentMethod": { \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "fields": { \
          "account_type": "1", \
          "account":"4256********1231", \
          "exp_date": "MMYY" \
        } \
      }'
POST /sinap/api/v2/terms/464/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
        "account":"4256********1231",
        "account_type": "1",
        "exp_date": "MMYY"
  }
}
Parameter Type Description
fields.account String Recipient's card number (no spaces)
fields.exp_date String Card expiry date, as MMYY (for example, 0218). Parameter is required for ID 464 and 821.
fields.account_type String Bank identifier type. For each bank specific value applies:
ID 464 - 1
ID 084 - 1
ID 815 - 1
ID 810 - 5
ID 816 - 5
ID 821 - 7
ID 870 - 5
ID 1134 - 5
ID 881 - 1.
fields.mfo String Bank MFO (BIK)
fields.lname String Recipient's last name
fields.fname String Recipient's first name
fields.mname String Recipient's middle name

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "21131343",
  "terms": "464",
  "fields": {
      "account": "4256********1231",
      "account_type": "1",
      "exp_date": "MMYY"
  },
  "sum": {
      "amount": 1000,
      "currency": "643"
  },
  "source": "account_643",
  "transaction": {
      "id": "4969142201",
      "state": {
        "code": "Accepted"
      }
  }
}

Successful response contains JSON-object PaymentInfo with accepted payment data.

Bank account transfer

The request makes money transfer to personal accounts opened in Russian banks. You can use quick transfer service (within an hour if transaction is made from 9:00 until 19:30).

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/816/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"21131343", \
        "sum": { \
          "amount":1000, \
          "currency":"643" \
        }, \
        "paymentMethod": { \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "fields": { \
          "account_type": "2", \
          "urgent": "0", \
          "lname": "Иванов", \
          "fname": "Иван", \
          "mname": "Иванович", \
          "mfo": "046577795", \
          "account":"40817***" \
        } \
      }'
POST /sinap/api/v2/terms/816/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
          "account_type": "2",
          "urgent": "0",
          "lname": "Иванов",
          "fname": "Иван",
          "mname": "Иванович",
          "mfo": "046577795",
          "account":"40817***"
  }
}
Parameter Type Description
fields.account String Recipient's bank account number
fields.urgent String Quick transfer flag. For 0 - not used; for 1 - make quick transfer by Urgent transfer service of Central Bank of Russia. Extra commission is paid for quick transfer
fields.mfo String Bank MFO (BIK)
fields.account_type String Bank identifier type. For each bank specfic value applies:
ID 464 - 2
ID 804 - 2
ID 810 - 2
ID 815 - 2
ID 816 - 2
ID 821 - 9
ID 819 - 2
ID 868 - 2
ID 870 - 2
ID 1134 - 2
ID 27324 -2
ID 810 - 2
ID 816 - 5
ID 821 - 9
ID 881 - 2
ID 313 - 6.
fields.lname String Recipient's last name
fields.fname String Recipient's first name
fields.mname String Recipient's middle name
fileds.agrnum String Bank agreement number - for ID 313

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "21131343",
  "terms": "464",
  "fields": {
          "account": "407121010910909011",
          "account_type": "2"
  },
  "sum": {
         "amount": 1000,
         "currency": "643"
  },
  "source": "account_643",
  "transaction": {
         "id": "4969142201",
         "state": {
            "code": "Accepted"
          }
  }
}

Successful response contains JSON-object PaymentInfo with accepted payment data.

Other services

You can pay for services by user identifier. This request applies for QIWI providers with one user identifier and without account number online check.

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/674/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  -d '{ \
        "id":"21131343", \
        "sum": { \
          "amount":100, \
          "currency":"643" \
        },\
        "paymentMethod": { \
          "type":"Account", \
          "accountId":"643" \
        }, \
        "fields": { \
          "account":"111000000" \
        } \
      }'
POST /sinap/api/v2/terms/674/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com

{
  "id":"21131343",
  "sum": {
        "amount":100,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
        "account":"111000"
  }
}
import requests
import time

# payment for service provider

def pay_simple_prv(api_access_token, prv_id, to_account, sum_pay):
    s = requests.Session()
    s.headers['Accept'] = 'application/json'
    s.headers['Content-Type'] = 'application/json'
    s.headers['authorization'] = 'Bearer ' + api_access_token
    postjson = {"id":"","sum": {"amount":"","currency":"643"},"paymentMethod": {"type":"Account","accountId":"643"},"fields": {"account":""}}
    postjson['id'] = str(int(time.time() * 1000))
    postjson['sum']['amount'] = sum_pay
    postjson['fields']['account'] = to_account
    res = s.post('https://edge.qiwi.com/sinap/api/v2/terms/'+prv_id+'/payments', json = postjson)
    return res.json()
Parameter Type Description
fields.account String User identifier

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "21131343",
  "terms": "674",
  "fields": {
          "account": "111000"
  },
  "sum": {
         "amount": 100,
         "currency": "643"
  },
  "source": "account_643",
  "transaction": {
         "id": "4969142201",
         "state": {
            "code": "Accepted"
          }
  }
}

Successful response contains JSON-object PaymentInfo with accepted payment data.

Payment by any requisites

This method makes payments for commercial services by their bank details.

Request → POST

user@server:~$ curl -X POST "https://edge.qiwi.com/sinap/api/v2/terms/1717/payments" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer YUu2qw048gtdsvlk3iu" \
  --header "User-Agent: ***" \
  -d '{ \
  "id":"21131343", \
  "sum": { \
        "amount":1000, \
        "currency":"643" \
  }, \
  "paymentMethod": { \
      "type":"Account", \
      "accountId":"643" \
  }, \
  "fields": { \
         "extra_to_bik":"044525201", \
         "requestProtocol":"qw1", \
         "city":"МОСКВА", \
         "name":"ПАО АКБ \"АВАНГАРД\"", \
         "to_bik":"044525201", \
         "urgent":"0", \
         "to_kpp":"772111001", \
         "is_commercial":"1", \
         "nds":"НДС не облагается", \
         "goal":" Оплата товара по заказу №090738231", \
         "from_name_p":"Николаевич", \
         "from_name":"Иван", \
         "from_name_f":"Михайлов", \
         "info":"Коммерческие организации", \
         "to_name":"ООО \"Технический Центр ДЕЛЬТА\"", \
         "to_inn":"7726111111", \
         "account":"40711100000012321", \
         "toServiceId":"1717" \
  } \
}'
POST /sinap/api/v2/terms/1717/payments HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer YUu2qw048gtdsvlk3iu
Host: edge.qiwi.com
User-Agent: ****

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
         "extra_to_bik":"044525201",
         "requestProtocol":"qw1",
         "city":"МОСКВА",
         "name":"ПАО АКБ \"АВАНГАРД\"",
         "to_bik":"044525201",
         "urgent":"0",
         "to_kpp":"772111001",
         "is_commercial":"1",
         "nds":"НДС не облагается",
         "goal":" Оплата товара по заказу №090738231",
         "from_name_p":"Николаевич",
         "from_name":"Иван",
         "from_name_f":"Михайлов",
         "info":"Коммерческие организации",
         "to_name":"ООО \"Технический Центр ДЕЛЬТА\"",
         "to_inn":"7726111111",
         "account":"40711100000012321",
         "toServiceId":"1717"
  }
}
Parameter Type Description
fields.name String Recipient's bank name (escape quotes with \)
fields.extra_to_bik String Recipient's bank MFO (BIK)
fields.to_bik String Recipient's bank MFO (BIK)
fields.city String Recipient's city of placement
fields.info String Constant, Коммерческие организации (in Russian)
fields.is_commercial String Service info, constant 1
fields.to_name String Recipient's organization name (escape quotes with \)
fields.to_inn String Organization's TIN
fields.to_kpp String Organization's KPP (code for the reason in the tax service regisration)
fields.nds String Value-added tax flag. If you pay for invoice and there is no VAT, then put the string НДС не облагается (in Russian). Otherwise, put the string В т.ч. НДС (in Russian).
fields.goal String Payment appointment
fields.urgent String Urgent payment (0 - no, 1 - yes). Urgent payment is made in 10 minutes or more. It is applicable for weekdays from 9:00 to 20:30, Moscow time zone. Extra fee for the service is 25 rubles.
fields.account String Recipient's account number
fields.from_name String Recipient's first name
fields.from_name_p String Recipient's middle name
fields.from_name_f String Recipient's last name
fields.requestProtocol String Service info, constant qw1
fields.toServiceId String Service info, QIWI provider ID 1717

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "21131343",
  "terms": "1717",
  "fields": {
         "extra_to_bik":"044525201",
         "requestProtocol":"qw1",
         "city":"МОСКВА",
         "name":"ПАО АКБ \"АВАНГАРД\"",
         "to_bik":"044525201",
         "urgent":"0",
         "to_kpp":"772111001",
         "is_commercial":"1",
         "nds":"НДС не облагается",
         "goal":" Оплата товара по заказу №090738231",
         "from_name_p":"Николаевич",
         "from_name":"Иван",
         "from_name_f":"Михайлов",
         "info":"Коммерческие организации",
         "to_name":"ООО \"Технический Центр ДЕЛЬТА\"",
         "to_inn":"7726111111",
         "account":"40711100000012321",
         "toServiceId":"1717"
  },
  "sum": {
         "amount": 1000,
         "currency": "643"
  },
  "source": "account_643",
  "transaction": {
         "id": "10969142201",
         "state": {
            "code": "Accepted"
          }
  }
}

Successful response contains JSON-object PaymentInfo with accepted payment data.

Search by string

Use API for searching QIWI provider's ID in payment methods.

Request → POST

user@server:~$ curl -X POST "https://qiwi.com/search/results/json.action?searchPhrase=%D0%91%D0%B8%D0%BB%D0%B0%D0%B9%D0%BD+%D0%B4%D0%BE%D0%BC%D0%B0%D1%88%D0%BD%D0%B8%D0%B9+%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BD%D0%B5%D1%82" \
  --header "Accept: application/json"
POST /search/results/json.action?searchPhrase=%D0%91%D0%B8%D0%BB%D0%B0%D0%B9%D0%BD+%D0%B4%D0%BE%D0%BC%D0%B0%D1%88%D0%BD%D0%B8%D0%B9+%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BD%D0%B5%D1%82 HTTP/1.1
Accept: application/json
Host: qiwi.com
import requests

# provider id by its name
def qiwi_com_search(search_phrase):
    s = requests.Session()
    search = s.post('https://qiwi.com/search/results/json.action', params={'searchPhrase':search_phrase})
    return search.json()['data']['items']

Response ←

HTTP/1.1 200 OK
Content-Type: application/json
  
{
  "data": {
    ...
    "items": [
      {
        "item": {
          "id": {
            "id": "120",
            ...
          },
          ...
        },
        ...
      }
    ]
  }
}
# get Beeline Internet  provider ID
prv = qiwi_com_search('Билайн домашний интернет')[0]['item']['id']['id']
print(prv)

Successful JSON-response contains IDs of the found QIWI providers:

Parameter Type Description
data.items Array List of providers
items[].item.id.id String Provider's ID in the array's element

Mobile network operator

Use the method for mobile network operator determination by the client's mobile number. Response returns QIWI provider ID for using in the API method of the client's mobile phone replenishment.

Request → POST

user@server:~$ curl -X POST "https://qiwi.com/mobile/detect.action" \
  --header "Accept: application/json" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  -d "phone=79651238341"
POST /mobile/detect.action HTTP/1.1
Host: qiwi.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache

phone=79651238341
import requests

def mobile_operator(phone_number):
    s = requests.Session()
    res = s.post('https://qiwi.com/mobile/detect.action', data = {'phone': phone_number })
    s.headers['Accept'] = 'application/json'
    s.headers['Content-Type'] = 'application/x-www-form-urlencoded'
    return res.json()['message']
Parameter Type Description
phone String URL-encoded Client's mobile phone number, international format without +. Required.

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": {
    "value": "0",
    "_name": "NORMAL"
  },
  "data": null,
  "message": "3",
  "messages": null
}

Cannot determine the mobile operator

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": {
    "value": "2",
    "_name": "ERROR"
  },
 "data": null,
 "message": "По указанному номеру невозможно определить оператора сотовой связи. Воспользуйтесь поиском.",
 "messages": {}
}
print(mobile_operator(79652468447))

Response with HTTP Status 200 and code.value = 0 means successful operator determination. QIWI provider ID is the value of message field.

Response with HTTP Status 200 and code.value = 2 means that operator determination is not possible.

Card transfer provider

To get QIWI provider ID for money transfer to credit card, use the following method.

No authorization is required.

Request → POST

user@server:~$ curl -X POST "https://qiwi.com/card/detect.action" \
  --header "Accept: application/json" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  -d "cardNumber=4256********1231"
POST /card/detect.action HTTP/1.1
Host: qiwi.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache

cardNumber=4256********1231
import requests

def card_system(card_number):
    s = requests.Session()
    res = s.post('https://qiwi.com/card/detect.action', data = {'cardNumber': card_number })
    return res.json()['message']
Parameter Type Description
cardNumber String Full card number (no spaces). Required

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code": {
    "value": "0",
    "_name": "NORMAL"
  },
  "data": null,
  "message": "1963",
  "messages": null
}
print(card_system(4890xxxxxxxx1698))

Cannot get provider ID for credit card money tranfser

HTTP/1.1 200 OK
Content-Type: application/json

{
    "code": {
        "value": "2",
        "_name": "ERROR"
    },
    "data": null,
    "message": "Неверно введен номер банковской карты. Попробуйте ввести номер еще раз.",
    "messages": {}
}

Response with HTTP Status 200 and code.value = 0 means successful ID determination. QIWI provider ID is the value of message field.

Response with HTTP Status 200 and code.value = 2 means that ID determination is not possible (wrong card number or payment system is not supported).

API data models

Payment class

{
  "id":"21131343",
  "sum": {
        "amount":1000,
        "currency":"643"
  },
  "paymentMethod": {
      "type":"Account",
      "accountId":"643"
  },
  "fields": {
         "extra_to_bik":"044525201",
         "requestProtocol":"qw1",
         "city":"МОСКВА",
         "name":"ПАО АКБ \"АВАНГАРД\"",
         "to_bik":"044525201",
         "urgent":"0",
         "to_kpp":"772111001",
         "is_commercial":"1",
         "nds":"НДС не облагается",
         "goal":" Оплата товара по заказу №090738231",
         "from_name_p":"Николаевич",
         "from_name":"Иван",
         "from_name_f":"Михайлов",
         "info":"Коммерческие организации",
         "to_name":"ООО \"Технический Центр ДЕЛЬТА\"",
         "to_inn":"7726111111",
         "account":"40711100000012321",
         "toServiceId":"1717"
  }
}

Object describes payment data for QIWI Wallet provider.

Parameter Type Description Required
id String Client transaction ID (max 20 digits). Must be unique for each transaction. Increment with each following transaction. To satisfy these requirements, set it to 1000*(Standard Unix time in seconds). +
sum Object Payment amount data  
sum.amount Number Payment amount value (rubles and kopeks, separator .). Positive number rounded down to 2 decimals. If you specify more decimals, our system will round the number down to the same precision. +
sum.currency String Payment currency (only rubles, 643) +
paymentMethod Object QIWI wallet account to fund the payment  
paymentMethod.type String Constant, Account +
paymentMethod.accountId String Constant, 643 +
fields Object Payment requisites. Object fields depend on provider ID.  
comment String Payment comment. Used for QIWI wallet transfer or conversion only -

PaymentInfo class

{
    "id": "150217833198900",
    "terms": "99",
    "fields": {
        "account": "79121238345"
    },
    "sum": {
        "amount": 100,
        "currency": "643"
    },
    "transaction": {
        "id": "11155897070",
        "state": {
            "code": "Accepted"
        }
    },
    "source": "account_643",
    "comment": "test"
}

Object describes QIWI wallet transaction data and returns in response from Payment API.

Parameter Type Description
id Number id parameter from the original request
terms String QIWI provider ID used for the payment
fields Object fields object from the original request. Card number returns in masked form
sum Object sum object from the original request
source String Always constant, account_643
comment String comment parameter from the original request (if exists in the request)
transaction Object Object with QIWI transaction data
transaction.id String QIWI transaction ID
transaction.state Object Current state of the transaction
state.code String Current status of the transaction. Only Accepted is returned (it means that the payment is accepted for processing). Actual transaction status can be obtained from Payments history API.

Invoices

Invoice is the universal request for payment or money transfer in QIWI Wallet system.

API provides operations of invoice creation (only P2P invoices for money transfer to another QIWI wallet), payment, rejection, and also method for requesting list of unpaid invoices issued to your QIWI wallet.

Invoice issue and P2P token

You can issue invoices to any QIWI wallet by using P2P invoices API. Use special P2P token for authorization in P2P invoices API.

How to get P2P token

To get P2P token, authorize on p2p.qiwi.com, or use the given request. You may also specify Invoice payment callbacks URL in this request.

The method returns P2P tokens for using with Payment form and with P2P API in PublicKey and SecretKey fields of the response.

Use QIWI Wallet API token for authorization.

Request → POST

curl -X POST \
  https://edge.qiwi.com/widgets-api/api/p2p/protected/keys/create \
  -H 'Authorization: Bearer ec74********' \
  -H 'Content-Type: application/json' \
  -H 'cache-control: no-cache' \
  -d '{"keysPairName":"Name","serverNotificationsUrl":"https://test.com"}'
POST /widgets-api/api/p2p/protected/keys/create HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
Content-Type: application/json
User-Agent: ****

{"keysPairName":"Name", "serverNotificationsUrl":"https://test.com"}
Parameter Type Description
keysPairName String Name for the couple of P2P tokens
serverNotificationsUrl String Invoice payment callbacks URL (optional)

List of invoices

API provides the method for getting unpaid invoices issued to your wallet. Invoices are placed in the list in reverse chronological order. By default, the list is paginated on 50 elements on each page. You can specify the number of elements on each page. You may use filters: invoice creation period of dates and starting invoice ID.

Request → GET

user@server:~$ curl -X GET --header 'Accept: application/json' \
   --header 'Authorization: Bearer ***' \
   'https://edge.qiwi.com/checkout-api/api/bill/search?statuses=READY_FOR_PAY&rows=50'
GET /checkout-api/api/bill/search?statuses=READY_FOR_PAY&rows=50 HTTP/1.1
Accept: application/json
Authorization: Bearer ***
Host: edge.qiwi.com
User-Agent: ****
Parameter Type Description
statuses String Unpaid invoice status. Only READY_FOR_PAY. Required parameter.
rows Integer Maximum number of invoices to be returned, for list pagination. Integer number from 1 to 50. Default value is 50.
min_creation_datetime Long Lower time limit for invoice search, Unix-time
max_creation_datetime Long Greater time limit for invoice search, Unix-time
next_id Number Starting invoice identifier for invoice search. Only invoices with IDs equal or smaller than this ID are returned. Use it for obtaining next invoices in the paginated list.
next_creation_datetime Long Starting date for invoice search, Unix-time. Only invoices created before this date are returned. Use it for obtaining next invoices in the paginated list.

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "bills": [
    {
      "id": 1063702405,
      "external_id": "154140605",
      "creation_datetime": 1523025585000,
      "expiration_datetime": 1523026003808,
      "sum": {
        "currency": 643,
        "amount": 100
      },
      "status": "READY_FOR_PAY",
      "type": "MERCHANT",
      "repetitive": false,
      "provider": {
        "id": 480706,
        "short_name": "Букмекерская контора ФОНБЕТ",
        "long_name": "ООО «Ф.О.Н.»",
        "logo_url":"https://static.qiwi.com/img/providers/logoBig/480706_l.png"
      },
      "comment": "Deposit to FON 13515573",
      "pay_url":"https://oplata.qiwi.com/form?shop=480706&transaction=102263702405"
    }
  ]
}

Successful JSON response includes a list of unpaid invoices according to the conditions of the request:

Parameter Type Description
bills Array[Object] List of invoices.
List length is rows parameter from the original request, or 50, if it is absent
bills[].id Integer QIWI Wallet invoice ID
bills[].external_id String Merchant's invoice ID
bills[].creation_datetime Long Date/time of the invoice creation, Unix-time
bills[].expiration_datetime Long Date/time of the invoice expiration, Unix-time
bills[].sum Object Invoice amount data
sum.currency Integer Invoice currency
sum.amount Number Invoice amount
bills[].status String Constant, READY_FOR_PAY
bills[].type String Cinstant, MERCHANT
bills[].repetitive Boolean Service data
bills[].provider Object Merchant information
provider.id Integer QIWI identifier
provider.short_name String Short name
provider.long_name String Full name
provider.logo_url String Logo URL
bills[].comment String Invoce comment
bills[].pay_url String URL to pay for the invoice on QIWI Payment Form

Invoice payment

The request makes invoice payment immediately without SMS confirmation.

Request → POST

user@server:~$ curl -X POST --header 'Content-Type: application/json;charset=UTF-8' \
   --header 'Accept: application/json' \
   --header 'Authorization: Bearer 68ec21fd52e4244838946dd07ed225a1' \
   -d '{ \
         "invoice_uid": "1063702405", \
         "currency": "643" \
        }' 'https://edge.qiwi.com/checkout-api/invoice/pay/wallet'
POST /checkout-api/invoice/pay/wallet HTTP/1.1
Accept: application/json
Content-type: application/json
Authorization: Bearer ***
Host: edge.qiwi.com
User-Agent: ****

{
   "invoice_uid": "1063702405",
   "currency": "643"
}
Parameter Type Description
invoice_uid String QIWI invoice ID (take it from bills[].id field of invoice data
currency String Invoice currency (take it from bills[].sum.currency field of invoice data)

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "invoice_status": "PAID_STATUS",
  "is_sms_confirm": false,
  "WALLET_ACCEPT_PAY_RESULT": {}
}

Successful response contains JSON with paid invoice status:

Field Type Description
invoice_status String Invoice payment status, PAID_STATUS. Any other status means unsuccessful transaction.
is_sms_confirm String SMS confirmation flag

Unpaid invoice cancelling

The method rejects an unpaid invoice. This makes the account unavailable for payment.

Request → POST

user@server:~$ curl -X POST --header 'Accept: application/json' \
                            --header 'Authorization: Bearer ***' \
                            'https://edge.qiwi.com/checkout-api/api/bill/reject' \
                            -d '{ "id": 1034353453 }'
POST /checkout-api/api/bill/reject HTTP/1.1
Accept: application/json
Authorization: Bearer ***
Content-type: application/json
Host: edge.qiwi.com
User-Agent: ****

{
  "id": 1034353453
}
Parameter Type Description
id Integer Invoice ID to reject (take it from bills[].id field of invoice data

Response ←

HTTP/1.1 200 OK
Content-Type: application/json

Successful response has HTTP code 200.

Callbacks

Last update: 2020-07-28 | Edit on GitHub

Исходящие платежи - платеж в проведении

POST /some-hook.php HTTP/1.1
Accept: application/json
Content-type: application/json
Host: falcon.com

{"hash": "50779a03d90c4fa60ac44dfd158dbceec0e9c57fa4cf4f5298450fdde1868945",
 "hookId": "f57f95e2-149f-4278-b2cb-4114bc319727",
 "messageId": "f9a197a8-26b6-4d42-aac4-d86b789c373c",
 "payment": {"account": "thedandod",
             "comment": "",
             "commission": Null,
             "date": "2018-05-18T16:05:15+03:00",
             "errorCode": "0",
             "personId": 79254914194,
             "provider": 25549,
             "signFields": "sum.currency,sum.amount,type,account,txnId",
             "status": "WAITING",
             "sum": {"amount": 1.73, "currency": 643},
             "total": {"amount": 1.73, "currency": 643},
             "txnId": "13117338074",
             "type": "OUT"},
 "test": false,
 "version": "1.0.0"}

Исходящие платежи - успешный платеж

POST /some-hook.php HTTP/1.1
Accept: application/json
Content-type: application/json
Host: falcon.com

{"hash": "50779a03d90c4fa60ac44dfd158dbceec0e9c57fa4cf4f5298450fdde1868945",
 "hookId": "f57f95e2-149f-4278-b2cb-4114bc319727",
 "messageId": "6e2a0e32-4c8d-4fe2-9eed-fe3b6a726ff4",
 "payment": {"account": "thedandod",
             "comment": "",
             "commission": {"amount": 0.0, "currency": 643},
             "date": "2018-05-18T16:05:15+03:00",
             "errorCode": "0",
             "personId": 79254914194,
             "provider": 25549,
             "signFields": "sum.currency,sum.amount,type,account,txnId",
             "status": "SUCCESS",
             "sum": {"amount": 1.73, "currency": 643},
             "total": {"amount": 1.73, "currency": 643},
             "txnId": "13117338074",
             "type": "OUT"},
 "test": false,
 "version": "1.0.0"}

Исходящие платежи - неуспешный платеж

POST /some-hook.php HTTP/1.1
Accept: application/json
Content-type: application/json
Host: falcon.com

{"hash": "0637b07b1018d76585db26b0f8077016b12996006429e22a7dc5b6982710a1ef",
 "hookId": "f57f95e2-149f-4278-b2cb-4114bc319727",
 "messageId": "1133873b-9bb6-4adb-9bfe-7be3a9aa999f",
 "payment": {"account": "borya241203",
             "comment": "",
             "commission": None,
             "date": "2018-05-20T05:19:16+03:00",
             "errorCode": "5",
             "personId": 79254914194,
             "provider": 25549,
             "signFields": "sum.currency,sum.amount,type,account,txnId",
             "status": "ERROR",
             "sum": {"amount": 1.01, "currency": 643},
             "total": {"amount": 1.01, "currency": 643},
             "txnId": "13126423989",
             "type": "OUT"},
 "test": false,
 "version": "1.0.0"}

Входящие платежи - успешный платеж

POST /some-hook.php HTTP/1.1
Accept: application/json
Content-type: application/json
Host: falcon.com

{"hash": "a56ed0090fa3fd2fd0b002ed80f85a120037a6a85f840938888275e1631da96f",
 "hookId": "8c79f60d-0272-476b-b120-6e7629467328",
 "messageId": "bba24947-ab5f-4b33-881b-738fc3a4c9e1",
 "payment": {"account": "79042426915",
             "comment": "Order i_4769798 Счет №65361451. Пополнение аккаунта "
                        "P11689160 (garik3315@gmail.com) в платежной системе "
                        "Payeer. Внимание! Не меняйте сумму, валюту и "
                        "комментарий к переводу, не делайте повторный перевод, "
                        "в ином случае Ваш платеж зачислен НЕ будет!",
             "commission": {"amount": 0.0, "currency": 643},
             "date": "2018-03-25T13:16:48+03:00",
             "errorCode": "0",
             "personId": 79645265240,
             "provider": 7,
             "signFields": "sum.currency,sum.amount,type,account,txnId",
             "status": "SUCCESS",
             "sum": {"amount": 1.09, "currency": 643},
             "total": {"amount": 1.09, "currency": 643},
             "txnId": "12565018935",
             "type": "IN"},
 "test": false,
 "version": "1.0.0"}

Хуки или уведомления с данными о событии (платеже/пополнении) отправляются на ваш сервер. В настоящее время поддерживаются только вебхуки (webhook) - сообщения, адресованные веб-сервисам. Для приема вебхуков вам необходимо настроить свой сервер на прием и обработку POST-запросов (Формат запросов).

От вашего сервера успешный ответ 200 OK на входящий запрос должен поступить в течение 1-2 сек. Не дождавшись ответа, сервис КИВИ отправляет еще одно уведомление через 10 минут, потом еще одно через 1 час.

Пулы IP-адресов, с которых сервисы QIWI отправляют webhook:

Если ваш сервер обработки вебхуков работает за брандмауэром, необходимо добавить эти IP-адреса в список разрешенных адресов входящих TCP-пакетов.

Быстрый старт

  1. Реализуйте веб-сервис обработки запросов. Особое внимание обратите на реализацию проверки подписи.
  2. Зарегистрируйте свой обработчик PUT-запросом. Внимание! Длина адреса сервиса обработчика не должна превышать 100 символов.
  3. Запросите ключ проверки подписи.
  4. Протестируйте прием запросов вашим обработчиком с помощью тестового запроса. На зарегистрированный в п.1 сервис придет пустой вебхук.

Чтобы сменить адрес сервера для обработки вебхуков:

  1. Удалите обработчик вебхуков DELETE-запросом.
  2. Зарегистрируйте новый обработчик PUT-запросом. Внимание! Длина адреса сервиса обработчика не должна превышать 100 символов.
  3. Запросите ключ проверки подписи для нового обработчика.
  4. Протестируйте прием запросов новым обработчиком с помощью тестового запроса. На зарегистрированный в п.2 сервис придет пустой вебхук.

Обработка вебхука

Каждый вебхук - входящий POST-запрос с JSON-объектом, содержащий данные об одном платеже. Схема объекта:

POST /some-hook.php HTTP/1.1
Accept: application/json
Content-type: application/json
Host: falcon.com

{"hash": "a56ed0090fa3fd2fd0b002ed80f85a120037a6a85f840938888275e1631da96f",
 "hookId": "8c79f60d-0272-476b-b120-6e7629467328",
 "messageId": "bba24947-ab5f-4b33-881b-738fc3a4c9e1",
 "payment": {"account": "79042426915",
             "comment": "Order i_4769798 Счет №65361451. Пополнение аккаунта "
                        "P11689160 (garik3315@gmail.com) в платежной системе "
                        "Payeer. Внимание! Не меняйте сумму, валюту и "
                        "комментарий к переводу, не делайте повторный перевод, "
                        "в ином случае Ваш платеж зачислен НЕ будет!",
             "commission": {"amount": 0.0, "currency": 643},
             "date": "2018-03-25T13:16:48+03:00",
             "errorCode": "0",
             "personId": 79645265240,
             "provider": 7,
             "signFields": "sum.currency,sum.amount,type,account,txnId",
             "status": "SUCCESS",
             "sum": {"amount": 1.09, "currency": 643},
             "total": {"amount": 1.09, "currency": 643},
             "txnId": "12565018935",
             "type": "IN"},
 "test": false,
 "version": "1.0.0"}
<?php

//Функция возвращает упорядоченную строку значений параметров webhook и хэш подписи webhook для проверки
function getReqParams(){

    //Make sure that it is a POST request.
    if(strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0){
        throw new Exception('Request method must be POST!');
    }

    //Receive the RAW post data.
    $content = trim(file_get_contents("php://input"));

    //Attempt to decode the incoming RAW post data from JSON.
    $decoded = json_decode($content, true);

    //If json_decode failed, the JSON is invalid.
    if(!is_array($decoded)){
        throw new Exception('Received content contained invalid JSON!');
    }

    //Check if test
    if ($decoded['test'] == 'true') {
      throw new Exception('Test!');
    }

    // Строка параметров
    $reqparams = $decoded['payment']['sum']['currency'] . '|' . $decoded['payment']['sum']['amount'] . '|'. $decoded['payment']['type'] . '|' . $decoded['payment']['account'] . '|' . $decoded['payment']['txnId'];
    // Подпись из запроса
    foreach ($decoded as $name=>$value) {
       if ($name == 'hash') {
            $SIGN_REQ = $value;
       }
    }

    return [$reqparams, $SIGN_REQ];
}

// Список параметров и подпись

$Request = getReqParams();

// Base64 encoded ключ для дешифровки вебхуков (метод /hook/{hookId}/key)

$NOTIFY_PWD = "JcyVhjHCvHQwufz+IHXolyqHgEc5MoayBfParl6Guoc=";

// Вычисляем хэш SHA-256 строки параметров и шифруем с ключом для веб-хуков

$reqres = hash_hmac("sha256", $Request[0], base64_decode($NOTIFY_PWD));

// Проверка подписи вебхука

if (hash_equals($reqres, $Request[1])) {
    $error = array('response' => 'OK');
}
else $error = array('response' => 'error');

//Ответ

header('Content-Type: application/json');
$jsonres = json_encode($error);
echo $jsonres;
error_log('error code' . $jsonres);
?>
import base64
import hmac
import hashlib

# Base64 encoded ключ для расшифровки вебхука (/hook/{hookId}/key)
webhook_key_base64 = 'JcyVhjHCvHQwufz+IHXolyqHgEc5MoayBfParl6Guoc='

# строка параметров
data = '643|1|IN|+79165238345|13353941550'

webhook_key = base64.b64decode(bytes(webhook_key_base64,'utf-8'))
print(hmac.new(webhook_key, data.encode('utf-8'), hashlib.sha256).hexdigest())
Поле Тип Описание
hookId String (UUID) Уникальный id хука
messageId String (UUID) Уникальный id отправленного вебхука
payment Object Данные платежа
payment.txnId String ID транзакции в процессинге QIWI Wallet
payment.account String Для платежей - номер счета получателя. Для пополнений - номер отправителя, терминала или название агента пополнения кошелька
payment.signFields String Список полей объекта payments (через ,), которые хешируются алгоритмом HmacSHA256 для проверки хука (см. параметр hash)
payment.personId Integer Номер кошелька
payment.date String DateTime Дата/время платежа, в московской временной зоне. Формат даты ГГГГ-ММ-ДД'T'чч:мм:сс+03:00
payment.errorCode String Код ошибки платежа
payment.type String Тип платежа. Возможные значения:
IN - пополнение,
OUT - платеж
payment.status String Статус платежа. Возможные значения:
WAITING - платеж проводится,
SUCCESS - успешный платеж,
ERROR - ошибка платежа.
payment.provider Integer ID провайдера QIWI Wallet
payment.comment String Комментарий к транзакции
payment.sum Object Данные о сумме платежа или пополнения. Параметры:
sum.amount Number(Decimal) Сумма
sum.currency Integer Код валюты
payment.commission Object Данные о комиссии для платежа или пополнения. Параметры:
commission.amount Number(Decimal) Сумма
commission.currency Integer Код валюты
payment.total Object Данные об итоговой сумме платежа или пополнения. Параметры:
total.amount Number(Decimal) Сумма
total.currency Integer Код валюты
test Boolean Признак тестового сообщения
version String Версия API
hash String Хэш цифровой подписи вебхука. Как проверить хэш: берутся значения полей из списка payment.signFields (в том же порядке) в формате String, конкатенируются с разделителем | и шифруются алгоритмом SHA-256 с ключом проверки подписи. Полученное значение сравнивается с тем, что пришло в поле hash.

Пример расшифровки подписи (см. также функцию PHP на вкладке справа):

  1. По запросу пользователь получает свой ключ, закодированный в Base64: JcyVhjHCvHQwufz+IHXolyqHgEc5MoayBfParl6Guoc=
  2. Приходит вебхук {"messageId":"7814c49d-2d29-4b14-b2dc-36b377c76156","hookId":"5e2027d1-f5f3-4ad1-b409-058b8b8a8c22","payment":{"txnId":"13353941550","date":"2018-06-27T13:39:00+03:00","type":"IN","status":"SUCCESS","errorCode":"0","personId":78000008000,"account":"+79165238345","comment":"","provider":7,"sum":{"amount":1,"currency":643},"commission":{"amount":0,"currency":643},"total":{"amount":1,"currency":643},"signFields":"sum.currency,sum.amount,type,account,txnId"},"hash":"76687ffe5c516c793faa46fafba0994e7ca7a6d735966e0e0c0b65eaa43bdca0","version":"1.0.0","test":false}
  3. Склеиваются требуемые поля платежных данных: 643|1|IN|+79165238345|13353941550
  4. Поля шифруются методом SHA-256 с раскодированным ключом из п.1. Результат 76687ffe5c516c793faa46fafba0994e7ca7a6d735966e0e0c0b65eaa43bdca0 совпадает с параметром hash из запроса.

Регистрация обработчика вебхуков

Запрос → PUT

curl -X PUT "https://edge.qiwi.com/payment-notifier/v1/hooks?hookType=1&param=http%3A%2F%2Fecho.fjfalcon.ru%2F&txnType=2" \
     -H "accept: */*" \
     -H "authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f"
PUT /payment-notifier/v1/hooks?hookType=1&param=http%3A%2F%2Fecho.fjfalcon.ru%2F&txnType=2 HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
User-Agent: ****
Название Тип Описание
hookType Integer Тип хука. Только 1 - вебхук.
param URL-encoded Адрес сервера обработки вебхуков. Внимание! Длина исходного (не URL-encoded) адреса сервиса обработчика не должна превышать 100 символов.
txnType String Тип транзакций, по которым будут включены уведомления. Возможные значения:
0 - только входящие транзакции (пополнения)
1 - только исходящие транзакции (платежи)
2 - все транзакции

Ответ ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "hookId":"d63a8729-f5c8-486f-907d-9fb8758afcfc",
  "hookParameters":{
    "url":"http://echo.fjfalcon.ru/"
  },
  "hookType":"WEB",
  "txnType":"BOTH"
}

Ответ в формате JSON.

Название Тип Описание
hookId String UUID созданного вебхука
hookParameters Object Набор параметров вебхука (только URL)
hookType String Тип вебхука (только WEB)
txnType String Тип транзакций, по которым отсылаются вебхуки (IN - входящие, OUT - исходящие, BOTH - все)

Удаление обработчика вебхуков

Запрос → DELETE

curl -X DELETE "https://edge.qiwi.com/payment-notifier/v1/hooks/d63a8729-f5c8-486f-907d-9fb8758afcfc" \
   -H "accept: */*" \
   -H "authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f"
DELETE /payment-notifier/v1/hooks/d63a8729-f5c8-486f-907d-9fb8758afcfc HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
User-Agent: ****

Ответ ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "response":"Hook deleted"
}

Формат ответа JSON.

Название Тип Описание
response String Описание результата операции

Получение секретного ключа

Каждый вебхук содержит цифровую подпись сообщения, зашифрованную ключом. Для получения ключа проверки подписи используйте данный запрос.

Запрос → GET

curl -X GET "https://edge.qiwi.com/payment-notifier/v1/hooks/d63a8729-f5c8-486f-907d-9fb8758afcfc/key" \
   -H "accept: */*" \
    -H "accept: */*" \
    -H "authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f"
GET /payment-notifier/v1/hooks/d63a8729-f5c8-486f-907d-9fb8758afcfc/key HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
User-Agent: ****

Ответ ←

HTTP/1.1 201 Created
Content-Type: application/json

{
  "key":"L8UVF3JkLVUr6r70LiE0A9/5WoGGwWKG2pI/e+l/9fs="
}

Формат ответа JSON.

Название Тип Описание
key String Base64-закодированный ключ

Изменение секретного ключа

Для смены ключа шифрования сообщений вебхука используйте данный запрос.

Запрос → POST

curl -X POST "https://edge.qiwi.com/payment-notifier/v1/hooks/d63a8729-f5c8-486f-907d-9fb8758afcfc/newkey" \
   -H "accept: */*" \
   -H "authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f"
POST /payment-notifier/v1/hooks/d63a8729-f5c8-486f-907d-9fb8758afcfc/newkey HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
User-Agent: ****

Ответ ←

HTTP/1.1 201 Created
Content-Type: application/json

{
  "key":"OikS4/CcIbSf+yYGnLbnOige8RGoYmGxs/LNMwkJy7Q="
}

Формат ответа JSON.

Название Тип Описание
key String Base64-закодированный новый ключ

Данные об обработчике вебхуков

Список действующих (активных) обработчиков вебхуков, связанных с вашим кошельком, можно получить данным запросом.

Так как сейчас используется только один тип хуков - вебхуки, то в ответе содержится только один объект данных.

Запрос → GET

curl -X GET "https://edge.qiwi.com/payment-notifier/v1/hooks/active" \
   -H "accept: */*" \
   -H "accept: */*" \
   -H "authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f"
GET /payment-notifier/v1/hooks/active HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
User-Agent: ****

Ответ ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "hookId":"d63a8729-f5c8-486f-907d-9fb8758afcfc",
  "hookParameters":{
    "url":"http://echo.fjfalcon.ru/"
  },
  "hookType":"WEB",
  "txnType":"BOTH"
}

Формат ответа JSON.

Название Тип Описание
hookId String UUID действующего обработчика вебхуков
hookParameters Object Набор параметров обработчика (только URL)
hookType String Тип вебхука (только WEB)
txnType String Тип транзакций, по которым отсылаются уведомления (IN - входящие, OUT - исходящие, BOTH - все)

Отправка тестового вебхука

Для проверки вашего обработчика вебхуков используйте данный запрос. Запрос отправляется на адрес, указанный в параметрах действующего обработчика.

Запрос → GET

curl -X GET "https://edge.qiwi.com/payment-notifier/v1/hooks/test" \
   -H "accept: */*" \
   -H "authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f"
POST /payment-notifier/v1/hooks/test HTTP/1.1
Host: edge.qiwi.com
Authorization: Bearer 3b7beb2044c4dd4a8f4588d4a6b6c93f
User-Agent: ****

Ответ ←

HTTP/1.1 200 OK
Content-Type: application/json

{
  "response":"Webhook sent"
}

Формат ответа JSON.

Название Тип Описание
response String Результат запроса

Error Codes

В случае ошибки API возвращается HTTP-код ошибки.

HTTP Код Секция API Описание
400 Все Ошибка синтаксиса запроса (неправильный формат данных)
401 Все Неверный токен или истек срок действия токена API
403 Все Нет прав на данный запрос (недостаточно разрешений у токена API)
404 История платежей, Информация о транзакции, Отправка квитанции Не найдена транзакция или отсутствуют платежи с указанными признаками
404 Балансы, Профиль пользователя, Идентификация пользователя Не найден кошелек
404 Веб-хуки Не найден активный веб-хук
404 Оплата/Отмена счета Не найден счет
422 Регистрация веб-хука Неправильно указаны домен/подсеть/хост веб-хука(в параметре param для URL веб-хука), неправильно указаны тип хука или тип транзакции, попытка создать хук при наличии уже созданного
423 Все Слишком много запросов, сервис временно недоступен
500 Все Внутренняя ошибка сервиса (превышена длина URL веб-хука, проблемы с инфраструктурой, недоступность каких-либо ресурсов и т.д.)

Следующие ошибки возвращаются на запросы истории платежей и информации о транзакции в параметре errorCode ответа:

errorCode Описание
0 OK
3 Техническая ошибка, нельзя отправить запрос провайдеру
4 Неверный формат счета/телефона
5 Номер не принадлежит оператору
8 Прием платежа запрещен по техническим причинам
131 Платежи на выбранного провайдера запрещено проводить из данной страны.
202 Ошибка в параметрах запроса
220 Недостаточно средств
241 Сумма платежа меньше минимальной
242 Сумма платежа больше максимальной
319 Платеж невозможен
500 По техническим причинам этот платеж не может быть выполнен. Для совершения платежа обратитесь, пожалуйста, в свой обслуживающий банк
522 Неверный номер или срок действия карты получателя
547 Ошибка в сроке действия карты получателя
548 Истек срок действия карты получателя
561 Платеж отвергнут оператором банка получателя
702 Платеж не проведен из-за ограничений у получателя. Подробности по телефону: 8-800-707-77-59
705 Ежемесячный лимит платежей и переводов для статуса Стандарт - 200 000 р. Для увеличения лимита пройдите идентификацию.
746 Превышен лимит по платежам в пользу провайдера
852 Превышен лимит по платежам в пользу провайдера
893 Срок действия перевода истек
1050 Превышен лимит на операции, либо превышен дневной лимит на переводы на карты Visa/MasterCard