Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncertainty on when invoice.subscription is to be expanded. #61

Open
rdarder opened this issue Sep 1, 2020 · 12 comments
Open

Uncertainty on when invoice.subscription is to be expanded. #61

rdarder opened this issue Sep 1, 2020 · 12 comments
Assignees
Labels

Comments

@rdarder
Copy link

rdarder commented Sep 1, 2020

Hi there!
I'm wrapping my head around x-expandableFields and x-expansionResources. I thought I got this right but there's a case that confuses me.
Let's take invoice.subscription. it's not an expandableFIeld and it's still anyOf(str, ref(subscription)). So far, every time I get an invoice, I see the subscription automatically expanded. So my questions are:

  • can subscription in this case come un-expanded and just as a string?
  • is there any way of controlling this behavior?
    I notice that the field is hinted with an x-expansionResources, which if I understand correctly, hints that the id form of this field is a reference to the indicated (subscription) resource. I'm just unsure if I'm missing something here.

My intention is to reduce the type ambiguity of the return types, so consumers don't need to check whether -- in this case -- the subscription is an id or the actual object. I can deal with expandableFields most of the times, but this one seems off.

Thank you!!

@rdarder
Copy link
Author

rdarder commented Sep 1, 2020

Sorry, after re-reading the spec, I got this wrong, but I'm still confused.
invoice.subscription is expandable, but I get it expanded even when I set no headers for expanding that field. Do some endpoints choose to expand some fields by default? Is that annotated in the openapi spec somehow and/or is there a way of controlling it?

@remi-stripe
Copy link
Collaborator

@rdarder Would you be able to provide a bit more details about how you are testing this exactly? What do you use to fetch the Invoice that leads to you seeing the subscription property be an expanded Subscription object? For example when I try on my end with the latest stripe-mock I get subscription: null today. I only get a full object if I explicitly pass expand[]=subscription as a query param.

@rdarder
Copy link
Author

rdarder commented Sep 1, 2020

Hi Remi,
I think I reported the wrong example, I'm sorry for that. I've gone deeper with the Customer object and have similar scenarios that I'd like to clarify.
I'm getting customers via GET /v1/customers, no headers other than the api key.
The spec for customer says these fields are expandible:

  • "address",
  • "default_source",
  • "discount",
  • "invoice_settings",
  • "shipping",
  • "sources",
  • "subscriptions",
  • "tax_ids"

Here's a sample anonymized customer I get back as part of the response. Below are some questions regarding some specific patterns:

address: anyOf([address]), nullable: true, marked as expandable
comes as null, which makes sense. Should I expect that address is always null unless I expand it?

default_source: anyOf(str, ... polymorphic entities), is nullable, is expandable.
comes back as a string, which again makes sense. I should expect this to always come back as a string or null as long as I don't expand it, right?

invoice_settings. ref(invoice_settings_customer_setting), not nullable, marked as expandable.
comes as an object with its keys set, all to null (which matches the invoice_settings schema).
what's the semantic of expandable here?

sources: this is a "page-like" object of a polymorphic entity (payment sources). non nullable and expandable. Also within the object, the "data" attribute is also marked as expandable.
it comes back with all fields present (including data, which has entries in it.)

subscriptions: equivalent case to sources: I get back the whole thing without asking for expansion.

Could you help me figure out how expansion works in these scenarios?
Thank you!

@remi-stripe
Copy link
Collaborator

@rdarder I usually recommend referring more to our API Reference than the openapi for questions like this honestly but here's a detailed answer. In all the examples you gave, there are 4 separate and different situations:

  • address, invoice_settings and shipping are hashes. They don't point to another API resource and so they are not "expandable". They are just a hash and some of them can be null while others would just be empty.

  • default_source: this is the id of the default source. This can be null (if they have no card/bank_account/source) or a string by default such as card_123. If you expand it then you can either get null or the whole Card, BankAccount or Source API resource.

  • discount: This is an auto-expanded API resource, this means that it's either null or the whole Discount object when there's one.

  • sources, subscriptions and tax_ids: Those are includable sub-lists. This means that by default they are not even returned (so you just don't get it in the response, instead of getting subscriptions: null for example). This is true as of the latest API version 2020-08-27. Those sub-lists can be explicitly included in the response by using the expand feature too as documented here in which case you get the whole sub-lists with data as an array of object (which can be empty).

@rdarder
Copy link
Author

rdarder commented Sep 1, 2020

Thanks for the quick response! I opted to ask here since I'm trying to make sense of your openapi spec extensions rather than individual cases. In other words, I'm pursuing statically typing the resources I get back from stripe's API.
I just updated the API version to 2020-08-27, and still get the same exact customer json that I posted earlier. That response includes sources and subscriptions (with their data array populated) in it, and I didn't ask for expanding them explicitly. This is probably my main source of confusion.

@remi-stripe
Copy link
Collaborator

@rdarder How are you getting that raw JSON exactly? I just tried quickly on the default test account for our docs and as long as I force the latest API version explicitly in the call then sources is absent (and so are subscriptions and tax_ids).

Here's what I get:

curl https://api.stripe.com/v1/customers/cus_HwfwuUZoxYBjJp   -u sk_test_4eC39HqLyjWDarjtT1zdp7dc:   -H "Stripe-Version: 2020-08-27"
{
  "id": "cus_HwfwuUZoxYBjJp",
  "object": "customer",
  "address": null,
  "balance": 0,
  "created": 1599017108,
  "currency": "usd",
  "default_source": null,
  "delinquent": false,
  "description": null,
  "discount": null,
  "email": null,
  "invoice_prefix": "B530716",
  "invoice_settings": {
    "custom_fields": null,
    "default_payment_method": null,
    "footer": null
  },
  "livemode": false,
  "metadata": {
  },
  "name": null,
  "next_invoice_sequence": 1,
  "phone": null,
  "preferred_locales": [

  ],
  "shipping": null,
  "tax_exempt": "none"
}

@rdarder
Copy link
Author

rdarder commented Sep 2, 2020

I'm listing all customers through GET /v1/customers

@rdarder
Copy link
Author

rdarder commented Sep 2, 2020

Nevermind, I wasn't setting the right api version. If I use the 2020-08-27, I get exactly what you said. Thank you!

@rdarder
Copy link
Author

rdarder commented Sep 2, 2020

  • discount: This is an auto-expanded API resource, this means that it's either null or the whole Discount object when there's one.

Could you help me figure out if there's anything on your openapi spec that would help me determine that this is "auto-expanded"? Cause it's marked as an expandable field.

@remi-stripe
Copy link
Collaborator

Whether it is auto-expanded or not depends on whether it's optional and what is the shape described.

For discount for example the spec says that this is either null or an instance of Discount

discount:
  anyOf:
  - "$ref": "#/components/schemas/discount"
  description: Describes the current discount active on the customer, if there
    is one.
  nullable: true

and later discount appears in the list of required which confirms it's always returned.

On the other hand for sources and tax_ids for example you can see it's a list of objects, it's optional since it's not in required and it's includable because the properties appear in the x-expandableFields.

@rdarder
Copy link
Author

rdarder commented Sep 2, 2020

Thank you.
Unfortunately, either I'm misunderstanding or have the wrong spec file. I don't see discount as a required field for the customer schema. I find it, however, in the x-expandableFields.
image

@remi-stripe
Copy link
Collaborator

@rdarder Really sorry for the delays. I checked in internally on this ask and unfortunately there is no reliable way right now to know for sure if a property is automatically expanded or not in openapi. It's definitely something we'd like to improve upon in the future but it won't happen immediately.

cc @richardm-stripe who is looking into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants