Before you start
What your AI can and can't do
- You need a ShelfSpace login at a store. Your AI acts as you, with your role at each store.
- When you connect, you choose which stores it may use. It can’t see any other store.
- It can look things up. If you allow everyday actions when you connect, it can also do everyday tasks: add a comment to a delivery, ask your team to check one, attach a Metrc manifest or COA, and send in a vendor invoice (it lands in Pending Review for a person to check). It can never make or approve a payment.
- Disconnect it any time in ShelfSpace under Settings → AI agents.
Claude and ChatGPT
Add ShelfSpace as a connector
Both apps connect with one address. Paste it where the app asks for a connector’s server URL.
Server URL
https://ourshelf.space/api/mcp- 1Claude: open Settings → Connectors, choose Add custom connector, and paste the server URL.
- 2ChatGPT: open Settings → Connectors, create a connector, paste the server URL, and pick OAuth for sign-in.
- 3Your app sends you to ShelfSpace. Sign in, enter your code, pick your stores, and approve.
- 4Ask a question, for example “Which of my stores can you see?”
Desktop coding tools such as Cursor and Claude Code are coming soon.
Meta Muse
Register an app, then add it to Muse
Muse signs in with an app you register in ShelfSpace. It takes about two minutes.
- 1In ShelfSpace, open Settings → AI agents → Register an app, and choose the Meta Muse preset.
- 2Copy the Client ID and the Client Secret. The secret is shown once, so keep it somewhere safe.
- 3In Muse, add a custom connector and paste the Client ID, the Client Secret and the values below.
- 4Turn on PKCE (S256). It’s required. Then connect, sign in to ShelfSpace, pick your stores, and approve.
Authorization URL
https://ourshelf.space/api/oauth/authorizeToken URL
https://ourshelf.space/api/oauth/tokenScope
shelfspace.readAPI description (OpenAPI)
https://ourshelf.space/api/agent/v1/openapi.jsonWeb API
Call the same tools over plain HTTP
Every tool is also a web endpoint. The OpenAPI file lists each tool with its inputs and answers.
Endpoint
POST https://ourshelf.space/api/agent/v1/tools/{tool}- Send
Authorization: Bearer <access token>from the sign-in above. Requests with cookies are refused. - The body is the tool’s arguments as a JSON object. An empty body means no arguments.
- Money is a decimal string with 2 places plus currency “USD”. Dates come with a matching *_display field in MM/DD/YYYY.
curl -X POST https://ourshelf.space/api/agent/v1/tools/list_my_stores \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Answers
| Status | Meaning |
|---|---|
| 200 | The tool ran, or it was refused. A refusal has applied: false, a refusal_code and a refusal_reason. |
| 400 | The body is not a JSON object, or the request carried a cookie. Send only the Authorization header. |
| 401 | The access token is missing, expired or revoked. Refresh it, or connect again. |
| 403 | The connection can't be used right now, for example no store is available to it. |
| 404 | No such tool. The list is in the OpenAPI file. |
| 429 | Too many requests. Wait a minute (see Retry-After) and try again. |
| 503 | AI agent access is turned off right now, or the service is briefly unavailable. Try again later. |
Refusal codes
A refusal is a normal answer, not an error. Show the person the refusal_reason, and don’t retry the same call in a loop. Some codes only apply to changes, which aren’t available yet.
| Code | Reason |
|---|---|
| not_found | No such tool or record is available to you. |
| ambiguous_candidates | That name is not a single clear match. Pick one of the candidates and use its id instead of the name. |
| role_not_permitted | Your role at this store does not allow this. |
| store_not_in_scope | That store is not one of the stores this connection can use. Call list_my_stores. |
| no_store_in_scope | None of the connected stores are available right now. |
| writes_paused | Changes by AI agents are paused right now. |
| agents_disabled_for_store | AI agents are turned off for this store. |
| rate_limited | Too many calls right now. Wait a minute and try again. |
| daily_cap_reached | This connection has reached today's call limit. It resets at midnight UTC. |
| limit_reached | A limit on reading invoices sent by AI apps has been reached. Try again in a few minutes; if it is the daily limit, it resets at midnight UTC — or add the invoice in ShelfSpace. |
| in_progress | This call is already running. |
| idempotency_key_reused | That idempotency_key was already used with different arguments. |
| target_busy | Another call is already working on this record. |
| freshness_stale | The record changed since you looked at it. Read it again first. |
| freshness_token_used | That confirmation was already used. Read the record again first. |
| review_in_app | This needs a person to review it in ShelfSpace. |
| needs_human_receive | A person needs to receive this delivery in ShelfSpace. |
| document_type_not_permitted | That document type is not available to AI agents. |
| money_route_refused | Payments and money changes are not available to AI agents. |
| route_conflict | The record is not in a state that allows this. |
| unknown_outcome | We could not confirm whether this finished. Check the record in ShelfSpace. |
| invalid_query | That query is outside what this tool accepts. Use an entity, fields and operators from the tool description. |
| invalid_arguments | A required argument is missing or not valid (for a change: an idempotency_key of 16 to 128 characters). Check the tool's input schema. |
Questions? Email support@shelfspace.pro and we’ll answer there.