{"id":16482455,"url":"https://github.com/jamesmacaulay/shopify-clj","last_synced_at":"2025-03-23T11:33:18.506Z","repository":{"id":4929730,"uuid":"6086377","full_name":"jamesmacaulay/shopify-clj","owner":"jamesmacaulay","description":"A Clojure library for interacting with the Shopify API","archived":false,"fork":false,"pushed_at":"2015-10-01T01:42:31.000Z","size":687,"stargazers_count":14,"open_issues_count":4,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-18T20:16:31.372Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"andres-montanez/Magallanes","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesmacaulay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-10-05T05:49:00.000Z","updated_at":"2024-07-10T11:12:39.000Z","dependencies_parsed_at":"2022-07-08T03:01:47.673Z","dependency_job_id":null,"html_url":"https://github.com/jamesmacaulay/shopify-clj","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/jamesmacaulay%2Fshopify-clj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmacaulay%2Fshopify-clj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmacaulay%2Fshopify-clj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmacaulay%2Fshopify-clj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesmacaulay","download_url":"https://codeload.github.com/jamesmacaulay/shopify-clj/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245097197,"owners_count":20560311,"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":[],"created_at":"2024-10-11T13:10:47.433Z","updated_at":"2025-03-23T11:33:17.722Z","avatar_url":"https://github.com/jamesmacaulay.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# shopify-clj\n\n\n[![Dependencies Status](https://jarkeeper.com/jamesmacaulay/shopify-clj/status.png)](https://jarkeeper.com/jamesmacaulay/shopify-clj)\n\nA [Clojure][clojure] library for interacting with the [Shopify][shopify] platform.\n\n* `shopify.resources`: functions for interacting with [a shop's resources][resource-docs].\n* `shopify.friend`: provides a [friend][friend] workflow to authenticate [ring][ring] apps with Shopify shops using [OAuth2][auth-docs].\n\nThere is [documentation][codox-docs] and [annotated source][marginalia-docs].\n\n[clojure]: http://clojure.org\n[shopify]: http://www.shopify.com/\n[resource-docs]: http://docs.shopify.com/api\n[ring]: https://github.com/ring-clojure/ring\n[friend]: https://github.com/cemerick/friend\n[auth-docs]: http://docs.shopify.com/api/tutorials/oauth\n[codox-docs]: http://jamesmacaulay.github.com/shopify-clj/docs/codox/index.html\n[marginalia-docs]: http://jamesmacaulay.github.com/shopify-clj/docs/marginalia/uberdoc.html\n\n## Installation\n\nShopify artifacts are [released to Clojars][clojars-shopify].\n\n[Leiningen][leiningen] is the way to go for managing dependencies in Clojure. Add the following dependency to your `project.clj`:\n\n```\n:dependencies [[shopify \"0.1.1\"]]\n```\n\n[clojars-shopify]: https://clojars.org/shopify/shopify\n[leiningen]: https://github.com/technomancy/leiningen\n\n## Getting started\n\nFirst, you'll need to [get some API credentials and a development shop][api-getting-started].\n\nThe easiest way of accessing an individual shop is by [creating a private app][private-apps], but this is only really useful for experimentation. To use OAuth2, you need to [create an app through your Partner account][api-getting-started].\n\n[api-getting-started]: http://docs.shopify.com/api/the-basics/getting-started\n[private-apps]: http://docs.shopify.com/api/tutorials/creating-a-private-app\n\n### Private App Authentication\n\nPrivate apps are the quickest way of getting started. Just [get some credentials][private-apps] and put them in a map:\n\n```clojure\n(def auth {:shop \"my-dev-shop.myshopify.com\"\n           :api-key \"6dd96e9b19a0a7b3792f354eaf2a982b\"\n           :password \"195b5baab7ce4581a861e925e930301d\"})\n```\n\n### Making requests\n\nFire up a REPL and define an auth map for a private app as shown above. Now bring in the `shopify.resources` namespace:\n\n```clojure\n(require '[shopify.resources :as shop])\n```\n\nAnd try out a few simple requests:\n\n```clojure\n(shop/get-shop auth)\n; {:country \"CA\", :longitude \"-79.385324\", ...}\n\n(shop/get-list :pages {:limit 2 :fields \"id,title\"} auth)\n; [{:shopify.resources/type :page, :id 9855484, :title \"About Us\"}\n;  {:shopify.resources/type :page, :id 9855482, :title \"Welcome\"}]\n\n(shop/get-one :page {:id 9855484} auth)\n; {:published-at \"2013-03-10T23:49:41-04:00\", :handle \"about-us\", ...}\n\n(shop/get-count :pages {} auth)\n; 2\n```\n\nThe first map argument is always assumed to be the params or attributes of the request, which is why an empty map needed to be passed before `auth` in the `get-count` request (`get-shop` never takes any params).\n\nIf you don't want to bother passing in the same auth map with every request, you can wrap your requests with the `with-opts` macro:\n\n```clojure\n(shop/with-opts auth\n  {:page-count (shop/get-count :pages)\n   :first-title (-\u003e (shop/get-list :pages {:limit 1}) first :title)})\n; {:page-count 2, :first-title \"About Us\"}\n```\n\nYou can create and update with `save!`:\n\n```clojure\n(shop/save! :page {:title \"New page!\" :body_html \"\u003cp\u003eHello!\u003c/p\u003e\"} auth)\n; {:published-at \"2013-03-11T00:11:00-04:00\", :handle \"new-page\", :id 9855576, ...}\n\n(shop/with-opts auth\n  (-\u003e (shop/get-one :page {:id 9855576})\n      (update-in [:title] clojure.string/upper-case)\n      shop/save!\n      (select-keys [:id :title])))\n; {:title \"NEW PAGE!\", :id 9855576}\n```\n\nThe call to `save!` in the second example just had a single altered attribute map as its only argument (via the [thread-first macro][thread-first]). Instead of figuring out the resource type from the usual first keyword argument, it extracted the type from a `:shopify.resources/type` key which is embedded into all attribute maps returned by the library (and which is stripped from request params before they get serialized).\n\nLastly, you can delete stuff:\n\n```clojure\n(shop/delete! :page {:id 9855576} auth)\n; nil\n```\n\n[thread-first]: http://clojuredocs.org/clojure_core/clojure.core/-%3E\n\n### OAuth2\n\nIf you're building a Shopify web app, you'll need to use OAuth2. The `shopify.friend` namespace provides a [friend][friend] workflow for this purpose.\n\nFirst, you'll need a map representing your app:\n\n```clojure\n(def my-shopify-app\n  {:url \"http://localhost:3000\"\n   :key \"70bc2f19efa5129f202e661ac6fd38f3\"\n   :secret \"8eb54f11bedfad9c3e2287479f2d525c\"\n   :scope [:read_products :read_orders]})\n```\n\nThis is used to configure the workflow provided by `shopify.friend`:\n\n```clojure\n(def shopify-auth\n  (shopify.friend/workflow {:api-client my-shopify-app}))\n\n(def app\n  (-\u003e my-handler\n      some-other-middleware\n      (cemerick.friend/authenticate\n        {:allow-anon? true\n         :workflows [shopify-auth]})))\n```\n\nHere's [a working example][example-server]. With the middleware in place, you can authenticate a shop by hitting `/auth/shopify?shop=some-shop.myshopify.com`. This is most often done [with a form][example-login-form].\n\n**Note** Make sure to include [wrap-params](https://ring-clojure.github.io/ring/ring.middleware.params.html#var-wrap-params) in your middleware, so that the extension can parse the shop parameter.\n\nYou can get a list of the current Shopify authentications from the request like so:\n\n```clojure\n(shopify.friend/shopify-auths request)\n```\n\nThis returns a sequence of auth maps which can be used as the basis of shop resource requests in the same way as the auth map for a private app.\n\n[example-server]: https://github.com/jamesmacaulay/shopify-clj/blob/master/examples/shop-launchpad/src/shop_launchpad/server.clj\n[example-login-form]: https://github.com/jamesmacaulay/shopify-clj/blob/71344d9c0816d9b70c18b85fbb5fe15dd1523a80/examples/shop-launchpad/src/shop_launchpad/templates/index.html#L16-L19\n\n## License\n\nCopyright © 2012-2013\n\nDistributed under the Eclipse Public License, the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmacaulay%2Fshopify-clj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesmacaulay%2Fshopify-clj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmacaulay%2Fshopify-clj/lists"}