{"openapi":"3.0.1","info":{"title":"Check Cherry App Platform","version":"v1","description":"This guide is for developers building an app that Check Cherry businesses install:\na design shop, a marketing tool, an accounting sync. It walks through how a customer\nconnects your app to their account and how your app calls the API on their behalf.\nThe endpoints themselves are in the [Business API reference](/api/docs).\n\n## Getting Started\n\n**Base URL** — All API requests should be made to:\n\n```\nhttps://api.checkcherry.com/api/v1/\n```\n\n**Setup:**\n\n1. Join the Partner Program. Email `support@checkcherry.com` and we will set up your\n   developer account.\n2. Create your app at [checkcherry.com/developer/apps](https://www.checkcherry.com/developer/apps).\n   The name, logo, and links you enter are what customers see when they connect.\n3. Open your app's **OAuth** page and turn it on. Fill in three things:\n   - **Redirect URL.** The page on your site we send customers back to after they\n     approve. Must be `https://`.\n   - **Permissions.** What your app needs to do in the customer's account. Ask only\n     for what you use; customers see this list before they approve.\n   - **Install URL.** The page on your site where a customer clicks to connect.\n     Check Cherry links customers there from their Integrations page.\n4. Copy your **Client ID**. It identifies your app in the steps below. There is no\n   secret to keep.\n\nOnce your app is published, every customer sees it on their Integrations page with a\n**Connect** button that opens your Install URL.\n\n## Authentication\n\nWhen a customer connects your app, you receive an access token for their account.\nSend it with every request:\n\n```\ncurl -H \"Authorization: Bearer <access_token>\" https://api.checkcherry.com/api/v1/leads\n```\n\nThe token already knows which business it belongs to, so there is nothing else to\nsend. It can do exactly what your app's permissions allow; a request outside them\nreturns `403`.\n\nAlways send the token in the `Authorization` header, never in the URL.\n\nWhen a token no longer works (it expired, or the customer disconnected your app), the\nAPI returns `401`. Refresh it (see below). If refreshing fails too, ask the customer\nto connect again.\n\n**Built on App ID and App Secret?** That method still works for existing apps and is\ndocumented in [App credentials (legacy)](/api/docs?spec=legacy), along with how to\nmove to OAuth.\n\n## Implementing OAuth\n\nConnecting works the same way as \"Sign in with Google\": the customer is sent to\nCheck Cherry, approves your app, and is sent back to you with a code that you trade\nfor a token. Check Cherry follows the OAuth 2.1 standard, so a standard OAuth\nlibrary for your language will handle most of this. Point it at:\n\n```\nAuthorization URL:  https://www.checkcherry.com/oauth/authorize\nToken URL:          https://www.checkcherry.com/oauth/token\n```\n\nYour library will ask whether to use PKCE. Say yes, with the `S256` method. If it\nasks for a client secret, leave it blank; your app doesn't have one.\n\n**Want to see it working first?** Our\n[sample apps](https://github.com/Check-Cherry/checkcherry-sample-apps) include a\ncomplete connect flow you can run locally and copy from.\n\nIf you are doing it by hand, here is the whole flow.\n\n**1. The customer starts on your site.** Before sending them to Check Cherry, make two\nrandom strings and save them in the customer's session:\n\n- a **verifier**, which you will send back at step 3, and\n- a **state** value, which you will check when the customer returns.\n\nHash the verifier with SHA-256, base64url-encode the result, and call that the\n**challenge**. Then send the customer to:\n\n```\nhttps://www.checkcherry.com/oauth/authorize\n  ?response_type=code\n  &client_id=<your client id>\n  &redirect_uri=<your redirect URL>\n  &code_challenge=<the challenge>\n  &code_challenge_method=S256\n  &state=<the state value>\n```\n\n**2. The customer approves.** They sign in to Check Cherry, see your app's name and\nlogo, and see the full list of permissions you declared. They approve the whole list\nor cancel. Your app now appears on the customer's Integrations page.\n\n**3. Trade the code for a token.** We send the customer back to your redirect URL\nwith two query parameters: `code` and `state`. Check that `state` matches what you\nsaved. Then, from your server, make this request:\n\n```\nPOST https://www.checkcherry.com/oauth/token\nContent-Type: application/x-www-form-urlencoded\n\ngrant_type=authorization_code\n&code=<the code>\n&redirect_uri=<your redirect URL>\n&client_id=<your client id>\n&code_verifier=<the verifier you saved>\n```\n\nYou get back:\n\n```json\n{\n  \"access_token\": \"…\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600,\n  \"refresh_token\": \"…\",\n  \"scope\": \"lead_read lead_create\"\n}\n```\n\nSave both tokens for this customer. The access token is what you send with API\nrequests. It lasts one hour.\n\n**4. Get a new token when it expires.** Use the refresh token:\n\n```\nPOST https://www.checkcherry.com/oauth/token\n\ngrant_type=refresh_token\n&refresh_token=<the refresh token>\n&client_id=<your client id>\n```\n\nYou get back a new access token *and* a new refresh token. Save both; the old\nrefresh token stops working.\n\n**5. Disconnecting.** A customer can disconnect your app from their Integrations page\nat any time. Your next request returns `401`; stop calling the API for that customer.\nIf they want to come back, they connect again from step 1. To disconnect from your\nside, send `POST https://www.checkcherry.com/oauth/revoke` with `token` and\n`client_id`.\n\n## Making Requests\n\nOnce you have a token, requests work exactly as described in the\n[Business API reference](/api/docs). The short version:\n\n- Send JSON, with the `Content-Type: application/json` header.\n- Responses are [JSON:API](https://jsonapi.org/): a `data` object or array with\n  `attributes` and `relationships`.\n- Lists are paged. Pass `page` and `per`, and stop when `page` reaches\n  `meta.total_pages`.\n- Every endpoint lists the permission it needs. A request your app isn't permitted\n  to make returns `403`, and fields it isn't permitted to read (pricing, for example)\n  come back as `null`.\n\n**Rate limiting** — Typical usage will not hit a limit. If you do, Check Cherry\nreturns `429 Too Many Requests` with a `Retry-After` header. Wait that long and\ntry again.\n\n## What's New\n\nNew endpoints, new fields, and newly documented behavior are listed at\n[checkcherry.com/api/changelog](https://www.checkcherry.com/api/changelog).\n"},"paths":{},"servers":[{"url":"https://api.checkcherry.com"}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"For apps other businesses install. Authorization code grant with PKCE (S256); no client secret. See the App Platform guide at /api/docs?spec=app.","flows":{"authorizationCode":{"authorizationUrl":"https://www.checkcherry.com/oauth/authorize","tokenUrl":"https://www.checkcherry.com/oauth/token","refreshUrl":"https://www.checkcherry.com/oauth/token","scopes":{"event_create":"Create bookings","assigned_event_read":"View assigned bookings","assigned_event_read_pricing":"View pricing on assigned bookings","assigned_event_write":"Edit assigned bookings","unassigned_event_read":"View all bookings","unassigned_event_read_pricing":"View pricing on all bookings","unassigned_event_write":"Edit all bookings","unclaimed_bookings_read":"View unclaimed bookings","pending_review_bookings_read":"View bookings pending review","all_pending_staff_assignments_read":"View all staff assignments awaiting response","proposal_create":"Create proposals","proposal_read":"View proposals","proposal_write":"Edit proposals","lead_create":"Create leads","lead_read":"View leads","lead_write":"Edit leads","appointment_create":"Create appointments","assigned_appointment_read":"View assigned appointments","assigned_appointment_write":"Edit assigned appointments","unassigned_appointment_read":"View all appointments","unassigned_appointment_write":"Edit all appointments","expense_read":"View expenses","expense_create":"Create expenses","expense_write":"Edit expenses","own_staff_check_in_read_and_create":"View and record your own check-ins","own_staff_check_in_write":"Edit your own check-ins","all_staff_check_in_read":"View all staff check-ins, including location and notes","all_staff_check_in_write":"Edit all staff check-ins","offerings_read":"View packages, add-ons, and extras","offerings_write":"Edit packages, add-ons, and extras","employee_read":"View staff list","user_read":"View user details","media_library_read":"View media library","reports_read":"View reports","design_template_read":"View design templates","design_template_select":"Select design templates","user_appointment_calendar_read":"View appointment calendars","availability_read":"Check booking availability","planning_read":"View planning tools"}}}}}}}