LinkToken with account filters - assets/investment/brokerage - not working - plaid

I am currently trying to retrieve the link token using a curl command in my terminal. I ultimately want to obtain the user's investment data in my app so I decided to use the assets product with account_filter of investment and subtype brokerage. However, this is not working.
Here is the request I am using (minus the IDs):
curl -X POST https://sandbox.plaid.com/link/token/create -H 'Content-Type: application/json' -d '{
"client_id": "...",
"secret": "...",
"user": { "client_user_id": "unique-per-user"
},
"client_name": "...",
"products": ["assets"],
"country_codes": ["US"],
"language": "en",
"redirect_uri": "...",
"account_filters": {
"investment": {
"account_subtypes": ["brokerage"]
}
}
}'
I then get the error:
{
"display_message": null,
"documentation_url": "https://plaid.com/docs/#create-link-token",
"error_code": "INVALID_FIELD",
"error_message": "account_filters must be nonempty Map\u003caccount type, Map\u003c\"account_subtypes\", Array\u003caccount subtype\u003e\u003e\u003e where account type and account subtype are strings. There must also be at least 1 valid product and account type combination.",
"error_type": "INVALID_REQUEST",
"request_id": "...",
"suggested_action": null
}%

UPDATE: I've confirmed with the Assets team that appears to be a bug / unintended behavior, they are looking into it.
I'm not entirely sure why, but it does seem like the Assets product does not support using account filters for anything other than depository accounts. Note that the Assets API is designed for lending use cases and gets a snapshot of a single point in time of a user's account balances and transactions. If you're looking to understand someone's investments, you in most cases probably want to use the Plaid Investments API, which allows you to view what a user is invested in, has automatic account filtering for investments accounts built in, and will keep you up-to-date with a user's current investments.

Related

What is the best way to accept multiple objects as input for a CLI?

Let's say I have a CLI which talks to a banking server to create a bank account. A bank account has a few properties, and a list of users associated with the account. If the bank account is represented as a json, it'll be
{
"accountType": "Savings",
"Balance": 500,
"Users": [
{
"firstName": "tony",
"lastName": "stark",
"nickName": "ironman"
},
{
"firstName": "Peter",
"lastName": "Parker",
"nickName": "spiderman"
}
]
}
I want to create this account object using a CLI, and I want to pass all the users at create time. Like
bank-cli account create --acount-type Savings --balance 500 <And the users>
How do I go about adding the users in the CLI? Adding the values like --firstName1 --lastName1 --firstName2 --lastName2 does not seem like a good UX. My current implementation is that this CLI opens up another editor, which accepts multiple lines of these parameters as
--firstName tony --lastName stark --nickname ironman
--firstName peter --lastName parker --nickname spiderman
And this is converted to an array of objects in the code. Is there a better way to do this?
I have considered accepting the parameters as json/toml or other formats. They didn't look too clean.

PUT vs POST when adding documents in elastic search

I am new to Elasticsearch and trying to add documents in elastic index. I have got confused between PUT and POST here as both are producing same results in below scenario:
curl -H "Content-Type: application/json" -XPUT "localhost:9200/products/mobiles/1?pretty" -d"
{
"name": "iPhone 7",
"camera": "12MP",
"storage": "256GB",
"display": "4.7inch",
"battery": "1,960mAh",
"reviews": ["Incredibly happy after having used it for one week", "Best iPhone so far", "Very expensive, stick to Android"]
}
"
vs
curl -H "Content-Type: application/json" -XPOST "localhost:9200/products/mobiles/1?pretty" -d"
{
"name": "iPhone 7",
"camera": "12MP",
"storage": "256GB",
"display": "4.7inch",
"battery": "1,960mAh",
"reviews": ["Incredibly happy after having used it for one week", "Best iPhone so far", "Very expensive, stick to Android"]
}
"
POST :used to achieve auto-generation of ids.
PUT :used when you want to specify an id.
see this
They both are among safe methods of HTTP.
usually we use POST to create a resource and PUT to modify that. besides if you're free to set-up the server side, you can use both of them because they both have similar properties like: they both have body, they are safe, data is not shown in URL, and ....
though it is better to consider standard rules that I said one of them before:
usually we use POST to create a resource and PUT to modify that. this way your code is more readable, changeable ...
for going deeper you can consider these tips according to put-versus-post:
Deciding between POST and PUT is easy: use PUT if and only if the endpoint will follow these 2 rules:
The endpoint must be idempotent: so safe to redo the request over and over again;
The URI must be the address to the resource being updated.
When we use PUT, we’re saying that we want the resource that we’re sending in our request to be stored at the given URI. We’re literally “putting” the resource at this address.
The only different between POST and PUT is that you cannot use PUT to create documents with auto ID generation.
The following query will create a document and auto generate an ID:
POST /products/_doc
{
"name": "Shoes",
"price": 100,
"in_stock": 64
}
Trying the same with PUT results to an "Incorrect HTTP method".
PUT /products/_doc
{
"name": "Shoes",
"price": 100,
"in_stock": 64
}
Unless I didn't experiment hard enough, this is the only difference between POST and PUT when creating documents.
Other than this, POST and PUT will get you to achieve the same things.

