{"id":13561100,"url":"https://github.com/40ants/openrpc","last_synced_at":"2026-01-16T20:20:31.578Z","repository":{"id":143092991,"uuid":"557887316","full_name":"40ants/openrpc","owner":"40ants","description":"OpenRPC implementation for Common Lisp","archived":false,"fork":false,"pushed_at":"2026-01-15T12:40:52.000Z","size":324,"stargazers_count":33,"open_issues_count":4,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-01-15T16:54:42.046Z","etag":null,"topics":["api","common-lisp","json-rpc","open-rpc","rpc"],"latest_commit_sha":null,"homepage":"https://40ants.com/openrpc/","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/40ants.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":"docs/contributing.lisp","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-26T13:46:23.000Z","updated_at":"2026-01-15T12:40:56.000Z","dependencies_parsed_at":"2023-10-15T17:06:20.742Z","dependency_job_id":"1cc33cfc-e485-49dd-91d3-ff66452f8523","html_url":"https://github.com/40ants/openrpc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/40ants/openrpc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Fopenrpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Fopenrpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Fopenrpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Fopenrpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/40ants","download_url":"https://codeload.github.com/40ants/openrpc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/40ants%2Fopenrpc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28482267,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["api","common-lisp","json-rpc","open-rpc","rpc"],"created_at":"2024-08-01T13:00:52.517Z","updated_at":"2026-01-16T20:20:31.564Z","avatar_url":"https://github.com/40ants.png","language":"Common Lisp","funding_links":["https://www.patreon.com/bePatron?u=33868637"],"categories":["Common Lisp","Interfaces to other package managers"],"sub_categories":["OpenAPI, OData, OpenRPC"],"readme":"\u003ca id=\"x-28OPENRPC-DOCS-2FINDEX-3A-40README-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n# OpenRPC for Common Lisp\n\n[![](https://github-actions.40ants.com/40ants/openrpc/matrix.svg)][4bbd]\n\nThis framework is built on top of [JSON-RPC][c597] and [`Clack`][75f7]. Comparing to `JSON-RPC` library,\nit provides these key features:\n\n* Automatic [OpenRPC spec][3160] generation.\n* Automatic `JSON-RPC` client building by Open`RPC` spec. This includes creation of Common Lisp classes and methods\n  for making `RPC` requests and returning native `CL` objects.\n* On both server and client sides your code looks very lispy, all `JSON` marshalling is done under the hood.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40SERVER-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## Server\n\n\u003ca id=\"openrpc-server-asdf-system-details\"\u003e\u003c/a\u003e\n\n### OPENRPC-SERVER ASDF System Details\n\n* Description: Open`RPC` server implementation for Common Lisp.\n* Licence: `BSD`\n* Author: Alexander Artemenko\n* Homepage: [https://40ants.com/openrpc/][348e]\n* Source control: [GIT][76b5]\n* Depends on: [alexandria][8236], [clack-cors][087e], [clack-prometheus][babd], [closer-mop][61a4], [jsonrpc][a9bd], [lack-request][6a02], [lambda-fiddle][3ad9], [local-time][46a1], [log4cl][7f8b], [log4cl-extras][691c], [serapeum][c41d], [str][ef7f], [websocket-driver][4f50], [yason][aba2]\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40DEFINING-METHODS-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n### Defining Methods\n\nHere is an example of openrpc-server `ASDF` system allows to define\n`JSON-RPC` methods and data-structures they return.\n\nLet's see how we can define an [`api`][5d14] for usual PetShop example.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40SIMPLE-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n#### Simple Example\n\nFirst, we will operate on usual Common Lisp class:\n\n```\n(defclass pet ()\n  ((id :initarg :id\n       :type integer\n       :reader pet-id)\n   (name :initarg :name\n         :type string\n         :reader pet-name)\n   (tag :initarg :tag\n        :type string\n        :reader pet-tag)))\n```\nNow we can define an `RPC` method to create a new pet:\n\n```\n(openrpc-server:define-rpc-method create-pet (name tag)\n  (:summary \"Short method docstring.\")\n  (:description \"Lengthy description of the method.\")\n  (:param name string \"Pet's name\"\n          :description \"This is a long description of the parameter.\")\n  (:param tag string \"Old param, don't use it anymore.\" :deprecated t)\n  (:result pet)\n  (let* ((new-id (get-new-id))\n         (pet (make-instance 'pet\n                             :id new-id\n                             :name name\n                             :tag tag)))\n    (setf (gethash new-id *pets*)\n          pet)\n    pet))\n```\nHere we should explicitly specify type for each parameter and result's type.\n\nPay attention, the result type is `PET`. [`openrpc-server`][24be] system takes care on serializing\nobjects and you can retrieve an Open`RPC` spec for any type, using [`type-to-schema`][4de0] generic-function:\n\n```\nCL-USER\u003e (serapeum:toggle-pretty-print-hash-table)\nT\nCL-USER\u003e (openrpc-server:type-to-schema 'pet)\n(SERAPEUM:DICT\n  \"type\" \"object\"\n  \"properties\" (SERAPEUM:DICT\n                 \"id\" (SERAPEUM:DICT\n                        \"type\" \"integer\"\n                       )\n                 \"name\" (SERAPEUM:DICT\n                          \"type\" \"string\"\n                         )\n                 \"tag\" (SERAPEUM:DICT\n                         \"type\" \"string\"\n                        )\n                )\n  \"required\" '(\"tag\" \"name\" \"id\")\n  \"x-cl-class\" \"PET\"\n  \"x-cl-package\" \"COMMON-LISP-USER\"\n )\n```\nThis method is used to render response requests to `/openrpc.json` handle of your [`api`][5d14].\n\nThere is also a second generic-function which transform class instance into simple datastructures\naccording to a scheme. For example, here is how we can serialize our pet:\n\n```\nCL-USER\u003e (openrpc-server:transform-result\n          (make-instance 'pet :name \"Bobik\"))\n(SERAPEUM:DICT\n  \"name\" \"Bobik\"\n ) \nCL-USER\u003e (openrpc-server:transform-result\n          (make-instance 'pet\n                         :name \"Bobik\"\n                         :tag \"the dog\"))\n(SERAPEUM:DICT\n  \"name\" \"Bobik\"\n  \"tag\" \"the dog\"\n )\n```\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40LISTS-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n#### Returning Lists\n\nTo return result as a list of objects of some kind, use `(:result (list-of pet))` form:\n\n```\n(openrpc-server:define-rpc-method list-pets ()\n  (:result (list-of pet))\n  (retrieve-all-pets))\n```\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40PAGINATION-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n#### Paginated Results\n\nSometimes your system might operate on a lot of objects and you don't want to return all of them at once.\nFor this case, framework supports a [keyset pagination][7ba8]. To use\nit, your method should accept `LIMIT` argument and `PAGE-KEY` argument. And if there are more results, than\nmethod should return as a second value the page key for retrieving the next page.\n\nIn this simplified example, we'll return `(list 1 2 3)` for the first page, `(list 4 5 6)` for the second and\n`(list 7 8)` for the third. Pay attention how `VALUES` form is used for first two pages but omitted for the third:\n\n```\n(openrpc-server:define-rpc-method list-pets (\u0026key (limit 3) page-key)\n  (:param limit integer)\n  (:param page-key integer)\n  (:result (paginated-list-of integer))\n\n  (cond\n    ((null page-key)\n     (values (list 1 2 3)\n             3))\n    ((= page-key 3)\n     (values (list 4 5 6)\n             6))\n    (t\n      (list 7 8))))\n```\nOf cause, in the real world application, you should use `PAGE-KEY` and `LIMIT` arguments in the `WHERE` `SQL` clause.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40STARTING-SERVER-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n### Using Clack to Start Server\n\nFramework is based on Clack. Use [`make-clack-app`][1d3d] to create an application suitable for serving with `CLACK:CLACKUP`.\n\nThen just start the web application as usual.\n\n```\n(clack:clackup (make-clack-app)\n               :address interface\n               :port port)\n```\nAlso, you might use any Lack middlewares. For example, here is how \"mount\" middleware can be used\nto make [`api`][5d14] work on `/api/` `URL` path, while the main application is working on other `URL` paths:\n\n```\n(defparameter *app*\n  (lambda (env)\n    '(200 (:content-type \"text/plain\") (\"Hello, World!\"))))\n\n(clack:clackup\n (lambda (app)\n   (funcall (lack.util:find-middleware :mount)\n            app\n            \"/api\"\n            (make-clack-app)))\n *app*)\n```\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40SPEC-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n### OpenRPC Spec\n\nThe key feature of the framework, is an automatic `OpenRPC spec` generation.\n\nWhen you have your [`api`][5d14] up and running, spec will be available on `/openrpc.json` path.\nFor our example project it will looks like:\n\n```json\n{\n  \"methods\": [\n    {\n      \"name\": \"rpc.discover\",\n      \"params\": [],\n      \"result\": {\n        \"name\": \"OpenRPC Schema\",\n        \"schema\": {\n          \"$ref\": \"https://raw.githubusercontent.com/open-rpc/meta-schema/master/schema.json\"\n        }\n      }\n    },\n    {\n      \"name\": \"list-pets\",\n      \"params\": [\n        {\n          \"name\": \"page-key\",\n          \"schema\": {\n            \"type\": \"integer\"\n          }\n        },\n        {\n          \"name\": \"limit\",\n          \"schema\": {\n            \"type\": \"integer\"\n          }\n        }\n      ],\n      \"result\": {\n        \"name\": \"list-pets-result\",\n        \"schema\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"items\": {\n              \"type\": \"array\",\n...\n```\n\u003ca id=\"x-28OPENRPC-SERVER-2FDOCS-3A-3A-40API-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n### API\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FAPI-3AAPI-20CLASS-29\"\u003e\u003c/a\u003e\n\n#### [class](ecd8) `openrpc-server/api:api` ()\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FAPI-3A-2ACURRENT-API-2A-20-28VARIABLE-29-29\"\u003e\u003c/a\u003e\n\n#### [variable](b3c7) `openrpc-server/api:*current-api*` -unbound-\n\nPoints to a current [`api`][5d14] object when processing any `RPC` method.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FAPI-3ADEFINE-API-20-2840ANTS-DOC-2FLOCATIVES-3AMACRO-29-29\"\u003e\u003c/a\u003e\n\n#### [macro](6fa2) `openrpc-server/api:define-api` (NAME \u0026KEY (TITLE \"Default API\") (VERSION \"0.1.0\")) \u0026BODY SLOTS\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FAPI-3AAPI-METHODS-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20OPENRPC-SERVER-2FAPI-3AAPI-29-29\"\u003e\u003c/a\u003e\n\n#### [reader](d9f8) `openrpc-server/api:api-methods` (api) (= (make-hash-table :test 'equal))\n\nReturns a hash-table containing meta-information about all [`api`][5d14] methods.\n\nReturned hash-table has key strings having methods names and internal\nobjects of class `method-info` as values. I'm not sure if we need to\nexport functions to manipulate with method info objects manually.\nUse [`openrpc-server/method:define-rpc-method`][b2e4] macro to add or update `RPC` methods.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FAPI-3AAPI-TITLE-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20OPENRPC-SERVER-2FAPI-3AAPI-29-29\"\u003e\u003c/a\u003e\n\n#### [reader](a8a9) `openrpc-server/api:api-title` (api) (:TITLE = \"Default API\")\n\nReturns a title of the [`api`][5d14].\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FAPI-3AAPI-VERSION-20-2840ANTS-DOC-2FLOCATIVES-3AREADER-20OPENRPC-SERVER-2FAPI-3AAPI-29-29\"\u003e\u003c/a\u003e\n\n#### [reader](9b9f) `openrpc-server/api:api-version` (api) (:version = \"0.1.0\")\n\nReturns a version of the [`api`][5d14].\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FMETHOD-3ADEFINE-RPC-METHOD-20-2840ANTS-DOC-2FLOCATIVES-3AMACRO-29-29\"\u003e\u003c/a\u003e\n\n#### [macro](e874) `openrpc-server/method:define-rpc-method` name args \u0026body body\n\nMacro to define `RPC` method.\n\nAll arguments should have corresponding (:param arg type) form in the `BODY`.\n\nAlso, there should be one (:result type) form in the `BODY`.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FINTERFACE-3ATYPE-TO-SCHEMA-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](6310) `openrpc-server/interface:type-to-schema` type\n\nThis method is called for all types for which [`primitive-type-p`][edf5] generic-function\nreturns `NIL`.\n\nIt should return as hash-table with `JSON-SCHEMA` corresponding to type. Keys of the dictionary should\nbe strings. It is convenient to use Serapeum's `DICT` macro for building the result.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FINTERFACE-3ATRANSFORM-RESULT-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](bf73) `openrpc-server/interface:transform-result` object\n\nPrepares object for serialization before responding to `RPC` call.\n\nResult should be list, hash-map or a value of primitive type.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FINTERFACE-3APRIMITIVE-TYPE-P-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](67f8) `openrpc-server/interface:primitive-type-p` type\n\nShould return t for type if it's name matched to simple types supported by [JSON-SCHEMA][686b].\n\nArgument `TYPE` is a symbol.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FINTERFACE-3AMAKE-INFO-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](d6c1) `openrpc-server/interface:make-info` api\n\nReturns a basic information about `API` for [info section][5f59] of Open`RPC` spec.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FERRORS-3ARETURN-ERROR-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [function](2efc) `openrpc-server/errors:return-error` message \u0026key (code -1) (error-class 'jsonrpc/errors:jsonrpc-callback-error)\n\nRaises an error to interrupt processing and return status to the caller.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FCLACK-3AMAKE-CLACK-APP-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](e463) `openrpc-server/clack:make-clack-app` api \u0026key http websocket indent-json\n\nShould return an app suitable for passing to clackup.\n\nYou can define a method to redefine application.\nBut to add middlewares it is more convenient to define a method for\n[`app-middlewares`][a0d7] generic-function.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FCLACK-3AAPP-MIDDLEWARES-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](9c4a) `openrpc-server/clack:app-middlewares` api\n\nShould return an plist of middlewared to be applied to the Clack application.\n\nKeys should be a keyword with middleware name. And value is a function accepting\na Clack application as a single argument and returning a new application.\n\nMiddlewares are applied to the app from left to right. This makes it possible to\ndefine an :around method which will inject or replace a middleware or original app.\n\nDefault method defines two middlewares with keys `:CORS` and `:PROMETHEUS`.\n(Prometheus middleware works on `SBCL` but not on `CCL`).\nTo wrap these middlewares, add your middlewares to the end of the list.\nTo add your middleware inside the stack - push it to the front.\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FCLACK-3ADEBUG-ON-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [function](ec03) `openrpc-server/clack:debug-on`\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FCLACK-3ADEBUG-OFF-20FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [function](1eea) `openrpc-server/clack:debug-off`\n\n\u003ca id=\"x-28OPENRPC-SERVER-2FINTERFACE-3ASLOTS-TO-EXCLUDE-20GENERIC-FUNCTION-29\"\u003e\u003c/a\u003e\n\n#### [generic-function](7acc) `openrpc-server/interface:slots-to-exclude` type\n\nYou can define a method for this generic function to exclude some slots from being shown in the `JSON` schema.\n\nPay attention that this generic-function is called with class not with objects to be serialized.\nWe need this because at the moment of generation [`api`][5d14] methods and Open`RPC` spec we know nothing about\nobjects except their classes.\n\nMethods of this function should return a list of strings. Given slots will be excluded from the spec\nand will not be serialized. Strings are compared in case-insensitive mode.\n\n\u003ca id=\"x-28OPENRPC-CLIENT-2FDOCS-3A-3A-40CLIENT-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## Client\n\n\u003ca id=\"openrpc-client-asdf-system-details\"\u003e\u003c/a\u003e\n\n### OPENRPC-CLIENT ASDF System Details\n\n* Description: Open`RPC` client implementation for Common Lisp.\n* Licence: `BSD`\n* Author: Alexander Artemenko\n* Homepage: [https://40ants.com/openrpc/][348e]\n* Source control: [GIT][76b5]\n* Depends on: [alexandria][8236], [closer-mop][61a4], [dexador][8347], [jsonrpc][a9bd], [kebab][5186], [log4cl][7f8b], [serapeum][c41d], [str][ef7f], [usocket][636b], [yason][aba2]\n\n[`openrpc-client`][4c76] `ASDF` system provides a way to build `CL` classes and methods for working with `JSON-RPC` `API`.\nAll you need is to give it an `URL` and all code will be created in compile-time as a result of macro-expansion.\n\n\u003ca id=\"generating\"\u003e\u003c/a\u003e\n\n### Generating\n\nFor example, this macro call:\n\n```\n\n(generate-client petshop\n                 \"http://localhost:8000/openrpc.json\")\n```\nWill generate the whole bunch of classes and methods:\n\n```\n(defclass petshop (jsonrpc/client:client) nil)\n\n(defun make-petshop () (make-instance 'petshop))\n\n(defmethod describe-object ((openrpc-client/core::client petshop) stream)\n  (format stream \"Supported RPC methods:~2%\")\n  (format stream \"- ~S~%\" '(rpc-discover))\n  (format stream \"- ~S~%\"\n          '(list-pets \u0026key (page-key nil page-key-given-p)\n            (limit nil limit-given-p)))\n  (format stream \"- ~S~%\" '(create-pet (name string) (tag string)))\n  (format stream \"- ~S~%\" '(get-pet (id integer))))\n\n(defclass pet nil\n  ((id :initform nil :initarg :id :reader pet-id)\n   (name :initform nil :initarg :name :reader pet-name)\n   (tag :initform nil :initarg :tag :reader pet-tag)))\n\n(defmethod print-object ((openrpc-client/core::obj pet) stream)\n  (print-unreadable-object (openrpc-client/core::obj stream :type t)\n    (format stream \" ~A=~S\" 'id (pet-id openrpc-client/core::obj))\n    (format stream \" ~A=~S\" 'name (pet-name openrpc-client/core::obj))\n    (format stream \" ~A=~S\" 'tag (pet-tag openrpc-client/core::obj))))\n\n(defmethod rpc-discover ((openrpc-client/core::client petshop))\n  ...)\n\n(defmethod list-pets\n    ((openrpc-client/core::client petshop)\n     \u0026key (page-key nil page-key-given-p) (limit nil limit-given-p))\n  ...)\n\n(defmethod create-pet\n    ((openrpc-client/core::client petshop) (name string) (tag string))\n  ...)\n\n(defmethod get-pet ((openrpc-client/core::client petshop) (id integer))\n  ...)\n```\n\u003ca id=\"using\"\u003e\u003c/a\u003e\n\n### Using\n\nWhen client is generated, you need to make an instance of it and to connect\nit to the server:\n\n```\n(let ((cl (make-petshop)))\n    (jsonrpc:client-connect cl :url \"http://localhost:8000/\" :mode :http)\n    cl)\n```\nYou can use any transport, supported by `JSONRPC` library.\n\n`DESCRIBE-OBJECT` method is defined for a client, so you might see which methods are supported right in the `REPL`:\n\n```common-lisp-repl\nOPENRPC-EXAMPLE/CLIENT\u003e (defvar *client* (make-test-client))\n#\u003cPETSHOP {1007AB2B13}\u003e\n\nOPENRPC-EXAMPLE/CLIENT\u003e (describe *client*)\nSupported RPC methods:\n\n- (RPC-DISCOVER)\n- (LIST-PETS \u0026KEY (PAGE-KEY NIL PAGE-KEY-GIVEN-P)\n             (LIMIT NIL LIMIT-GIVEN-P))\n- (CREATE-PET (NAME STRING) (TAG STRING))\n- (GET-PET (ID INTEGER))\n```\nAnd then to call these methods as usually you do in Common Lisp. Pay attention, that\nthe library returns not `JSON` dictionaries, but ready to use `CL` class instances:\n\n```common-lisp-repl\nOPENRPC-EXAMPLE/CLIENT\u003e (create-pet *client* \"Bobik\" \"the dog\")\n#\u003cPET  ID=1 NAME=\"Bobik\" TAG=\"the dog\"\u003e\n\nOPENRPC-EXAMPLE/CLIENT\u003e (create-pet *client* \"Murzik\" \"the cat\")\n#\u003cPET  ID=2 NAME=\"Murzik\" TAG=\"the cat\"\u003e\n\nOPENRPC-EXAMPLE/CLIENT\u003e (create-pet *client* \"Homa\" \"the hamster\")\n#\u003cPET  ID=3 NAME=\"Homa\" TAG=\"the hamster\"\u003e\n```\nNow, pay attention how pagination does work.\n\n```common-lisp-repl\nOPENRPC-EXAMPLE/CLIENT\u003e (list-pets *client* :limit 2)\n(#\u003cPET  ID=1 NAME=\"Bobik\" TAG=\"the dog\"\u003e\n #\u003cPET  ID=2 NAME=\"Murzik\" TAG=\"the cat\"\u003e)\n#\u003cFUNCTION (FLET OPENRPC-CLIENT/CORE::RETRIEVE-NEXT-PAGE :IN LIST-PETS) {1006D1F3CB}\u003e\n```\nThis call has returned a list of objects as the first value and a closure, which can\nbe called to retrive the next page. Let's retrieve it now!\n\n```common-lisp-repl\nOPENRPC-EXAMPLE/CLIENT\u003e (funcall #v167:1)\n(#\u003cPET  ID=3 NAME=\"Homa\" TAG=\"the hamster\"\u003e)\n```\nNow this is the last page and there is now a closure to retrieve the next page. Learn more how\nto implement pagination on server-side in the [`Paginated Results`][5c31] section.\n\n\u003ca id=\"x-28OPENRPC-CLIENT-2FCORE-3AGENERATE-CLIENT-20-2840ANTS-DOC-2FLOCATIVES-3AMACRO-29-29\"\u003e\u003c/a\u003e\n\n### [macro](c524) `openrpc-client/core:generate-client` class-name url-or-path \u0026key (export-symbols t)\n\nGenerates Common Lisp client by Open`RPC` spec.\n\n`CLASS-NAME` is the name of a `API` class. Also, a corresponding `MAKE`-\u003cCLASS-NAME\u003e function\nis created.\n\n`URL-OR-PATH` argument could be a string with `HTTP` `URL` of a spec, or a pathname\nif a spec should be read from the disc.\n\n\u003ca id=\"x-28OPENRPC-DOCS-2FCONTRIBUTING-3A-3A-40ASK-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## Our Ask...\n\nIf you use this or find value in it, please consider contributing in one or more of the following ways:\n\n1. Sponsor project at [Patreon][2180] or [Boosty][ae59] and make a contribution.\n2. Star it!\n3. Share posts about it in social networks!\n4. Fix an issue.\n5. Add a feature (post a proposal in an issue first!).\n\n\u003ca id=\"x-28OPENRPC-DOCS-2FCONTRIBUTING-3A-3A-40CONTRIBUTORS-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\"\u003e\u003c/a\u003e\n\n## Contributors\n\nThese people have contributed to Open`RPC`. I'm so grateful to them!\n\n* [Kilian M. Haemmerle][5863]\n\n\n[348e]: https://40ants.com/openrpc/\n[4c76]: https://40ants.com/openrpc/#x-28-23A-28-2814-29-20BASE-CHAR-20-2E-20-22openrpc-client-22-29-20ASDF-2FSYSTEM-3ASYSTEM-29\n[24be]: https://40ants.com/openrpc/#x-28-23A-28-2814-29-20BASE-CHAR-20-2E-20-22openrpc-server-22-29-20ASDF-2FSYSTEM-3ASYSTEM-29\n[5d14]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FAPI-3AAPI-20CLASS-29\n[a0d7]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FCLACK-3AAPP-MIDDLEWARES-20GENERIC-FUNCTION-29\n[1d3d]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FCLACK-3AMAKE-CLACK-APP-20GENERIC-FUNCTION-29\n[5c31]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FDOCS-3A-3A-40PAGINATION-2040ANTS-DOC-2FLOCATIVES-3ASECTION-29\n[edf5]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FINTERFACE-3APRIMITIVE-TYPE-P-20GENERIC-FUNCTION-29\n[4de0]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FINTERFACE-3ATYPE-TO-SCHEMA-20GENERIC-FUNCTION-29\n[b2e4]: https://40ants.com/openrpc/#x-28OPENRPC-SERVER-2FMETHOD-3ADEFINE-RPC-METHOD-20-2840ANTS-DOC-2FLOCATIVES-3AMACRO-29-29\n[ae59]: https://boosty.to/40ants\n[76b5]: https://github.com/40ants/openrpc\n[4bbd]: https://github.com/40ants/openrpc/actions\n[c524]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/client/core.lisp#L522\n[b3c7]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/api.lisp#L14\n[ecd8]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/api.lisp#L18\n[d9f8]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/api.lisp#L19\n[a8a9]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/api.lisp#L27\n[9b9f]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/api.lisp#L31\n[6fa2]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/api.lisp#L39\n[ec03]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/clack.lisp#L181\n[1eea]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/clack.lisp#L186\n[e463]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/clack.lisp#L67\n[9c4a]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/clack.lisp#L74\n[2efc]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/errors.lisp#L9\n[d6c1]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/interface.lisp#L167\n[bf73]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/interface.lisp#L21\n[67f8]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/interface.lisp#L56\n[7acc]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/interface.lisp#L72\n[6310]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/interface.lisp#L85\n[e874]: https://github.com/40ants/openrpc/blob/661a1049c4b2e3e861de7a359597ca7837fbe77d/server/method.lisp#L313\n[c597]: https://github.com/cxxxr/jsonrpc\n[75f7]: https://github.com/fukamachi/clack\n[5863]: https://github.com/kilianmh\n[686b]: https://json-schema.org/\n[8236]: https://quickdocs.org/alexandria\n[087e]: https://quickdocs.org/clack-cors\n[babd]: https://quickdocs.org/clack-prometheus\n[61a4]: https://quickdocs.org/closer-mop\n[8347]: https://quickdocs.org/dexador\n[a9bd]: https://quickdocs.org/jsonrpc\n[5186]: https://quickdocs.org/kebab\n[6a02]: https://quickdocs.org/lack-request\n[3ad9]: https://quickdocs.org/lambda-fiddle\n[46a1]: https://quickdocs.org/local-time\n[7f8b]: https://quickdocs.org/log4cl\n[691c]: https://quickdocs.org/log4cl-extras\n[c41d]: https://quickdocs.org/serapeum\n[ef7f]: https://quickdocs.org/str\n[636b]: https://quickdocs.org/usocket\n[4f50]: https://quickdocs.org/websocket-driver\n[aba2]: https://quickdocs.org/yason\n[3160]: https://spec.open-rpc.org/\n[5f59]: https://spec.open-rpc.org/#info-object\n[7ba8]: https://use-the-index-luke.com/no-offset\n[2180]: https://www.patreon.com/bePatron?u=33868637\n\n* * *\n###### [generated by [40ANTS-DOC](https://40ants.com/doc/)]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F40ants%2Fopenrpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F40ants%2Fopenrpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F40ants%2Fopenrpc/lists"}