Artha API
    • Introduction
    • Authentication
    • KYC/KYB Requirements
    • API Setup Guide
    • Customers
      • Create Customer
        POST
      • List Customers
        GET
      • Get Customer
        GET
      • Update Customer
        PATCH
    • Cards
      • Submit KYC/KYB Applicant
        POST
      • Issue Card
        POST
      • Cards List
        GET
      • Get Card
        GET
      • Get Sensitive Card Details
        GET
    • Card Operations
      • Activate Card
        POST
      • Freeze Card
        POST
      • Unfreeze Card
        POST
      • Cancel Card
        POST
      • Replace Card
        POST
      • Set / Reset Card PIN
        POST
      • Get Card Limits
        GET
      • Update Card Limits
        POST
    • Funding
      • Top Up Card
        POST
      • Get Card Balance
        GET
      • List Top-Up History
        GET
    • Transactions
      • List All Transactions
        GET
      • List Card Transactions
        GET
      • List Customer Transactions
        GET
      • Get Transaction
        GET
    • Products
      • List Products
      • Get Product
    • Utilities
      • Upload Documents
    • Webhook's
      • Webhooks

    Authentication

    Overview#

    The Artha Cards External API uses HMAC-SHA256 request signing for authentication. Every request must include 5 headers that prove the client's identity, ensure request integrity, and prevent replay attacks.
    This is the same approach used by Stripe, Adyen, Razorpay, and other fintech providers.

    Credentials#

    When onboarded, each client receives:
    CredentialDescriptionExample
    API KeyPublic identifier sent with every requestak_live_8f3a9b2c1d4e5f6a
    SecretPrivate key used to compute HMAC signatures. Never sent over the wire.mJ8v3aQpT5y2rX6nK9cD4eH7sB1uF0gLzN2wV8tYqP=
    Important: The Secret is displayed only once at creation time. Store it securely (e.g., in a vault or environment variable). If lost, a new API key must be generated.

    Required Headers#

    Every request to /ext/api/v1/* must include these 5 headers:
    HeaderTypeDescription
    X-API-KeystringYour API key (e.g., ak_live_8f3a9b2c1d4e5f6a)
    X-TimestampstringCurrent UTC time as Unix epoch seconds (e.g., 1707753600)
    X-NoncestringA unique random string per request (e.g., UUID or random hex). Must not be reused within 5 minutes.
    X-Body-Hashstringbase64(SHA-256(request_body)). For requests with no body (GET, DELETE), hash an empty string.
    X-Signaturestringbase64(HMAC-SHA256(secret, string_to_sign))

    How to Compute the Signature#

    Step 1: Compute the Body Hash#

    body_hash = base64(SHA-256(request_body_bytes))
    Use the raw request body bytes (UTF-8 encoded)
    For GET/DELETE requests with no body, hash an empty byte array: base64(SHA-256(b""))
    The body hash for an empty body is always: 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=

    Step 2: Build the String to Sign#

    Concatenate 5 components separated by newline (\n):
    string_to_sign = "{METHOD}\n{PATH_AND_QUERY}\n{TIMESTAMP}\n{NONCE}\n{BODY_HASH}"
    ComponentDescriptionExample
    METHODHTTP method in uppercasePOST
    PATH_AND_QUERYFull path including query string/ext/api/v1/cards?limit=10
    TIMESTAMPSame value as X-Timestamp header1707753600
    NONCESame value as X-Nonce headera1b2c3d4e5f6
    BODY_HASHSame value as X-Body-Hash headerbase64(SHA-256(body))

    Step 3: Compute the HMAC Signature#

    signature = base64(HMAC-SHA256(secret_bytes, string_to_sign_bytes))
    secret_bytes: your Secret encoded as UTF-8 bytes
    string_to_sign_bytes: the string from Step 2 encoded as UTF-8 bytes

    Full Example#

    Request#

    POST /ext/api/v1/cards HTTP/1.1
    Host: api.arthapay.com
    Content-Type: application/json
    X-API-Key: ak_test_abc123def456
    X-Timestamp: 1707753600
    X-Nonce: f47ac10b-58cc-4372-a567
    X-Body-Hash: oWVxV2ghrGQFIMUEm0bRNNMCHTCnxNFKbqA3CMY9VVE=
    X-Signature: K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
    
    {"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "customer_id": "...", "currency": "USD"}

    Step-by-step Computation#

    1. Body Hash:
       body = '{"product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", ...}'
       X-Body-Hash = base64(SHA-256(body_bytes))
    
    2. String to Sign:
       "POST\n/ext/api/v1/cards\n1707753600\nf47ac10b-58cc-4372-a567\noWVxV2ghrGQFIMUEm0bRNNMCHTCnxNFKbqA3CMY9VVE="
    
    3. Signature:
       X-Signature = base64(HMAC-SHA256(secret, string_to_sign))

    Code Examples#

    C# (.NET)#

    Python#

    JavaScript / Node.js#

    cURL#


    Error Responses#

    When authentication fails, the API returns a 401 Unauthorized response:
    {
      "success": false,
      "error": {
        "code": "UNAUTHORIZED",
        "message": "Missing required authentication headers (X-API-Key, X-Timestamp, X-Nonce, X-Body-Hash, X-Signature)."
      }
    }

    Common Authentication Errors#

    Error MessageCauseFix
    Missing required authentication headersOne or more of the 5 headers is missingInclude all 5 headers
    Invalid API keyAPI key not found in databaseCheck your API key is correct
    API key is disabledKey was manually disabled or auto-lockedContact admin
    API key has expiredKey passed its ExpiresAt dateRequest a new API key
    API key is locked due to excessive failures50+ consecutive auth failuresContact admin to reset
    Request from unauthorized IP addressClient IP not in the AllowedIPs whitelistRequest IP whitelist update
    Request timestamp is outside the allowed windowX-Timestamp is more than 5 minutes from server timeSync your system clock (NTP)
    Replay detected (duplicate nonce)Same nonce reused within 5 minutesGenerate a new nonce per request
    Body hash mismatchX-Body-Hash doesn't match the actual request bodyRecompute SHA-256 of the exact body bytes sent
    Signature mismatchHMAC signature is incorrectVerify string-to-sign format and secret

    Security Properties#

    PropertyMechanism
    IdentityAPI Key identifies the client and tenant
    AuthenticationHMAC-SHA256 proves the client has the secret
    IntegrityBody hash ensures the request body wasn't tampered with
    Replay ProtectionTimestamp window (5 min) + unique nonce per request
    Timing Attack ProtectionConstant-time comparison for all hash/signature checks
    Auto-lockoutKey auto-disables after 50 consecutive auth failures
    IP RestrictionOptional IP whitelist per API key
    ExpirationOptional key expiration date
    ScopingPer-key permission scopes

    Rate Limits#

    Requests are rate-limited per API key
    Default: varies by endpoint
    HTTP 429 is returned when limits are exceeded
    Use X-RateLimit-Remaining and X-RateLimit-Reset response headers to manage your request rate

    Modified at 2026-02-18 17:21:48
    Previous
    Introduction
    Next
    KYC/KYB Requirements
    Built with