NAV
cURL Python

Authentication

Toman uses OAuth 2.0 to authorize API requests. We will provide you with the required Username, Password, Client ID, and Client Secret required for the process of token acquirement.

Each endpoint in our project has none, one, or more scope requirements, which can be found in the endpoint documentation. Note that you have to had included the required scopes in your authentication process in order to be allowed to use them.

The authentication process URL for our staging and productions servers are:

Environment Auth URL
Production https://accounts.qbitpay.org/oauth2/token/
Staging https://auth.qbitpay.org/oauth2/token/

The acquired token should be included among request headers with the prefix Bearer:

Authorization: Bearer 5OGgq1FQS7jPITItICRwlDYZv5P91A

Get Access Token

To acquire your access token, you need to send your username, password, client_id, and client_secret to the auth endpoint.

Request Data Example (Without Basic Authentication)

Sample Code (Without Basic Authentication)

import requests

auth_url = "https://auth.qbitpay.org/oauth2/token/"
username = "MY_USERNAME"
password = "MY_PASSWORD"
client_id = "MY_CLIENT_ID"
client_secret = "MY_CLIENT_SECRET"

response = requests.request(
    "POST",
    auth_url,
    data={
        "client_id": client_id,
        "client_secret": client_secret,
        "username": username,
        "password": password,
        "grant_type": "password",
        "scope": "settlement.wallet.retrieve"
    },
)
token = response.json()["access_token"]
refresh_token = response.json()["refresh_token"]

authorization_header = {
    "Authorization": f"Bearer {token}"
}

endpoint_response = requests.request(
    "GET",
    "https://settlement-staging.qbitpay.org/wallets/deposits/summary/",
    headers=authorization_header
)

print(endpoint_response.json())

curl -X POST -d "username=$USERNAME" \
             -d "password=$PASSWORD" \
             -d "client_id=$CLIENT_ID" \
             -d "client_secret=$CLIENT_SECRET" \
             -d "grant_type=password" \
             -d "scope=settlement.wallet.retrieve" \
             $AUTH_URL

curl -H "Authorization: Bearer $TOKEN" $API_ENDPOINT
POST /oauth2/token/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: auth.qbitpay.org

grant_type=password&
client_id=MY_CLIENT_ID&
client_secret=MY_CLIENT_SECRET&
username=MY_USERNAME&
password=MY_PASSWORD&
scope=settlement.single.submit%20settlement.single.verify

Request Data Example (Using Basic Authentication)

Sample Code (Using Basic Authentication)

import requests

auth_url = "https://auth.qbitpay.org/oauth2/token/"
username = "MY_USERNAME"
password = "MY_PASSWORD"
client_id = "MY_CLIENT_ID"
client_secret = "MY_CLIENT_SECRET"

response = requests.request(
    "POST",
    auth_url,
    data={
        "username": username,
        "password": password,
        "grant_type": "password",
        "scope": "settlement.wallet.retrieve"
    },
    # this is how requests handles the basic http authentication
    auth=(client_id, client_secret)
)
token = response.json()["access_token"]
refresh_token = response.json()["refresh_token"]

authorization_header = {
    "Authorization": f"Bearer {token}"
}

endpoint_response = requests.request(
    "GET",
    "https://settlement-staging.qbitpay.org/wallets/deposits/summary/",
    headers=authorization_header
)

print(endpoint_response.json())

curl -u $CLIENT_ID:$CLIENT_SECRET -X POST -d "username=$USERNAME" \
                                          -d "password=$PASSWORD" \
                                          -d "grant_type=password" \
                                          -d "scope=settlement.wallet.retrieve" \
                                          $AUTH_URL

curl -H "Authorization: Bearer $TOKEN" $API_ENDPOINT
POST /oauth2/token/ HTTP/1.1
Authorization: Basic TVlfQ0xJRU5UX0lEOk1ZX0NMSUVOVF9TRUNSRVRF
Content-Type: application/x-www-form-urlencoded
Host: auth.qbitpay.org

grant_type=password&
username=MY_USERNAME&
password=MY_PASSWORD&
scope=settlement.single.submit%20settlement.single.verify

Response Data Example

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

{
"access_token":"5OGgq1FQS7jPITItICRwlDYZv5P91A",
"expires_in":86400,
"token_type":"Bearer",
"scope":"settlement.single.submit settlement.single.verify",
"refresh_token":"upTFapSZfpJISYeo0YsZVjf8X29SBy"
}


Refresh Token

Since every access token has an expiration date (see expires_in), you need to acquire a new access token after it expires. The Oauth2 standard, is to use refresh tokens.

To refresh your access token, you need to send your refresh_token, client_id, and client_secret to the auth endpoint with grant_type=refresh_token. The expiration time of the refresh token itself is one week. please notice in the response body of the refresh-token process, a new refresh token will be generated, so we suggest replacing the newly generated refresh token with the old one, for future refresh requests.

Sample Code

response = requests.request(
    "POST",
    auth_url,
    data={
        "grant_type": "refresh_token",
        "refresh_token": refresh_token,
        "client_id": client_id,
        "client_secret": client_secret,
    }
)
access_token = response.json()["access_token"]
new_refresh_token = response.json()["refresh_token"]
curl -X POST -d "refresh_token=$REFRESH_TOKEN"\
             -d "client_id=$CLIENT_ID" \
             -d "client_secret=$CLIENT_SECRET" \
             -d "grant_type=refresh_token" \
             $AUTH_URL

Request Data Example

POST /oauth2/token/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: auth.qbitpay.org

grant_type=refresh_token&
refresh_token=upTFapSZfpJISYeo0YsZVjf8X29SBy&
client_id=MY_CLIENT_ID&
client_secret=MY_CLEINT_SECRET

Response Data Example

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

{
"access_token":"mAGJQqnhLBEZ5UMVAvHVNruOzAyZVs",
"expires_in":86400,
"token_type":"Bearer",
"scope":"settlement.single.submit settlement.single.verify",
"refresh_token":"BLVE2AleqqLHPBmGad4HAQEmqkPr4b"
}

Error Handling

In this section we will list some of the errors that you may encounter while trying to obtian or refresh your tokens.

400_INVALID_SCOPE

{"error": "invalid_scope"}

Reasons

400_INVALID_GRANT

{
    "error"
:
    "invalid_grant", "error_description"
:
    "..."
}

Reasons

401_INVALID_CLIENT

{
    "error"
:
    "invalid_client"
}

Reasons

Enums

1. Bank IDs

Each bank has a unique numeric identifier. The mappings are as follows.

Name Persian Name ID
Shahr شهر 1
Melli ملی 2
Mellat ملت 3
Tejarat تجارت 4
Keshavarzi کشاورزی 5
Refah Kargaran رفاه کارگران 6
Pasargad پاسارگاد 7
Sepah سپه 8
Saderat صادرات 9
Resalat رسالت 10
Tose Saderat توسعه‌ صادرات 11
Sina سینا 12
Ayande آینده 13
Maskan مسکن 14
Saman سامان 15
Karafarin کارآفرین 16
Eghtesad Novin اقتصاد نوین 17
Parsian پارسیان 18
Ansar انصار 19
Sarmaye سرمایه 20
Dey دی 21
gavamin قوامین 22
gardeshgari گردشگری 23
khavarmiane خاورمیانه 24
Sannat Madan صنعت و معدن 25
tose_taavon توسعه تعاون 26
Iran_Zamin ایران زمین 27
Post Bank پست بانک 28
Mehr_Iranian مهر ایرانیان 29
Hekmat Iranian حکمت ایرانیان 30
Moassese Etebari Tose موسسه اعتباری توسعه 31
Moassese Etebari Melal موسسه اعتباری ملل 32
Moassese Etebari Kosar موسسه اعتباری کوثر 33
Moassese Etebari Noor موسسه اعتباری نور 34
Mehr Eghtesad مهر اقتصاد 35
Iran_venezuela مشترک ایران - ونزوئلا 36
Caspian موسسه اعتباری كاسپین 37
Markazi بانک مرکزی 38

APIs

1. Base URLs

The base URLs for our staging and production API servers are as follows:

Environment URL
Production https://inquisitor.toman.ir/api/v1/
Staging https://inquisitor-staging.qcluster.org/api/v1/

Note: Please pay attention to trailing slash at the end of the urls for all endpoints.

2. Card To IBAN

Used to retrieve the IBAN from a given card number.

