Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save OrhanYigitDurmaz/e1e23f472bf96276d3c89b490b38e90b to your computer and use it in GitHub Desktop.

Select an option

Save OrhanYigitDurmaz/e1e23f472bf96276d3c89b490b38e90b to your computer and use it in GitHub Desktop.

Turkish eArşiv Portal API Documentation

This is the complete documentation for the Turkish Revenue Administration's eArşiv (e-Archive) Portal API that handles electronic invoice management for Turkish tax compliance.

Base Information

API Endpoints

  • Production: https://earsivportal.efatura.gov.tr
  • Test Environment: https://earsivportaltest.efatura.gov.tr

Core Paths

  • Authentication: /earsiv-services/assos-login
  • API Dispatch: /earsiv-services/dispatch
  • Download Service: /earsiv-services/download
  • Referrer Path: /intragiris.html

Authentication Flow

All API calls require a session token obtained through authentication.

Authentication API

1. Get Test Credentials

Endpoint: POST /earsiv-services/assos-login Purpose: Retrieve test credentials for development environment

Request Parameters:

assoscmd: "kullaniciOner"
rtype: "json"

Response Format:

{
  "userid": "test_username",
  "sifre": "test_password"
}

2. Login (Get Token)

Endpoint: POST /earsiv-services/assos-login Purpose: Authenticate and receive session token

Request Parameters:

assoscmd: "login" (test) | "anologin" (production)
rtype: "json"
userid: "username"
sifre: "password"
sifre2: "password"
parola: "1"

Response Format:

{
  "token": "session_token_string",
  "userid": "username"
}

Error Response:

{
  "error": "Authentication failed",
  "messages": ["Invalid credentials"]
}

3. Logout

Endpoint: POST /earsiv-services/assos-login Purpose: Invalidate session token

Request Parameters:

assoscmd: "logout"
rtype: "json"
token: "session_token"

Response Format:

{
  "data": "Logout successful"
}

Dispatch API Operations

All business operations use the dispatch endpoint with specific command structures.

Base Request Structure

POST /earsiv-services/dispatch

Parameters:
cmd: "COMMAND_NAME"
callid: "uuid_v1"
pageName: "PAGE_CONTEXT"
token: "session_token"
jp: "json_payload_string"

🚨 CRITICAL: JP Parameter Quote Wrapping and Escaping

EXTREMELY IMPORTANT: The jp parameter value is wrapped in DOUBLE QUOTES and contains ESCAPED JSON inside. This is THE MOST CRITICAL aspect of the API.

ACTUAL Real Format in HTTP Request:

jp="{\"faturaUuid\":\"ef7f1b70-eb03-41b4-89f2-7aaad5d7ee04\",\"belgeNumarasi\":\"\",\"faturaTarihi\":\"31/05/2025\",\"saat\":\"23:07:19\",\"paraBirimi\":\"TRY\",\"vknTckn\":\"11111111111\",\"aliciAdi\":\"John\",\"aliciSoyadi\":\"Doe\",...}"

