{"id":15286191,"url":"https://github.com/billgerrard/bing-content-api","last_synced_at":"2025-03-23T21:22:07.945Z","repository":{"id":56839292,"uuid":"133686040","full_name":"billgerrard/bing-content-api","owner":"billgerrard","description":"Bing::ContentAPI -- Perl interface to Bing Ads Content API for Shopping","archived":false,"fork":false,"pushed_at":"2022-09-29T19:34:35.000Z","size":15,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-29T04:42:50.052Z","etag":null,"topics":["bing","bingads","content-api","hacktoberfest","perl","shopping"],"latest_commit_sha":null,"homepage":"https://metacpan.org/pod/Bing::ContentAPI","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/billgerrard.png","metadata":{"files":{"readme":"README.pod","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-16T15:21:56.000Z","updated_at":"2021-10-04T15:39:37.000Z","dependencies_parsed_at":"2022-08-28T23:30:45.347Z","dependency_job_id":null,"html_url":"https://github.com/billgerrard/bing-content-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fbing-content-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fbing-content-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fbing-content-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fbing-content-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/billgerrard","download_url":"https://codeload.github.com/billgerrard/bing-content-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245169924,"owners_count":20571980,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bing","bingads","content-api","hacktoberfest","perl","shopping"],"created_at":"2024-09-30T15:10:55.939Z","updated_at":"2025-03-23T21:22:07.913Z","avatar_url":"https://github.com/billgerrard.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"=head1 NAME\n\n  Bing::ContentAPI - Perl interface to the Bing Ads / Microsoft Advertising Content API\n\n=head1 DESCRIPTION\n\n  Add, modify and delete products from the Microsoft Advertising Merchant Center platform\n  via the Bing Ads / Microsoft Advertising Content API.\n\n  https://learn.microsoft.com/en-us/advertising/shopping-content/\n\n  Authentication is done via OAuth using Authorization Code Grant Flow\n\n  See https://learn.microsoft.com/en-us/advertising/guides/authentication-oauth and\n  https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow\n\n  Follow the steps to register an application with the Microsoft identity platform:\n  https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app\n\n  Set up a Redirect URI. Set up a Mobile/Desktop app redirect URI (not a Web application redirect).\n  https://learn.microsoft.com/en-us/azure/active-directory/develop/reply-url\n\n  A redirect URI of 'http://localhost/native-app' is used as an example in this documentation.\n\n  Steps to authorize a native application and generate an initial refresh token:\n\n  Note: Substitute CLIENT_ID, REDIRECT_URI and AUTHORIZATION_CODE with the\n  actual values in the appropriate locations in the examples.\n\n  1) Request user consent through web browser:\n  (using an existing Bing Ads / Microsoft Advertising account when prompted)\n\n  https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=CLIENT_ID\u0026redirect_uri=REDIRECT_URI\u0026response_type=code\u0026response_mode=query\u0026scope=offline_access%20https%3A%2F%2Fads.microsoft.com%2Fmsads.manage\n\n  Response received:\n  http://localhost/native-app?code=AUTHORIZATION_CODE\n\n  2) Use the authorization 'code' received to request the access token and refresh token.\n  Note: scope must include 'offline_access', as included in the example, to receive a refresh token.\n\n  $ curl \\\n    -d client_id=CLIENT_ID \\\n    -d code=AUTHORIZATION_CODE \\\n    -d grant_type=authorization_code \\\n    -d redirect_uri=REDIRECT_URI \\\n    -d scope=offline_access%20https%3A%2F%2Fads.microsoft.com%2Fmsads.manage \\\n    -H \"Content-Type: application/x-www-form-urlencoded\" \\\n    https://login.microsoftonline.com/common/oauth2/v2.0/token\n\n  Response:\n  {\n    \"token_type\": \"Bearer\",\n    \"scope\": \"https://ads.microsoft.com/msads.manage\",\n    \"expires_in\": 3600,\n    \"ext_expires_in\": 3600,\n    \"access_token\": \"...\",\n    \"refresh_token\": \"...\"\n  }\n\n  3) Use the received refresh_token as the initial refresh_token in Bing::ContentAPI-\u003enew()\n\n=head1 SYNOPSIS\n\n  use Bing::ContentAPI;\n  use Data::Dumper;\n\n  my $bing = Bing::ContentAPI-\u003enew({\n    debug =\u003e 0,\n    redirect_uri    =\u003e 'http://localhost/native-app',\n    merchant_id     =\u003e '12345',          # merchant_id is the Merchant Center store ID\n    developer_token =\u003e '123ABC456DEF789',\n    client_id       =\u003e '1234abcd-5679-efgh-123456789',\n    refresh_token   =\u003e load_token(),     # previously saved refresh token\n  });\n  save_token($bing-\u003e{refresh_token}); # save new refresh token\n\n  sub load_token {\n    my $token;\n    # load token from storage\n    return $token;\n  }\n\n  sub save_token {\n    my $token = shift;\n    # save token to storage\n  }\n\n  my ($request, $result, $products, $batch_id, $product_id);\n\n  # list products\n\n  my $nextPageToken = '';\n  do {\n    $request = {\n      resource =\u003e 'products',\n      method   =\u003e 'list',\n      params   =\u003e ['max-results' =\u003e 250],\n    };\n    push @{$request-\u003e{params}}, ('start-token', \"$nextPageToken\") if $nextPageToken ne '';\n\n    $result = $bing-\u003eget(%$request);\n    $nextPageToken = $result-\u003e{response}-\u003e{nextPageToken} || '';\n\n    print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n    print \"Products list: \\n\". Dumper $result;\n  } while ($nextPageToken ne '');\n\n  # list catalogs\n\n  $result = $bing-\u003eget(\n    resource =\u003e 'catalogs',\n    method   =\u003e 'list',\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Catalogs list: \\n\". Dumper $result;\n\n  # get status of product offers in a catalog\n\n  my $catalogID = 123456;\n  $result = $bing-\u003eget(\n    resource =\u003e 'catalogs',\n    method   =\u003e 'status',\n    id       =\u003e $catalogID,\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Catalog status: \\n\". Dumper $result;\n\n  # insert a product\n\n  $result = $bing-\u003epost(\n    resource =\u003e 'products',\n    method   =\u003e 'insert',\n    dryrun   =\u003e 1,\n    body =\u003e {\n      contentLanguage =\u003e 'en',\n      targetCountry =\u003e 'US',\n      channel =\u003e 'online',\n      offerId =\u003e '333333',\n      title =\u003e 'Item title',\n      description =\u003e 'The item description',\n      link =\u003e 'http://www.bing.com',\n      imageLink =\u003e 'https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b',\n      availability =\u003e 'in stock',\n      condition =\u003e 'new',\n      price =\u003e {\n          value =\u003e '99.95',\n          currency =\u003e 'USD',\n      },\n      shipping =\u003e [\n        {\n          country =\u003e 'US',\n          service =\u003e 'Standard Shipping',\n          price =\u003e {\n            value =\u003e '7.95',\n            currency =\u003e 'USD',\n          },\n        },\n      ],\n      brand =\u003e 'Apple',\n      gtin =\u003e '33333367890',\n      mpn =\u003e '333333',\n      googleProductCategory =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Household Paper Products \u003e Paper Towels',\n      productType =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Household Paper Products \u003e Paper Towels',\n      customLabel1 =\u003e 'Paper Towels'\n    }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n\n  # get single product info\n\n  $product_id = '333333';\n  $result = $bing-\u003eget(\n    resource =\u003e 'products',\n    method   =\u003e 'get',\n    id       =\u003e 'online:en:US:'. $product_id\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Products info: \\n\". Dumper $result;\n\n  # delete a product\n\n  print \"product delete: \";\n\n  my $del_product_id = '333333';\n  $result = $bing-\u003edelete(\n    resource =\u003e 'products',\n    method   =\u003e 'delete',\n    id       =\u003e 'online:en:US:'. $del_product_id,\n    dryrun   =\u003e 1,\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '204' ? 'success' : 'failure') .\"\\n\"; # 204 = delete success\n  print Dumper $result;\n\n  # batch insert\n\n  $products = [];\n  $batch_id = 0;\n\n  foreach my $i ('211203'..'211205') {\n    push @$products, {\n      batchId =\u003e ++$batch_id,\n      merchantId =\u003e $bing-\u003e{merchant_id},\n      method =\u003e 'insert', # insert / get / delete\n      #productId =\u003e '', # for get / delete\n      product =\u003e { # for insert\n        contentLanguage =\u003e 'en',\n        targetCountry =\u003e 'US',\n        channel =\u003e 'online',\n        offerId =\u003e \"$i\",\n        title =\u003e \"item title $i\",\n        description =\u003e \"The item description for $i\",\n        link =\u003e 'http://www.bing.com',\n        imageLink =\u003e 'https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b',\n        availability =\u003e 'in stock',\n        condition =\u003e 'new',\n        price =\u003e {\n          value =\u003e '10.95',\n          currency =\u003e 'USD',\n        },\n        shipping =\u003e [\n          {\n            country =\u003e 'US',\n            service =\u003e 'Standard Shipping',\n            price =\u003e {\n              value =\u003e '7.95',\n              currency =\u003e 'USD',\n            },\n          },\n        ],\n        brand =\u003e 'Apple',\n        gtin =\u003e \"${i}67890\",\n        mpn =\u003e \"$i\",\n        googleProductCategory =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Household Paper Products \u003e Paper Towels',\n        productType =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Household Paper Products \u003e Paper Towels',\n        customLabel1 =\u003e 'Paper Towels'\n      }\n    };\n  }\n\n  $result = $bing-\u003epost(\n    resource =\u003e 'products',\n    method   =\u003e 'batch',\n    dryrun   =\u003e 1,\n    body =\u003e { entries =\u003e $products }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n\n  # batch get\n\n  $products = [];\n  $batch_id = 0;\n  foreach my $product_id ('211203'..'211209') {\n    push @$products, {\n      batchId    =\u003e ++$batch_id,\n      merchantId =\u003e $bing-\u003e{merchant_id},\n      method     =\u003e 'get', # insert / get / delete\n      productId  =\u003e 'online:en:US:'. $product_id, # for get / delete\n    };\n  }\n\n  $result = $bing-\u003epost(\n    resource =\u003e 'products',\n    method   =\u003e 'batch',\n    dryrun   =\u003e 1,\n    body =\u003e { entries =\u003e $products }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print Dumper $result;\n\n  # batch delete\n\n  $products = [];\n  $batch_id = 0;\n  foreach my $product_id ('211203'..'211205') {\n    push @$products, {\n      batchId    =\u003e ++$batch_id,\n      merchantId =\u003e $bing-\u003e{merchant_id},\n      method     =\u003e 'delete', # insert / get / delete\n      productId  =\u003e 'online:en:US:'. $product_id, # for get / delete\n    };\n  }\n\n  $result = $bing-\u003epost(\n    resource =\u003e 'products',\n    method   =\u003e 'batch',\n    dryrun   =\u003e 1,\n    body =\u003e { entries =\u003e $products }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n\n=head1 METHODS AND FUNCTIONS\n\n=head2 new()\n\n  Create a new Bing::ContentAPI object\n\n=head3 debug\n\n  Displays API debug information\n\n=head3 merchant_id\n\n  Merchant ID is the Microsoft Advertising Merchant Center Store ID at https://ads.microsoft.com/\n\n=head3 developer_token\n\n  Developer token from https://developers.ads.microsoft.com/Account\n\n=head3 client_id\n\n  Client ID is the Application ID value in \"Registering Your Application\":\n  https://learn.microsoft.com/en-us/advertising/guides/authentication-oauth-register\n\n=head3 redirect_uri\n\n  Redirect URI is the Mobile/Desktop app redirect URI value in \"Registering Your Application\":\n  https://learn.microsoft.com/en-us/advertising/guides/authentication-oauth-register\n\n=head3 refresh_token\n\n  The current refresh token\n\n=head2 refresh_access_token()\n\n  Using the current refresh_token, obtain a new access and refresh token\n\n=head3 access_token\n\n  returns access_token obtained via refresh_access_token()\n\n=head3 refresh_token\n\n  returns refresh_token obtained via refresh_access_token()\n\n=head2 PRODUCTS\n\n=head3 batch\n\n  Retrieves, inserts, and deletes multiple products in a single request.\n\n=head3 insert\n\n  Uploads a product to your Merchant Center account. If an item with the\n  same channel, contentLanguage, offerId, and targetCountry already exists,\n  this method updates that entry.\n\n=head3 list\n\n  Lists the products in your Merchant Center account.\n\n=head3 get\n\n  Retrieves a product from your Merchant Center account.\n\n=head3 delete\n\n  Deletes a product from your Merchant Center account.\n\n=head2 CATALOGS\n\n=head3 list\n\n  Lists the catalogs in your Merchant Center Account.\n\n=head3 status\n\n  Lists the status and issues of products offers in your Merchant Center Account.\n\n=head1 UNIMPLEMENTED FEATURES\n\n  Certain API methods are not yet implemented (no current personal business need).\n\n  A \"custom\" resource is available to perform methods that are not implemented by\n  this module.\n\n  $result = $bing-\u003eget(\n    resource =\u003e 'custom',\n    method   =\u003e 'merchantId/orders/orderId'\n  );\n\n=head1 PREREQUISITES\n\n  JSON\n  REST::Client\n  HTML::Entities\n\n=head1 AUTHOR\n\n  Original Author\n  Bill Gerrard \u003cbill@gerrard.org\u003e\n\n=head1 COPYRIGHT AND LICENSE\n\n  Copyright (C) 2018-2022 Bill Gerrard\n\n  This library is free software; you can redistribute it and/or modify\n  it under the same terms as Perl itself, either Perl version 5.20.2 or,\n  at your option, any later version of Perl 5 you may have available.\n  Disclaimer of warranty: This program is provided by the copyright holder\n  and contributors \"As is\" and without any express or implied warranties.\n  The implied warranties of merchantability, fitness for a particular purpose,\n  or non-infringement are disclaimed to the extent permitted by your local\n  law. Unless required by law, no copyright holder or contributor will be\n  liable for any direct, indirect, incidental, or consequential damages\n  arising in any way out of the use of the package, even if advised of the\n  possibility of such damage.\n\n\n=cut\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbillgerrard%2Fbing-content-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbillgerrard%2Fbing-content-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbillgerrard%2Fbing-content-api/lists"}