Sample Code

import requests

url = "https://inquisitor.toman.ir/api/v1/card_to_iban/"

payload = json.dumps({
  "card_number": "6789054325678412"
})
headers = {
    'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

curl --location 'https://inquisitor.toman.ir/api/v1/card_to_iban/' \
--header 'Content-Type: application/json' \
--data '{
    "card_number": "6789054325678412"
}'

Scope

inquiry.card_to_iban.read

Request Body

{ "card_number": "6789054325678412" }

Response Body

The response body contains the card number and IBAN.

Response Data Example

{
    "card_number": "234123465431245",
    "iban": "IR346786453214598456708342"
}

3. Account To IBAN

Used to retrieve the IBAN from a given account number.

Sample Code

import requests

url = "https://inquisitor.toman.ir/api/v1/account_number_to_iban/"

payload = json.dumps({
    "account_number": "732456732147",
    "bank_id": 2
})
headers = {
    'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

curl --location 'https://inquisitor.toman.ir/api/v1/account_number_to_iban/' \
--header 'Content-Type: application/json' \
--data '{
    "account_number": "732456732147",
    "bank_id": 2
}'

Scope

inquiry.account_number_to_iban.read

Request Body

{ "account_number": "732456732147", "bank_id": 2 }

Response Body

The response body contains the account number, IBAN, bank ID, bank name, account owners, account status, and any errors.

Response Data Example

{
    "iban": "IR4432795460000007634516001",
    "deposit": "732456732147",
    "deposit_description": "حساب فعال است",
    "deposit_comment": "",
    "bank_name": "بانک ملی ایران",
    "bank_id": "2",
    "deposit_owners": [
        {
            "firstName": "",
            "lastName": "الکام توسعه آماد"
        }
    ],
    "error_description": "بدون خطا"
}

4. IBAN Inquiry

Used to retrieve the IBAN details.

Sample Code

import requests

url = "https://inquisitor.toman.ir/api/v1/iban_inquiry/"

payload = json.dumps({
    "iban": "IR4432795460000007634516001"
})
headers = {
    'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

curl --location 'https://inquisitor.toman.ir/api/v1/iban_inquiry/' \
--header 'Content-Type: application/json' \
--data '{
    "iban": "IR4432795460000007634516001"
}'

Scope

inquiry.iban_inquiry.read

Request Body

{ "iban": "IR4432795460000007634516001" }

Response Body

The response body contains the account number, IBAN, bank ID, bank name, account owners, account status, and any errors.

Response Data Example

{
    "iban": "IR4432795460000007634516001",
    "deposit": "732456732147",
    "deposit_description": "حساب فعال است",
    "deposit_comment": "",
    "bank_name": "بانک ملی ایران",
    "bank_id": "2",
    "deposit_owners": [
        {
            "firstName": "",
            "lastName": "الکام توسعه آماد"
        }
    ],
    "error_description": "بدون خطا"
}

5. Wage Estimation

Used to retrieve the possibility of transferring via PAYA, SATNA, and A2A, along with the wage amount and transfer time, based on the given source and destination bank IDs and transfer amount.

Sample Code

import requests

url = "https://inquisitor.toman.ir/api/v1/wage-estimation/"

payload = json.dumps({
    "amount" : 700000000,
    "source_bank_id": 1,
    "destination_bank_id": 2
})
headers = {
    'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

curl --location 'https://inquisitor.toman.ir/api/v1/wage-estimation/' \
--header 'Content-Type: application/json' \
--data '{
    "amount" : 700000000,
    "source_bank_id": 1,
    "destination_bank_id": 2
}'

Scope

inquiry.wage_estimation.read

Request Body

{ "amount" : 700000000, "source_bank_id": 1, "destination_bank_id": 2 }

Response Body

The response body contains the possibility to transfer using PAYA, SATNA, and A2A, along with the wage amount and transfer time.

Response Data Example

{
    "paya": {
        "active": true,
        "wage": 30000,
        "estimated_time": "1403-07-02T18:45:00"
    },
    "satna": {
        "active": true,
        "wage": 140000,
        "estimated_time": "1403-07-03T07:00:00"
    },
    "a2a": {
        "active": false,
        "wage": 0,
        "estimated_time": null
    }
}