Structure Breakdown:

  • Parameter name: jp
  • Equals sign: =
  • Opening quote: "
  • Escaped JSON content: {\"field\":\"value\",...}
  • Closing quote: "

What This Means:

  • The entire jp value is wrapped in double quotes as a string parameter
  • Inside those quotes, the JSON has escaped quotes (\")
  • The structure is: jp="[ESCAPED_JSON_HERE]"
  • HTTP form encoding automatically handles the quote wrapping
  • All inner quotes become \" in the final HTTP request

PHP Library Implementation (Automatic Handling):

  1. Dynamic JSON Encoding (most operations):
"jp" => "" . json_encode($data) . ""
// HTTP client sends: jp="{\"field\":\"value\",\"field2\":\"value2\"}"
  1. Hardcoded JSON Strings (simple queries):
'jp' => '{"baslangic":"' . $startDate . '","bitis":"' . $endDate . '"}'
// HTTP client sends: jp="{\"baslangic\":\"01/01/2024\",\"bitis\":\"31/01/2024\"}"
  1. Empty JSON Object (info requests):
"jp" => "{}"
// HTTP client sends: jp="{}"

Python Implementation Examples:

  1. Using requests library:
import requests
import json

data = {
    "faturaTarihi": "15/03/2024",
    "vknTckn": "12345678901",
    "aliciUnvan": "Company Name"
}

params = {
    "cmd": "EARSIV_PORTAL_FATURA_OLUSTUR",
    "callid": "uuid-here",
    "pageName": "RG_BASITFATURA",
    "token": "session_token",
    "jp": json.dumps(data)  # This creates the JSON string
}

# requests automatically wraps form values in quotes
response = requests.post(base_url + "/earsiv-services/dispatch", data=params)
# Sends: jp="{\"faturaTarihi\":\"15/03/2024\",\"vknTckn\":\"12345678901\",...}"
  1. Manual parameter construction:
import json
import urllib.parse

data = {"faturaTarihi": "15/03/2024", "vknTckn": "12345678901"}
jp_value = json.dumps(data)  # Creates: {"faturaTarihi":"15/03/2024",...}

# Manual form encoding (for understanding)
form_data = f"jp={urllib.parse.quote(jp_value)}"
# Results in: jp=%7B%22faturaTarihi%22%3A%2215%2F03%2F2024%22...
  1. Using urllib:
import urllib.request
import urllib.parse
import json

data = {"faturaTarihi": "15/03/2024"}
params = {
    "cmd": "EARSIV_PORTAL_FATURA_OLUSTUR",
    "jp": json.dumps(data)
}

# urllib automatically handles quote wrapping
encoded_data = urllib.parse.urlencode(params).encode('utf-8')
# Sends: jp="{\"faturaTarihi\":\"15/03/2024\"}"

CRITICAL Understanding:

  • The json.dumps() creates the JSON string
  • HTTP clients automatically wrap form parameter values in quotes
  • You NEVER manually add quotes around the JSON string
  • The quote wrapping happens automatically during HTTP form encoding
  • Failure to understand this will cause ALL API calls to fail

Required Headers

accept: "*/*"
accept-language: "tr,en-US;q=0.9,en;q=0.8"
cache-control: "no-cache"
content-type: "application/x-www-form-urlencoded;charset=UTF-8"
pragma: "no-cache"
sec-fetch-mode: "cors"
sec-fetch-site: "same-origin"
referrer: "https://domain/intragiris.html"
User-Agent: "Mozilla/5.0 (compatible browser string)"

Invoice Management Operations

1. Create Invoice

Command: EARSIV_PORTAL_FATURA_OLUSTUR Page: RG_BASITFATURA

JSON Payload Structure:

{
  "belgeNumarasi": "",
  "faturaTarihi": "DD/MM/YYYY",
  "saat": "HH:MM:SS",
  "paraBirimi": "TRY",
  "dovzTLkur": "0",
  "faturaTipi": "SATIS",
  "hangiTip": "5000/30000",
  "vknTckn": "tax_id_or_identity_number",
  "aliciUnvan": "company_name",
  "aliciAdi": "first_name",
  "aliciSoyadi": "last_name",
  "binaAdi": "building_name",
  "binaNo": "building_number",
  "kapiNo": "door_number",
  "kasabaKoy": "town_village",
  "vergiDairesi": "tax_office",
  "ulke": "Türkiye",
  "bulvarcaddesokak": "street_address",
  "mahalleSemtIlce": "district",
  "sehir": "city",
  "postaKodu": "postal_code",
  "tel": "phone_number",
  "fax": "fax_number",
  "eposta": "email",
  "websitesi": "website",
  "iadeTable": [],
  "ozelMatrahTutari": "0",
  "ozelMatrahOrani": 0,
  "ozelMatrahVergiTutari": "0",
  "vergiCesidi": " ",
  "malHizmetTable": [
    {
      "malHizmet": "product_service_description",
      "miktar": 1,
      "birim": "ADET",
      "birimFiyat": "unit_price",
      "fiyat": "line_total_before_discount",
      "iskontoOrani": 0,
      "iskontoTutari": "0",
      "iskontoNedeni": "",
      "malHizmetTutari": "line_total_after_discount",
      "kdvOrani": 18,
      "vergiOrani": 0,
      "kdvTutari": "vat_amount",
      "vergininKdvTutari": "0",
      "ozelMatrahTutari": "0"
    }
  ],
  "tip": "İskonto",
  "matrah": 100.00,
  "malhizmetToplamTutari": 100.00,
  "toplamIskonto": "0",
  "hesaplanankdv": 18.00,
  "vergilerToplami": 18.00,
  "vergilerDahilToplamTutar": 118.00,
  "odenecekTutar": 118.00,
  "not": "notes",
  "siparisNumarasi": "order_number",
  "siparisTarihi": "order_date",
  "irsaliyeNumarasi": "waybill_number",
  "irsaliyeTarihi": "waybill_date",
  "fisNo": "receipt_number",
  "fisTarihi": "receipt_date",
  "fisSaati": " ",
  "fisTipi": " ",
  "zRaporNo": "z_report_number",
  "okcSeriNo": "fiscal_printer_serial"
}

🚨 CRITICAL JP ENCODING: This JSON structure must be converted to an ESCAPED JSON string for the jp parameter:

Actual HTTP Request Body:

jp="{\"belgeNumarasi\":\"\",\"faturaTarihi\":\"15/03/2024\",\"saat\":\"14:30:00\",\"paraBirimi\":\"TRY\",\"vknTckn\":\"12345678901\",\"aliciUnvan\":\"Company Name\",\"malHizmetTable\":[{\"malHizmet\":\"Service\",\"miktar\":1,\"birim\":\"ADET\",\"birimFiyat\":\"1000\",\"fiyat\":\"1000\",\"malHizmetTutari\":\"1000\",\"kdvOrani\":18,\"kdvTutari\":\"180\"}],\"matrah\":1000,\"hesaplanankdv\":180,\"odenecekTutar\":1180}"

PHP Implementation (automatic quote wrapping):

$parameters = [
    "cmd" => "EARSIV_PORTAL_FATURA_OLUSTUR",
    "callid" => Uuid::uuid1()->toString(),
    "pageName" => "RG_BASITFATURA", 
    "token" => $this->token,
    "jp" => "" . json_encode($invoiceData) . ""
    // HTTP client automatically wraps this in quotes: jp="JSON_STRING_HERE"
];

Python Implementation:

import requests
import json

invoice_data = {
    "belgeNumarasi": "",
    "faturaTarihi": "15/03/2024",
    "saat": "14:30:00",
    "paraBirimi": "TRY",
    "vknTckn": "12345678901",
    "aliciUnvan": "Company Name",
    "malHizmetTable": [{
        "malHizmet": "Service",
        "miktar": 1,
        "birim": "ADET",
        "birimFiyat": "1000",
        "fiyat": "1000",
        "malHizmetTutari": "1000",
        "kdvOrani": 18,
        "kdvTutari": "180"
    }],
    "matrah": 1000,
    "hesaplanankdv": 180,
    "odenecekTutar": 1180
}

params = {
    "cmd": "EARSIV_PORTAL_FATURA_OLUSTUR",
    "callid": "uuid-here",
    "pageName": "RG_BASITFATURA",
    "token": "session_token",
    "jp": json.dumps(invoice_data)  # Creates JSON string, requests wraps in quotes
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Key Point: The entire jp value gets wrapped in quotes automatically by HTTP form encoding!

Success Response:

{
  "data": "Faturanız başarıyla oluşturulmuştur. Düzenlenen Belgeler menüsünden faturanıza ulaşabilirsiniz.",
  "messages": [],
  "status": "success"
}

Error Response:

{
  "error": "Validation error message",
  "messages": [
    "Detailed error description"
  ],
  "status": "error"
}

2. Get Invoices (Drafts)

Command: EARSIV_PORTAL_TASLAKLARI_GETIR Page: RG_BASITTASLAKLAR

JSON Payload:

{
  "baslangic": "DD/MM/YYYY",
  "bitis": "DD/MM/YYYY",
  "hangiTip": "5000/30000",
  "table": []
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"baslangic\":\"01/01/2024\",\"bitis\":\"31/01/2024\",\"hangiTip\":\"5000/30000\",\"table\":[]}"

PHP Implementation (hardcoded string that gets auto-wrapped):

"jp" => '{"baslangic":"' . $startDate . '","bitis":"' . $endDate . '","hangiTip":"5000/30000", "table":[]}'
// The HTTP client automatically wraps this in quotes: jp="JSON_STRING_HERE"

Python Implementation:

import requests

start_date = "01/01/2024"
end_date = "31/01/2024"

# Method 1: Using string formatting (like PHP)
jp_value = f'{{"baslangic":"{start_date}","bitis":"{end_date}","hangiTip":"5000/30000","table":[]}}'

# Method 2: Using json.dumps (recommended)
import json
data = {
    "baslangic": start_date,
    "bitis": end_date,
    "hangiTip": "5000/30000",
    "table": []
}
jp_value = json.dumps(data)

params = {
    "cmd": "EARSIV_PORTAL_TASLAKLARI_GETIR",
    "callid": "uuid-here",
    "pageName": "RG_BASITTASLAKLAR",
    "token": "session_token",
    "jp": jp_value  # requests automatically wraps in quotes
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Critical: All JSON strings get wrapped in quotes automatically by HTTP form encoding!

Response Format:

{
  "data": [
    {
      "ettn": "invoice_uuid",
      "belgeNo": "document_number",
      "faturaTarihi": "DD/MM/YYYY",
      "saat": "HH:MM:SS",
      "taxid": "tax_id",
      "aliciVknTckn": "recipient_tax_id",
      "aliciUnvanAdSoyad": "recipient_name",
      "toplamTutar": "total_amount",
      "kdvTutari": "vat_amount",
      "onayDurumu": "approval_status",
      "ettnId": "ettn_id"
    }
  ],
  "messages": [],
  "status": "success"
}

3. Get Invoices Issued to Me

Command: EARSIV_PORTAL_ADIMA_KESILEN_BELGELERI_GETIR Page: RG_ALICI_TASLAKLAR

JSON Payload:

{
  "baslangic": "DD/MM/YYYY",
  "bitis": "DD/MM/YYYY"
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"baslangic\":\"01/01/2024\",\"bitis\":\"31/01/2024\"}"

PHP Implementation:

"jp" => '{"baslangic":"' . $startDate . '","bitis":"' . $endDate . ' " }'
// HTTP client wraps in quotes: jp="JSON_STRING_HERE"

Python Implementation:

import requests
import json

start_date = "01/01/2024"
end_date = "31/01/2024"

data = {
    "baslangic": start_date,
    "bitis": end_date
}

params = {
    "cmd": "EARSIV_PORTAL_ADIMA_KESILEN_BELGELERI_GETIR",
    "callid": "uuid-here",
    "pageName": "RG_ALICI_TASLAKLAR",
    "token": "session_token",
    "jp": json.dumps(data)
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format: Same as Get Invoices

4. Get Specific Invoice

Command: EARSIV_PORTAL_FATURA_GETIR Page: RG_BASITFATURA

JSON Payload:

{
  "ettn": "invoice_uuid"
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"ettn\":\"e8277cfa-4ac9-11ea-a5b5-acde48001122\"}"

PHP Implementation:

"jp" => "" . json_encode($data) . ""
// HTTP client wraps json_encode() result in quotes automatically

Python Implementation:

import requests
import json

data = {
    "ettn": "e8277cfa-4ac9-11ea-a5b5-acde48001122"
}

params = {
    "cmd": "EARSIV_PORTAL_FATURA_GETIR",
    "callid": "uuid-here",
    "pageName": "RG_BASITFATURA",
    "token": "session_token",
    "jp": json.dumps(data)
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": {
    "ettn": "invoice_uuid",
    "belgeNumarasi": "document_number",
    "faturaTarihi": "DD/MM/YYYY",
    "saat": "HH:MM:SS",
    "paraBirimi": "TRY",
    "vknTckn": "tax_id",
    "aliciUnvan": "recipient_company",
    "toplamTutar": "total_amount",
    "kdvTutari": "vat_amount",
    "onayDurumu": "approval_status",
    "malHizmetTable": [
      {
        "malHizmet": "service_description",
        "miktar": 1,
        "birim": "ADET",
        "birimFiyat": "unit_price",
        "malHizmetTutari": "line_total",
        "kdvOrani": 18,
        "kdvTutari": "vat_amount"
      }
    ]
  }
}

5. Show Invoice HTML

Command: EARSIV_PORTAL_FATURA_GOSTER Page: RG_TASLAKLAR

JSON Payload:

{
  "ettn": "invoice_uuid",
  "onayDurumu": "Onaylandı" | "Onaylanmadı"
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"ettn\":\"e8277cfa-4ac9-11ea-a5b5-acde48001122\",\"onayDurumu\":\"Onaylandı\"}"

PHP Implementation:

"jp" => "" . json_encode($data) . ""
// HTTP client wraps json_encode() result in quotes automatically

Python Implementation:

import requests
import json

data = {
    "ettn": "e8277cfa-4ac9-11ea-a5b5-acde48001122",
    "onayDurumu": "Onaylandı"  # or "Onaylanmadı"
}

params = {
    "cmd": "EARSIV_PORTAL_FATURA_GOSTER",
    "callid": "uuid-here",
    "pageName": "RG_TASLAKLAR",
    "token": "session_token",
    "jp": json.dumps(data)
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": "<html>complete_invoice_html_content</html>"
}

6. Cancel/Delete Invoice

Command: EARSIV_PORTAL_FATURA_SIL Page: RG_BASITTASLAKLAR

JSON Payload:

{
  "silinecekler": [
    {
      "ettn": "invoice_uuid",
      "belgeNo": "document_number",
      "faturaTarihi": "DD/MM/YYYY",
      "toplamTutar": "total_amount",
      "onayDurumu": "approval_status"
    }
  ],
  "aciklama": "cancellation_reason"
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"silinecekler\":[{\"ettn\":\"uuid\",\"belgeNo\":\"INV001\",\"faturaTarihi\":\"15/03/2024\",\"toplamTutar\":\"1180.00\",\"onayDurumu\":\"Onaylanmadı\"}],\"aciklama\":\"Yanlış İşlem\"}"

PHP Implementation:

"jp" => "" . json_encode($data) . ""
// HTTP client wraps complex nested JSON in quotes automatically

Python Implementation:

import requests
import json

data = {
    "silinecekler": [{
        "ettn": "uuid-here",
        "belgeNo": "INV001",
        "faturaTarihi": "15/03/2024",
        "toplamTutar": "1180.00",
        "onayDurumu": "Onaylanmadı"
    }],
    "aciklama": "Yanlış İşlem"
}

params = {
    "cmd": "EARSIV_PORTAL_FATURA_SIL",
    "callid": "uuid-here",
    "pageName": "RG_BASITTASLAKLAR",
    "token": "session_token",
    "jp": json.dumps(data)
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": "1 fatura başarıyla silindi."
}

Download Service

Get Download URL

Endpoint: GET /earsiv-services/download

Query Parameters:

token: "session_token"
ettn: "invoice_uuid"
belgeTip: "FATURA"
onayDurumu: "Onaylandı" | "Onaylanmadı"
cmd: "EARSIV_PORTAL_BELGE_INDIR"

Response: Binary PDF content or redirect to PDF

Example URL:

https://earsivportal.efatura.gov.tr/earsiv-services/download?token=abc123&ettn=uuid-here&belgeTip=FATURA&onayDurumu=Onaylandı&cmd=EARSIV_PORTAL_BELGE_INDIR

User Information Management

1. Get User Information

Command: EARSIV_PORTAL_KULLANICI_BILGILERI_GETIR Page: RG_KULLANICI

JSON Payload:

{}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{}"

PHP Implementation:

"jp" => "{}"
// HTTP client wraps empty JSON in quotes: jp="{}"

Python Implementation:

import requests
import json

params = {
    "cmd": "EARSIV_PORTAL_KULLANICI_BILGILERI_GETIR",
    "callid": "uuid-here",
    "pageName": "RG_KULLANICI",
    "token": "session_token",
    "jp": "{}"  # or json.dumps({})
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": {
    "vknTckn": "tax_identity_number",
    "unvan": "company_title",
    "adi": "first_name",
    "soyadi": "last_name",
    "vergiDairesi": "tax_office",
    "ulke": "country",
    "bulvarCaddeSokak": "street_address",
    "mahalleSemtIlce": "district",
    "sehir": "city",
    "postaKodu": "postal_code",
    "binaAdi": "building_name",
    "binaNo": "building_number",
    "apartmanNo": "apartment_number",
    "kapiNo": "door_number",
    "kasabaKoy": "town_village",
    "tel": "phone",
    "fax": "fax",
    "eposta": "email",
    "websitesi": "website"
  }
}

2. Update User Information

Command: EARSIV_PORTAL_KULLANICI_BILGILERI_KAYDET Page: RG_KULLANICI

JSON Payload: Same structure as Get User Information response data

Response Format:

{
  "data": "User information updated successfully"
}

Company Information Lookup

Get Company Information by Tax ID

Command: SICIL_VEYA_MERNISTEN_BILGILERI_GETIR Page: RG_BASITFATURA

JSON Payload:

{
  "vknTcknn": "tax_id_or_identity_number"
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"vknTcknn\":\"1234567890\"}"

PHP Implementation:

"jp" => '{"vknTcknn":"' . $taxNr . '"}'
// HTTP client wraps hardcoded JSON string in quotes automatically

Python Implementation:

import requests
import json

tax_nr = "1234567890"

# Method 1: String formatting
jp_value = f'{{"vknTcknn":"{tax_nr}"}}'

# Method 2: json.dumps (recommended)
data = {"vknTcknn": tax_nr}
jp_value = json.dumps(data)

params = {
    "cmd": "SICIL_VEYA_MERNISTEN_BILGILERI_GETIR",
    "callid": "uuid-here",
    "pageName": "RG_BASITFATURA",
    "token": "session_token",
    "jp": jp_value
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": {
    "unvan": "company_name",
    "vergiDairesi": "tax_office",
    "adres": "full_address",
    "durum": "status"
  }
}

SMS Verification System

1. Get Phone Number

Command: EARSIV_PORTAL_TELEFONNO_SORGULA Page: RG_BASITTASLAKLAR

JSON Payload:

{}

Response Format:

{
  "data": {
    "telefon": "phone_number"
  }
}

2. Send SMS Verification Code

Command: EARSIV_PORTAL_SMSSIFRE_GONDER Page: RG_SMSONAY

JSON Payload:

{
  "CEPTEL": "phone_number",
  "KCEPTEL": false,
  "TIP": ""
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"CEPTEL\":\"05551234567\",\"KCEPTEL\":false,\"TIP\":\"\"}"

PHP Implementation:

"jp" => "" . json_encode($data) . ""
// HTTP client wraps JSON with boolean and empty string values in quotes

Python Implementation:

import requests
import json

data = {
    "CEPTEL": "05551234567",
    "KCEPTEL": False,  # Python boolean becomes JSON false
    "TIP": ""
}

params = {
    "cmd": "EARSIV_PORTAL_SMSSIFRE_GONDER",
    "callid": "uuid-here",
    "pageName": "RG_SMSONAY",
    "token": "session_token",
    "jp": json.dumps(data)
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": {
    "oid": "operation_id",
    "mesaj": "SMS sent successfully"
  }
}

3. Verify SMS Code

Command: 0lhozfib5410mp Page: RG_SMSONAY

JSON Payload:

{
  "SIFRE": "sms_code",
  "OID": "operation_id",
  "OPR": 1,
  "DATA": [
    {
      "ettn": "invoice_uuid",
      "belgeNo": "document_number",
      "onayDurumu": "Onaylanmadı"
    }
  ]
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"SIFRE\":\"123456\",\"OID\":\"operation_id\",\"OPR\":1,\"DATA\":[{\"ettn\":\"uuid\",\"belgeNo\":\"INV001\",\"onayDurumu\":\"Onaylanmadı\"}]}"

PHP Implementation:

"jp" => "" . json_encode($data) . ""
// HTTP client wraps complex nested arrays with mixed data types in quotes

Python Implementation:

import requests
import json

data = {
    "SIFRE": "123456",
    "OID": "operation_id",
    "OPR": 1,
    "DATA": [{
        "ettn": "uuid-here",
        "belgeNo": "INV001",
        "onayDurumu": "Onaylanmadı"
    }]
}

params = {
    "cmd": "0lhozfib5410mp",
    "callid": "uuid-here",
    "pageName": "RG_SMSONAY",
    "token": "session_token",
    "jp": json.dumps(data)
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": {
    "sonuc": 1,
    "mesaj": "Verification successful"
  }
}

Menu System

Get Main Menu

Command: getUserMenu Page: MAINTREEMENU

JSON Payload:

{
  "ANONIM_LOGIN": "1"
}

🚨 CRITICAL JP ENCODING:

Actual HTTP Request Body:

jp="{\"ANONIM_LOGIN\":\"1\"}"

PHP Implementation:

"jp" => '{"ANONIM_LOGIN":"1"}'
// HTTP client wraps simple hardcoded JSON in quotes automatically

Python Implementation:

import requests
import json

# Method 1: Hardcoded string
jp_value = '{"ANONIM_LOGIN":"1"}'

# Method 2: json.dumps (recommended)
data = {"ANONIM_LOGIN": "1"}
jp_value = json.dumps(data)

params = {
    "cmd": "getUserMenu",
    "callid": "uuid-here",
    "pageName": "MAINTREEMENU",
    "token": "session_token",
    "jp": jp_value
}

response = requests.post(base_url + "/earsiv-services/dispatch", data=params)

Response Format:

{
  "data": [
    {
      "id": "menu_id",
      "text": "menu_text",
      "children": []
    }
  ]
}

Data Validation Rules

Date Formats

  • Invoice Date: DD/MM/YYYY (e.g., "08/02/2020")
  • Time: HH:MM:SS (e.g., "09:07:48")

Tax ID Validation

  • Individual (TC Kimlik): 11 digits
  • Company (VKN): 10 digits
  • Must be numeric string
  • Must pass Turkish checksum validation

Currency Codes

  • TRY: Turkish Lira (default)
  • USD: US Dollar
  • EUR: Euro
  • GBP: British Pound

Invoice Types

  • SATIS: Sales Invoice
  • IADE: Return Invoice

Unit Types

  • ADET: Piece/Item
  • DAY: Day
  • KGM: Kilogram
  • LTR: Liter
  • MTR: Meter
  • SAAT: Hour
  • AY: Month
  • YIL: Year

VAT Rates (Turkey)

  • 0%: Exempt items
  • 1%: Books, newspapers
  • 8%: Basic food items
  • 18%: Standard rate (most goods/services)

Status Values

  • Onaylandı: Approved
  • Onaylanmadı: Not approved/Pending
  • İptal: Cancelled
  • Reddedildi: Rejected

Mathematical Validation Requirements

Item Level Calculations

Line Price = Unit Price × Quantity
Discount Amount = Line Price × (Discount Rate / 100)
Line Total = Line Price - Discount Amount
VAT Amount = Line Total × (VAT Rate / 100)

Invoice Level Calculations

Subtotal = Sum of all Line Totals
Total VAT = Sum of all VAT Amounts
Total Discount = Sum of all Discount Amounts
Grand Total = Subtotal + Total VAT
Payment Amount = Grand Total

Error Response Patterns

Common Error Codes

  • Authentication Error: Invalid credentials
  • Token Expired: Session timeout
  • Validation Error: Data format issues
  • Business Rule Error: Invoice business logic violations
  • Network Error: Connection issues

Error Response Structure

{
  "error": "Error description",
  "messages": [
    "Detailed error message 1",
    "Detailed error message 2"
  ],
  "status": "error",
  "errorCode": "ERROR_CODE"
}

Rate Limiting and Performance

Request Frequency

  • Maximum 60 requests per minute per session
  • Recommended delay: 1 second between requests
  • Bulk operations should implement exponential backoff

Session Management

  • Tokens expire after 30 minutes of inactivity
  • Maximum 8 hours total session time
  • Concurrent sessions limited per user

Data Limits

  • Maximum 100 invoices per query
  • Date range maximum 1 year
  • Maximum 50 line items per invoice

Test Environment Specifics

Test Portal Access

  • URL: https://earsivportaltest.efatura.gov.tr/login.jsp
  • No real tax implications
  • Full API functionality available
  • Test credentials auto-generated

Differences from Production

  • Uses "login" instead of "anologin" for authentication
  • Test data is periodically reset
  • Performance may be slower
  • Some features may be limited

Security Considerations

Token Security

  • Tokens are session-specific and expire
  • Never expose tokens in URLs or logs
  • Implement proper token rotation

Data Encryption

  • All API calls must use HTTPS
  • Form data is URL-encoded
  • JSON payloads are string-encoded

Authentication Flow

  • Two-factor authentication via SMS
  • IP-based session tracking
  • Failed login attempt limiting

This documentation covers the complete Turkish eArşiv Portal API as used by the eFatura PHP library for electronic invoice management and tax compliance in Turkey.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment