Autoridade Tributária Flow

This document describes how a client makes requests to the bizAPIs system when Two-Factor Authentication (2FA) is required for Autoridade Tributária.

Overview

2FA Request Flow

Phase 1: Initial Request with Credentials

Step 1: Client Sends Initial Request

The client makes a POST request to the orchestrator endpoint with credentials:

Endpoint: POST /v2/documents/{service}

Request Body:

{
  "user": "username",
  "password": "password"
}

Step 2: OTP Required Detection

After submitting credentials, the system checks if 2FA is required.

If OTP is not required, the flow skips directly to Phase 4 (Data Extraction and Response).

Phase 2: OTP Required Response

Step 3: Generate Second Request Token

When OTP is required, the service generates a second request token

Step 4: Return OTP Required Response

Response to Client:

{
  "otpResponse": {
    "secondRequestTokenId": "unique-token-uuid",
    "otpStatus": "OTP_REQUIRED",
    "requestId": "original-request-id"
  }
}

Phase 3: OTP Submission

Step 5: Client Sends OTP Code

The client makes a second request with the OTP code:

Endpoint: POST /v2/documents/{service}

Request Body:

{
  "otp": "123456",
  "secondRequestTokenId": "unique-token-uuid"
}

Key Points:

  • The secondRequestTokenId from the previous response is required
  • No credentials are needed in this request
  • The OTP code is provided by the user (received via SMS)

Step 6: Submit OTP to Portal

The service submits the OTP

Step 7: Verify Authentication

After OTP submission, the system verifies authentication

Phase 4: Data Extraction and Response

Step 8: Extract Data After Authentication

Once authenticated, the service proceeds with data extraction

Step 9: Return Final Response

The service returns the extracted data to the client

Success Response:

{
  "data": {
    "..."
  }
}

Error Response:

{
  "message": "..."
}

Error Handling

OTP Attempt Validation

The system checks OTP attempts remaining

{
  "message": "Can't authenticate - number of OTP attempts is about to be exceeded. Authenticate manually"
}

Session Expiration

Sessions can expire if:

  • The client takes too long to submit OTP (TTL default: 300 seconds)
  • The browser session is terminated
  • The service instance restarts

Error Response:

{
  "message": "Session expired or not found"
}

Invalid OTP

If an invalid OTP is submitted, the authentication framework detects it during verification and returns:

{
  "message": "Failed to login - Invalid Credentials"
}

Mock Requests for Testing

The system includes a Demo Mode that allows testing the 2FA flow without actual portal authentication. This is useful for:

  • Integration testing
  • Client application development
  • Simulating various error scenarios
  • Understanding the complete request/response flow

Request Structure

All requests (both demo and production) use the same structure:

Special Password Values for Demo Mode

1. Successful Authentication (No OTP)

Password: Any value not matching special keywords (e.g., "success", "test123")

Request:

{
  "user": "test-user",
  "password": "success"
}

Response:

{
  "data": {
    "atInteracoesList": [
      {
        "tax": "IUC",
        "description": "Entrega da declaração",
        "date": "2025-10-13"
      }
    ],
    "atPiList": [
      {
        "title": "IUC",
        "status": "verde"
      }
    ],
    "atAlertsList": [
      {
        "descriptionName": "IRC",
        "description": "Data limite para entrega da declaração Modelo 25 de IRC relativo a 2025",
        "limitDate": "2025-10-13"
      }
    ],
    "requestId": "generated-uuid"
  }
}

2. OTP Required Scenario

Password: "otprequired" (case-insensitive)

Initial Request:

{
  "user": "test-user",
  "password": "otprequired"
}

Initial Response:

{
  "otpResponse": {
    "requestId": "generated-uuid",
    "secondRequestTokenId": "e67fe840-e6e5-4c98-a37e-1a79bca43035",
    "otpStatus": "OTP_REQUIRED"
  }
}

Second Request (with OTP):

{
  "otp": "123456",
  "secondRequestTokenId": "e67fe840-e6e5-4c98-a37e-1a79bca43035"
}

Final Response:

{
  "data": {
    "atInteracoesList": [...],
    "atPiList": [...],
    "atAlertsList": [...],
    "requestId": "generated-uuid"
  }
}

3. Error Scenarios

Each error scenario is triggered by a specific password value:

3.1. Session Expired

Password: "sessionexpired"

Response:

{
  "message": "Session expired or not found"
}

3.2. Invalid Credentials

Password: "invalidcredentials"

Response:

{
  "message": "Failed to login - Invalid Credentials"
}

3.3. Problem During Authentication

Password: "problemduringauthentication"

Response:

{
  "message": "Failed to login - Problem during authentication"
}

3.4. OTP Error in Process

Password: "otperrorinprocess"

Response:

{
  "message": "Failed to submit OTP - Error in process"
}

3.5. OTP Exception in Process

Password: "otpexceptioninprocess"

Response:

{
  "message": "Failed to submit OTP - Exception occurred in process"
}

3.6. OTP Attempts Exceeded

Password: "numberofotpattemptsexceeded"

Response:

{
  "message": "Can't authenticate - number of OTP attempts is about to be exceeded. Authenticate manually"
}

3.7. Problem Reaching Authentication Page

Password: "reachauthentication"

Response:

{
  "message": "Failed to login - Problem reaching the authentication page."
}

3.8. Page Timeout

Password: "pagetimeout"

Response:

{
  "message": "Problem loading the page (timeout)"
}

3.9. Extract Data Error

Password: "extractdata"

Response:

{
  "message": "Failed to extract data"
}

3.10. Login Timeout

Password: "logintimeout"

Response:

{
  "message": "Failed to login - Website Timeout"
}

Complete 2FA Flow Example (Demo Mode)

Scenario: User authentication requiring OTP

Step 1: Initial Authentication Request

curl -X POST /v2/documents/{service} \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token" \
  -d '{
    "{ 
        "user": "test-user",
        "password": "otprequired"
      }"
    }

Step 1 Response:

{
  "otpResponse": {
    "requestId": "550e8400-e29b-41d4-a716-446655440000",
    "secondRequestTokenId": "e67fe840-e6e5-4c98-a37e-1a79bca43035",
    "otpStatus": "OTP_REQUIRED"
  }
}

Step 2: Submit OTP Code

curl -X POST /v2/documents/{service} \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-token" \
  -d '{
    "{ 
    "otp": "123456",
    "secondRequestTokenId": "e67fe840-e6e5-4c98-a37e-1a79bca43035"
    }"
  }

Step 2 Response:

{
  "data": {
    "atInteracoesList": [
      {
        "tax": "IUC",
        "description": "Entrega da declaração",
        "date": "2025-10-20"
      },
      {
        "tax": "IRS",
        "description": "Entrega da declaração",
        "date": "2025-10-25"
      }
    ],
    "atPiList": [
      {
        "title": "IUC",
        "status": "verde"
      },
      {
        "title": "IRS",
        "status": "amarelo"
      },
      {
        "title": "Patrimonio",
        "status": "verde"
      }
    ],
    "atAlertsList": [
      {
        "descriptionName": "IRC",
        "description": "Data limite para entrega da declaração Modelo 25 de IRC relativo a 2025",
        "limitDate": "2025-11-15"
      },
      {
        "descriptionName": "IVA",
        "description": "Data limite para entrega da declaração Modelo (texto exemplo)",
        "limitDate": "2025-10-30"
      }
    ],
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Testing Checklist

Use demo mode to test the following scenarios:

OTP required flow

  • Password: "otprequired"
  • Expected: OTP response → submit OTP → data returned
  • This helps simulate the 2FA response flow

Session expiration

  • Password: "sessionexpired"
  • Expected: Error message about expired session

Invalid credentials

  • Password: "invalidcredentials"
  • Expected: Error message about invalid credentials

OTP attempt limit

  • Password: "numberofotpattemptsexceeded"
  • Expected: Error message to authenticate manually

OTP submission errors

  • Password: "otperrorinprocess" or "otpexceptioninprocess"
  • Expected: Error message about OTP submission failure

Network/timeout errors

  • Password: "pagetimeout" or "logintimeout"
  • Expected: Error message about timeout

Data extraction failure

  • Password: "extractdata"
  • Expected: Error message about extraction failure

Successful authentication without OTP

  • Password: other value
  • Expected: Data returned immediately

Note: In demo mode, any OTP code will be accepted as long as the correct secondRequestTokenId is provided.


Security Considerations

  1. Token Security: secondRequestTokenId is a UUID, preventing guessing attacks
  2. Session Isolation: Each requestId has its own isolated session
  3. OTP Attempt Limiting: System checks remaining OTP attempts before submission
  4. Time-Based Expiration: Sessions expire after configured TTL
  5. Error Message Sanitization: Detailed errors are logged but generic messages returned to clients

2FA Error Messages Reference

This section lists all error messages that were added or modified as part of the 2FA feature implementation.

Authentication Errors

1. Session expired or not found

HTTP Status: 200 (returned in response body) Context: Occurs when attempting to submit OTP for a session that no longer exists Response Example:

{
  "message": "Session expired or not found"
}

Causes:

  • Client took longer than the TTL (default 300 seconds) to submit OTP
  • Invalid secondRequestTokenId provided

2. Failed to login - Problem during authentication

HTTP Status: 200 (returned in response body) Context: Generic authentication failure before OTP stage Response Example:

{
  "message": "Failed to login - Problem during authentication"
}

Causes:

  • Portal returned an error page after credential submission
  • Portal structure changed and elements could not be found
  • Unexpected exception during authentication process

3. Failed to login - Invalid Credentials

HTTP Status: 200 (returned in response body) Context: Portal explicitly indicated invalid username or password Response Example:

{
  "message": "Failed to login - Invalid Credentials"
}

Causes:

  • Incorrect username provided
  • Incorrect password provided
  • Invalid OTP code submitted

4. Can't authenticate - number of OTP attempts is about to be exceeded. Authenticate manually

HTTP Status: 200 (returned in response body) Context: Portal shows only 1 OTP attempt remaining Response Example:

{
  "message": "Can't authenticate - number of OTP attempts is about to be exceeded. Authenticate manually"
}

Causes:

  • Multiple invalid OTP codes have been submitted
  • Portal security measure to prevent brute force attacks
  • User has 1 OTP submission attempt remaining

Resolution:

  • User MUST authenticate manually through the portal website
  • System will not submit the final attempt to avoid account lockout
  • After manual authentication, the counter will reset

5. Failed to submit OTP - Error in process

HTTP Status: 200 (returned in response body) Context: Generic error during OTP submission process Response Example:

{
  "message": "Failed to submit OTP - Error in process"
}

Causes:

  • Portal returned unexpected response during OTP submission

6. Failed to submit OTP - Exception occurred in process

HTTP Status: 200 (returned in response body) Context: Unexpected exception during OTP submission Response Example:

{
  "message": "Failed to submit OTP - Exception occurred in process"
}

Causes:

  • Unhandled exception in OTP submission code