Is pagination for Youtube API Channel Memberships (sponsors.list) broken?

I'm trying to paginate through a list of results using the youtube API for Channel Memberships (sponsors.list), but the paging and PageTokens don't seem to be working as they are supposed to.
I'm currently developing an application for a user to generate a list of all Members to their channel (using the api for sponsors.list: https://developers.google.com/youtube/v3/live/docs/sponsors/list)
I have a test account, and I've been able to successfully pull the list. However, the test account only has 5 memberships. Since the API can only pull a maximum of 50 results per page, I want to make sure that my app can account for the possibility that the channel will have 50+ sponsors.
So, I've set the results per page to give me just 1, theoretically giving me 5 pages I can then sift through to simulate 50+ members.
The problem arises when I try to page through the results... as the API says, I grab the nextPageToken from the results, and pass it in the next call in the pageToken parameter. However, when I do so, even when testing in the API explorer, I get back an empty list, and no nextPageToken for the next page.
{
"kind": "youtube#sponsorListResponse",
"etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/UCSC321uKOiUT6GNkcPmkqoH1sY\"",
"pageInfo": {
"totalResults": 0,
"resultsPerPage": 0
},
"items": []
}
Additionally, if I pass a fake pageToken, the results come as if I'd passed no token at all, so it is at least recognizing the nextPageToken I'm passing it.
My google searches have failed me, other than just turning up pages talking about how the pagination is supposed to work... which it obviously isn't. Am I doing something wrong? Or is it indeed broken?
Edit
Here are the API calls I made.
Initial member list pull (After getting the authorization token, etc).
'https://www.googleapis.com/youtube/v3/sponsors?part=snippet&filter=all&maxResults=1' \
--header 'Authorization: Bearer [SECRET_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
Which results in: (I've edited out sensitive info, like [CHANNEL_ID], etc).
{
"kind": "youtube#sponsorListResponse",
"etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/PRgb6wjx--gdhgTtZ1auDKOony0\"",
"nextPageToken": "GLiawvDS6uEC",
"pageInfo": {
"totalResults": 5,
"resultsPerPage": 1
},
"items": [
{
"kind": "youtube#sponsor",
"etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/LoD6jhrr94l_4soca-7lx14kyRQ\"",
"snippet": {
"channelId": "[CHANNEL_ID]",
"sponsorDetails": {
"channelId": "[CHANNEL_ID]",
"channelUrl": "[CHANNEL_URL]",
"displayName": "[DISPLAY_NAME]",
"profileImageUrl": "[PROFILE_IMAGE_URL]"
},
"sponsorSince": "2019-04-25T06:36:11.677Z"
}
}
]
}
So I grab the nextPageToken "GLiawvDS6uEC", and drop that into my next call in the pageToken field, as the API instructs.
'https://www.googleapis.com/youtube/v3/sponsors?part=snippet&filter=all&maxResults=1&pageToken=GLiawvDS6uEC' \
--header 'Authorization: Bearer [SECRET_ACCESS_TOKEN]' \
--header 'Accept: application/json' \
And wind up with this depressing result:
{
"kind": "youtube#sponsorListResponse",
"etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/UCSC321uKOiUT6GNkcPmkqoH1sY\"",
"pageInfo": {
"totalResults": 0,
"resultsPerPage": 0
},
"items": []
}
So, turns out this was an actual problem with the API. Had a friend who knew someone at google, they looked into it, got the problem fixed! It works as intended now! Yay!
That said, if I hadn't had that connection, who knows if this would ever have been solved ;_;
As far as I can see, a nextPageToken of value GLiawvDS6uEC is invalid.
All the page tokens I came across were of a pattern described e.g. by Youtube Data API v3 pageToken for arbitrary page.
The API's documentation itself says nothing about how a page token should look like!
Maybe someone else has better inside on this issue. In any case, I suggest to file a report with Google.

Last Login Date to Application

I am looking for an API to find the user's last login date to a particular application. Not sure if it exists, please let me know your thoughts on getting this information through API calls.
You can get the last date the user was authenticated to any application on the User profile:
GET https://dev-12345.oktapreview.com/api/v1/users/xyz
{
"id": "xyz",
"status": "ACTIVE",
"created": "2017-02-22T02:33:02.000Z",
"activated": null,
"statusChanged": "2017-02-22T17:50:43.000Z",
"lastLogin": "2017-09-28T16:19:57.000Z",
"lastUpdated": "2017-08-08T20:11:46.000Z",
"passwordChanged": "2017-02-22T17:50:43.000Z",
"profile": {
"lastName": "Barbettini",
"firstName": "Nathanael",
// ...
}
The lastLogin field contains the timestamp of the last time the user logged in.
This isn't tracked on a per-app basis, though. You can get the app-specific App User:
GET https://dev-12345.oktapreview.com/api/v1/apps/abc/users/
{
"created": "2017-09-22T00:54:49.000Z",
"lastUpdated": "2017-09-22T00:54:49.000Z",
"scope": "GROUP",
"status": "ACTIVE",
"statusChanged": "2017-09-22T00:54:49.000Z",
"passwordChanged": null,
"syncState": "DISABLED",
"profile": {
"zoneinfo": "America/Los_Angeles",
"region": null,
// ...
}
But it doesn't have lastLogin. One way you could solve this is by saving a timestamp in the App User profile in your application code.
You could use filters to specify which logs do you want from the system logs API endpoint, limit the answer to 1, set the response order to start from the most recent ones, and user filters again to filter for your user.
So, you need to filter the request using the following filters:
actor.alternateId: which identifies the user, in my case the pattern "username#" is enough
event_type: this one should be user.authentication.sso which means that the user SSO to an app (any of the ones available for that user)
outcome.result: success, which means that the user successfully SSO to the app
Example query would be something like this:
curl -X GET -H "Content-Type: application/json" -H "Authorization: SSWS super-secret-token-here" -H "Accept: application/json" "https://<your.domain.here.com>/api/v1/logs?until=2018-07-17T11%3A30%3A55.664541&limit=1&sortOrder=DESCENDING&filter=event_type+eq+%22user.authentication.sso%22+and+outcome.result+eq+%22SUCCESS%22+and+actor.alternateId+sw+%22<user name here>%40%22"
Remember to replace the token, the URL and the before testing this query.
Also, remember that this example is URL encoded, so this is why it looks so weird.

googleapis giving back bad request

Having implemented oauth2.0 and done a handshake using the scopes:
"https://www.googleapis.com/auth/userinfo.email ",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/admin.directory.user ",
"https://www.googleapis.com/auth/admin.directory.group ",
"https://www.googleapis.com/auth/admin.directory.orgunit ",
I get back a token
the request
$ curl -X GET https://www.googleapis.com/oauth2/v1/userinfo?access_token=<Token>
{
"id": "{id}",
"email": "{email}",
"verified_email": true,
"name": "{name}",
...
}
as it should.
however a requst to the admin.directory.user namespace does not succeed:
$ curl -X GET https://www.googleapis.com/admin/directory/v1/users?access_token=<Token>
{
"error": {
"errors": [
{
"domain": "global",
"reason": "badRequest",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request"
}
}
Any good ideas to why this is?
The request to admin.directory.users is constructed from https://developers.google.com/admin-sdk/directory/v1/reference/#Users
I had the same problem retrieving all users through https://www.googleapis.com/auth/admin.directory.user endpoint. According to the documentation, you could do that in a specific domain by passing the domain as a parameter or get all existing users by passing the customer=my_customer parameter as follows:
Retrieve all users in a domain doc: https://www.googleapis.com/auth/admin.directory.user?domain=example.com
or
Retrieve all account users doc: https://www.googleapis.com/auth/admin.directory.user?customer=my_customer
In google playground oauth2 also you can test the above stuff by selecting Admin SDK API directory_v1 and auth/admin.directory.user.readonly to authorize the respective scope, then call the above requests.
Note that, you may need to get access to google playground within your google admin dashboard under the security apps section.
You need to specify either the domain (to get fields from only one domain) or the customer (to return all domains for a customer account).
I filed a bug to make more clear that is required to provide one of the two parameters.
At the very least, you need to include the Content-Type header:
curl -X GET -H "Content-Type: application/json" https://www.googleapis.com/admin/directory/v1/users?customer=my_customer&access_token=<Token>
For a full script that implements this API with CURL and BASH see this answer.
Note that the documentation is currently incorrect because it lists customer as an optional parameter when it is in fact required.

Resources