Skip to content

Type Mismatches in Adyen Terminal API OpenAPI Specification #72

@rebzden

Description

@rebzden

Describe the bug

The OpenAPI specification (TerminalAPI-v1.yaml) contains multiple type mismatches where fields are defined as integer but the actual API responses return string values. Additionally, several fields are incorrectly marked as required when they are actually optional in certain response contexts. These mismatches cause JSON deserialization failures when using generated client code.

To Reproduce

Steps to reproduce the behavior:

  1. Generate client code from the official TerminalAPI-v1.yaml OpenAPI specification
  2. Make a Payment request to an Adyen terminal
  3. Receive the PaymentResponse with fields like POIReconciliationID, CardCountryCode
  4. Attempt to deserialize the JSON response
  5. Observe type cast exceptions: type 'String' is not a subtype of type 'num?' in type cast

Alternative reproduction:

  1. Compare the official Adyen Terminal API Postman collection examples
  2. Check the data types in the example responses
  3. Compare against the OpenAPI specification
  4. Observe discrepancies in type definitions

Expected behavior

The OpenAPI specification should accurately reflect the actual API response types:

Type Mismatches Found

1. POIData.POIReconciliationID

  • Current specification: integer (lines 1570, 4739, 5336, 5362)
  • Actual API response: string (e.g., "1000")
  • Expected: Should be defined as type: string

2. CardData.CardCountryCode

  • Current specification: integer (line 1418)
  • Actual API response: string (e.g., "826" for GB)
  • Expected: Should be defined as type: string with minLength: 3 and maxLength: 3

3. SensitiveCardData fields

Multiple fields incorrectly defined as integer when they should be string:

  • PAN (line 1431): Should be string with minLength: 1, maxLength: 19
  • CardSeqNumb (line 1437): Should be string with minLength: 3, maxLength: 3
  • ExpiryDate (lines 1443, 1449): Should be string with minLength: 4, maxLength: 4

4. MobileData fields

Multiple fields incorrectly defined as integer when they should be string:

  • MSISDN (line 3759): Should be string with minLength: 1, maxLength: 25
  • IMSI (line 3765): Should be string with minLength: 1, maxLength: 25
  • IMEI (line 3771): Should be string with minLength: 1, maxLength: 25
  • MobileCountryCode (line 3777): Should be string with minLength: 3, maxLength: 3
  • MobileNetworkCode (line 3783): Should be string with minLength: 1, maxLength: 3
  • MaskedMSISDN (line 3789): Should be string with minLength: 1, maxLength: 25

5. Required fields in response schemas

Several response schemas incorrectly mark SaleData and POIData as required when they are actually optional in nested response contexts:

  • PaymentResponse (lines 5174-5177): SaleData and POIData should not be in the required array
  • CardAcquisitionResponse (lines 5214-5217): SaleData and POIData should not be in the required array
  • LoyaltyResponse (lines 5245-5248): SaleData and POIData should not be in the required array
  • StoredValueResponse (lines 5277-5280): SaleData and POIData should not be in the required array

Context: These fields are present in the initial payment response but are omitted when the same response structure is nested within a TransactionStatusResponseRepeatedMessageResponseRepeatedResponseMessageBody. Marking them as required causes deserialization to fail in these nested contexts.

Evidence

From Official Adyen Terminal API Postman Collection

The official Postman collection includes example responses that demonstrate these type mismatches:

  • POIReconciliationID: Shown as string values in Postman examples
  • CardCountryCode: ISO 3166-1 numeric country codes are transmitted as strings (e.g., "826")
  • Card number fields: PAN, ExpiryDate, etc., are string fields per PCI-DSS standards
  • Mobile identifiers: MSISDN, IMSI, IMEI are string fields per telecom standards

From Actual Terminal Responses

Decrypted terminal responses consistently show:

{
  "POIData": {
    "POIReconciliationID": "1000"  // String, not integer
  },
  "CardData": {
    "CardCountryCode": "826"  // String, not integer
  }
}

Environment

Impact

These type mismatches have significant impact:

  1. Client Code Generation: Generated clients fail at runtime with type cast exceptions
  2. Developer Experience: Developers must implement custom workarounds to handle type conversions
  3. Reliability: Applications crash when encountering these fields in API responses
  4. Maintenance: Custom workarounds must be maintained separately from generated code
  5. Receipt Printing: The incorrect required fields cause complete failure of receipt printing functionality when accessing transaction status

Proposed Solution

Update the OpenAPI specification to match actual API behavior:

  1. Change all identified fields from integer to string with appropriate constraints
  2. Remove SaleData and POIData from required arrays in response schemas
  3. Add validation patterns where applicable (e.g., ISO country codes, PAN format)
  4. Validate the specification against actual terminal responses
  5. Ensure Postman collection examples align with specification

Additional Context

  • These issues affect all programming languages using the OpenAPI specification for client generation
  • The type mismatches are consistent across different terminal models and environments (cloud/local)
  • Similar issues may exist in other parts of the specification that we haven't tested yet
  • The specification should follow industry standards (ISO 3166-1 for country codes, PCI-DSS for card data, ITU-T for mobile identifiers)

Files Referenced

  • TerminalAPI-v1.yaml: OpenAPI specification with type errors
  • Adyen Terminal API.postman_collection.json: Official Postman collection showing correct types
  • Actual terminal response logs: Consistently demonstrate string types for the fields listed above

Note: We have created a corrected version of the specification with all these fixes applied and successfully tested it with our Flutter/Dart application. The corrected specification eliminates all type cast exceptions and allows proper deserialization of all API responses.

Note2
This ticket has been generated using AI agent because comparison of the TerminalAPI-v1.yaml spec and Postman collection with examples was not really an option because of the size of the documents. Please have a closer look at the rest of the response types 🙏

terminal-api.yaml

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions