--- title: "Getting Started: Authentication & Request Headers" slug: "authentication" description: "Learn to set up Restaurant365 Public API access, manage tokens securely, and make your first successful API call with essential tips and guidelines." updated: 2026-09-08T17:58:25Z published: 2026-09-08T17:58:25Z canonical: "docs.restaurant365.com/authentication" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.restaurant365.com/llms.txt > Use this file to discover all available pages before exploring further. # Getting Started: Authentication & Request Headers Every request to the Restaurant365 Public API carries two pieces of information: who you are, and which customer instance you are acting on. This article shows you how to set those up and make your first successful call. > [!NOTE] > Early Adopter (Closed) > > The R365 Public API is currently available to a closed Early Adopter group. Restaurant365 is incorporating participant feedback before it opens access more broadly. Learn more about [requesting R365 Public API access](https://docs.restaurant365.com/apidocs/en/request-access). --- ## Before You Begin Restaurant365 provides a token and a customer instance value when [API access is set up](/developer-hub/apidocs/request-access#r365-public-api). | Value | Example | Identifies | | --- | --- | --- | | **Token** | `A1B2C3D4…-1` | Your application. Acts as your API key. | | **Customer instance** | `mycompanyco` | The Restaurant365 customer instance your requests read and write. | Store both values in your own secret manager before you start building. Treat the token like a password. --- ## Base URL and Versioning The R365 Public API base URL is: ```plaintext https://api.restaurant365.com/public ``` Paths follow the pattern `/v1/{domain}/{resource}`. For example: ```plaintext https://api.restaurant365.com/public/v1/core/locations https://api.restaurant365.com/public/v1/accounting/gl-accounts https://api.restaurant365.com/public/v1/labor/labor-punches ``` The `v1` segment identifies the current version of these endpoints. --- ## Required Headers Send both headers on every request, including `POST` and `PATCH`. | Header | Value | Description | | --- | --- | --- | | `Authorization` | `Bearer {token}` | Your token, prefixed with `Bearer` and a single space. | | `x-r365-context-tenant-id` | `{customer instance}` | The customer instance, exactly as provided. Lowercase, no spaces. | Write requests (`POST` and `PATCH`) also need: | Header | Value | | --- | --- | | `Content-Type` | `application/json` | Most tools set `Content-Type` for you. Postman adds it when you choose **Body → raw → JSON**, and HTTP libraries add it when you pass a JSON body. `curl` does not: `-d` sends `application/x-www-form-urlencoded` unless you set the header yourself. A write request without `Content-Type: application/json` returns `415 Unsupported Media Type`. Using the example values above, the completed headers look like this: ```plaintext Authorization: Bearer A1B2C3D4E5F6…-1 x-r365-context-tenant-id: mycompanyco Content-Type: application/json ``` > [!WARNING] > Common Header Mistakes > > Leaving out `Bearer `before the token, and using the customer's display name (for example, "My Company, LLC") instead of the customer instance value (for example, `mycompanyco`), are the most common causes of a failed request. --- ## Your First Request This call returns the locations in the customer instance. It is a safe read-only request and a good way to confirm your headers work. ```plaintext curl -sS -i \  -H "Authorization: Bearer A1B2C3D4E5F6…-1" \  -H "x-r365-context-tenant-id: mycompanyco" \  "https://api.restaurant365.com/public/v1/core/locations?pageSize=5" ``` A `200` response confirms both values are correct and your integration is connected. ### A Successful Response List endpoints return an `items` array and a `nextLink`: ```plaintext {  "items": [    { "id": "4a207100-d72f-4612-8dad-011e74b46bb0", "name": "Downtown", "number": "101" },    { "id": "6e6cfd04-0de5-e711-93ff-0cc47abcc4a5", "name": "Airport", "number": "102" }  ],  "nextLink": "https://api.restaurant365.com/public/v1/core/locations?pageSize=5&continuationToken=eyJ0b2tlbiI6…" } ``` List endpoints return one page of results at a time. - Set `pageSize` to control the number of results per page. The maximum is **250**. Omit it to use the endpoint default. - Follow `nextLink` exactly as returned to fetch the next page. It already contains the continuation token and the original filters — do not build continuation URLs manually. - Do not store a `nextLink` value to reuse later. Continuation tokens are short-lived. - When `nextLink` is `null`, the last page has been reached. Request `nextLink` with the same headers sent on the first call. ### A Write Request Send the body as JSON and add the `Content-Type` header. Batch write endpoints accept an array, even for a single item, and return `207 Multi-Status` with one entry in `results` per submitted item: ```plaintext curl -sS -i -X POST \  -H "Authorization: Bearer A1B2C3D4E5F6…-1" \  -H "x-r365-context-tenant-id: mycompanyco" \  -H "Content-Type: application/json" \  -d '{        "invoices": [          {            "invoiceNumber": "INV-1001",            "vendorId": "0f8fad5b-d9cb-469f-a165-70867728950e",            "locationId": "4a207100-d72f-4612-8dad-011e74b46bb0",            "documentDate": "2026-08-01",            "documentAmount": 249.50          }        ]      }' \  "https://api.restaurant365.com/public/v1/accounting/accounts-payable/invoices" ``` A `207` does not mean every item succeeded — check each entry: ```plaintext {  "results": [    { "id": "9b1c…", "invoiceNumber": "INV-1001", "status": "Success" }  ] } ``` Single-record endpoints — ones that take one object rather than an array — skip the batch envelope and return `200` or `201` directly instead of `207`. For example, creating a single GL account: ```plaintext curl -sS -i -X POST \  -H "Authorization: Bearer A1B2C3D4E5F6…-1" \  -H "x-r365-context-tenant-id: mycompanyco" \  -H "Content-Type: application/json" \  -d '{        "accountNumber": "6100",        "accountName": "Repairs and Maintenance"      }' \  "https://api.restaurant365.com/public/v1/accounting/gl-accounts" ``` A `201 Created` response returns the created record directly — there is no `results` array to check. --- ## Keeping Your Token Secure Store the token in a secret manager. Do not commit it to source control, and do not paste it into a support ticket, a browser URL, or a chat message. Send it in the `Authorization` header only. Your token carries the access granted to your integration. Request only the access your integration needs. Tokens can expire and can be rotated. Contact Restaurant365 Support to rotate a token or if you believe one has been exposed. Rotation invalidates the previous token immediately, so plan to deploy the new value at the same time. --- ## R365 Classic API Authentication > [!WARNING] > The R365 Classic API is a REST API. It is read-only. Existing integrations built on this surface continue to work as the company moves to the R365 Public API. The R365 Public API is currently an Early Adopter program, and acceptance is closed to new participants. The Classic API remains the production option until Public API access reopens more broadly. The authentication request generates the bearer token that will be passed with every subsequent request. Learn how to [request the UserName and Password required](/developer-hub/apidocs/request-access#r365-api-connector). The CURL commands below define an example request for Authentication: > [!NOTE] > **[YOUR-UNIQUE-CUSTOMER-URL]** represents the subdomain of your unique R365 database. This is the value that appears before '.[restaurant365.com](http://restaurant365.com)' when you are logged in to Restaurant365. > > i.e., [thedean.restaurant365.com](http://thedean.restaurant365.com) #### Request ```plaintext curl --request POST \ --url 'https://[YOUR-UNIQUE-CUSTOMER-URL].restaurant365.com/APIv1/Authenticate/JWT format=json' \ --header 'Content-Type: application/json' \ --data ' { "UserName":"yourUserName", "Password":"YourPassword" }' ``` #### Example Response: ```plaintext { "SessionId": "YourSessionId", "UserName": "YourUserName", "BearerToken": "YourBearerTokenReturned", "ResponseStatus": {} } ```