Subtransactions returned from API appear not to follow Swagger definition

Hei,

I am trying to work with data returned from YNAB Transactions API using automatically generated model (using swagger-codegen) and it looks like that data returned from API doesn't matches Swagger definition.

It seems like that sometime we can get SubTransaction without transfer_account_id defined. At the same time transfer_account_id is defines as mandatory field in Swagger definition.

I have transactions that are split of manually entered transactions and here is JSON returned from Transaction API (amounts and UUID are replaced, I can provide them in case it can help):

{
    "account_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "account_name": "kortkonto",
    "amount": 860,
    "approved": true,
    "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "category_name": "Split (Multiple Categories)...",
    "cleared": "cleared",
    "date": "2019-08-09",
    "deleted": false,
    "flag_color": null,
    "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "import_id": null,
    "matched_transaction_id": null,
    "memo": "Lønn",
    "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "payee_name": "Lønn",
    "subtransactions": [
        {
            "amount": 000,
            "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "deleted": false,
            "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "memo": "Lønn",
            "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transaction_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transfer_account_id": null,
            "transfer_transaction_id": null
        },
        {
            "amount": -000,
            "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "deleted": false,
            "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "memo": "Lønn",
            "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transaction_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transfer_account_id": null,
            "transfer_transaction_id": null
        },
        {
            "amount": -000,
            "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "deleted": false,
            "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "memo": "Lønn",
            "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transaction_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transfer_account_id": null,
            "transfer_transaction_id": null
        },
        {
            "amount": -840,
            "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "deleted": false,
            "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "memo": "Lønn",
            "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transaction_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transfer_account_id": null,
            "transfer_transaction_id": null
        },
        {
            "amount": -700,
            "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "deleted": false,
            "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "memo": "Lønn",
            "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transaction_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transfer_account_id": null,
            "transfer_transaction_id": null
        },
        {
            "amount": -600,
            "category_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "deleted": false,
            "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "memo": "Lønn",
            "payee_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transaction_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
            "transfer_account_id": null,
            "transfer_transaction_id": null
        }
    ],
    "transfer_account_id": null,
    "transfer_transaction_id": null
}

Note that none of sub transactions has transfer_account_id defined, and transfer_account_id is defined as required field in Swagger description: https://api.youneedabudget.com/papi/spec-v1-swagger.json

Here is definition of SubTransaction:

    "SubTransaction": {
      "type": "object",
      "required": [
        "id",
        "transaction_id",
        "amount",
        "memo",
        "payee_id",
        "category_id",
        "transfer_account_id",
        "deleted"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "transaction_id": {
          "type": "string"
        },
        "amount": {
          "type": "integer",
          "format": "int64",
          "description": "The subtransaction amount in milliunits format"
        },
        "memo": {
          "type": "string"
        },
        "payee_id": {
          "type": "string",
          "format": "uuid"
        },
        "category_id": {
          "type": "string",
          "format": "uuid"
        },
        "transfer_account_id": {
          "type": "string",
          "format": "uuid",
          "description": "If a transfer, the account_id which the subtransaction transfers to"
        },
        "deleted": {
          "type": "boolean",
          "description": "Whether or not the subtransaction has been deleted.  Deleted subtransactions will only be included in delta requests."
        }
      }
    }

Is it correct, or am I missing smth? Should either Swagger or API be fixed?

Update:

The same seem to be the case for payee_id attribute on Subtransaction class as well.

It is possible to skip defining payee for split in YNABs web GUI, and than we get a data from Transactions API that doesn't follows Swagger spec, automatically generated models fail with an error.

5replies Oldest first
  • Oldest first
  • Newest first
  • Active threads
  • Popular
  • Yon Yonson - It sounds like because the field transfer_account_id is marked as "required" in the spec, you are expecting a non-null value.  Is that right?  "required" in OpenAPI 2.0 (Swagger) is a bit ambiguous in the spec and some generators interpret that to mean the field is always specified in the response (even if it has a null value) and others, interpret it to mean that it will have a non-null value.  We are intentionally marking these fields "required" but that is meant to communicate they will always be included in the response, even it they have null values.

    Are you getting an error in your generator when a null value is returned?   Which generator are you using?

    Reply Like
  • You may want to try using OpenAPI Generator (https://github.com/OpenAPITools/openapi-generator) instead, which supports both OpenAPI/Swagger specification 2.0 and 3.0.

     

    It supports `nullable` (OAS3) or `x-nullable` (OAS2) to indicate the required field is nullable.

     

    Disclosure: I'm the top contributor to both OpenAPI Generator and Swagger Codegen.

    Reply Like
    • William Cheng Thank you for the tip! However, I have already written a large part of code that depends on the models from swagger-codegen, so that would take too much time moving to another model.

      Reply Like
Like Follow
  • 2 mths agoLast active
  • 5Replies
  • 45Views
  • 3 Following