openapi: 3.0.3 info: title: TutorCruncher API description: >- REST API for TutorCruncher, tutoring business management software for agencies, companies, and independent tutors. The API exposes the core domain - clients, recipients (students), contractors (tutors), agents, services (jobs), appointments (lessons), invoices, payment orders, proforma invoices, ad hoc charges, and reference data - plus HTTP webhooks for event notifications. Base URL: https://app.tutorcruncher.com/api/. Authentication uses a private API key (found under Integrations) sent in the Authorization header as `token `. All list endpoints are paginated with up to 100 objects per page and return `count`, `next`, `previous`, and `results`. Requests are rate limited to 100 per minute. This document targets API v2 (v1 was deprecated 2025-07-03); in v2, users are updated by ID (for example `POST /api/clients/{id}/`) rather than by email. Note: TutorCruncher's "Socket" is a JavaScript embed (https://cdn.tutorcruncher.com/socket/latest/socket.js) for publishing public tutor and lesson listings on a website; it is not a WebSocket API and is not modeled here. Event delivery is via HTTP webhooks. version: '2.0' contact: name: TutorCruncher url: https://tutorcruncher.com license: name: API documentation - TutorCruncher Terms url: https://tutorcruncher.com/terms-and-conditions servers: - url: https://app.tutorcruncher.com/api description: TutorCruncher API security: - tokenAuth: [] tags: - name: Clients description: Paying customers (parents or organizations). - name: Recipients description: Students who receive tutoring. - name: Contractors description: Tutors who deliver lessons. - name: Agents description: Affiliates / agents. - name: Services description: Services (jobs) tying recipients and contractors together. - name: Appointments description: Appointments (individual lessons / sessions). - name: Invoices description: Client invoices and payment. - name: Payments description: Payment orders, proforma invoices, and ad hoc charges. - name: Reference description: Reference data - subjects, countries, categories, action types. - name: Webhooks description: Webhook event catalog (action types). paths: /clients/: get: operationId: listClients tags: [Clients] summary: List clients parameters: - $ref: '#/components/parameters/Page' responses: '200': description: Paginated list of clients. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createClient tags: [Clients] summary: Create a client requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Client' responses: '201': description: Client created. '401': $ref: '#/components/responses/Unauthorized' /clients/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getClient tags: [Clients] summary: Retrieve a client responses: '200': description: A client. content: application/json: schema: $ref: '#/components/schemas/Client' '404': $ref: '#/components/responses/NotFound' post: operationId: updateClient tags: [Clients] summary: Update a client description: In API v2, clients are updated by ID via POST. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Client' responses: '200': description: Client updated. delete: operationId: deleteClient tags: [Clients] summary: Delete a client responses: '204': description: Client deleted. /recipients/: get: operationId: listRecipients tags: [Recipients] summary: List recipients (students) parameters: - $ref: '#/components/parameters/Page' responses: '200': description: Paginated list of recipients. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createRecipient tags: [Recipients] summary: Create a recipient requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Recipient' responses: '201': description: Recipient created. /recipients/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getRecipient tags: [Recipients] summary: Retrieve a recipient responses: '200': description: A recipient. content: application/json: schema: $ref: '#/components/schemas/Recipient' post: operationId: updateRecipient tags: [Recipients] summary: Update a recipient requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Recipient' responses: '200': description: Recipient updated. delete: operationId: deleteRecipient tags: [Recipients] summary: Delete a recipient responses: '204': description: Recipient deleted. /contractors/: get: operationId: listContractors tags: [Contractors] summary: List contractors (tutors) parameters: - $ref: '#/components/parameters/Page' responses: '200': description: Paginated list of contractors. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createContractor tags: [Contractors] summary: Create a contractor requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Contractor' responses: '201': description: Contractor created. /contractors/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getContractor tags: [Contractors] summary: Retrieve a contractor responses: '200': description: A contractor. content: application/json: schema: $ref: '#/components/schemas/Contractor' post: operationId: updateContractor tags: [Contractors] summary: Update a contractor requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Contractor' responses: '200': description: Contractor updated. delete: operationId: deleteContractor tags: [Contractors] summary: Delete a contractor responses: '204': description: Contractor deleted. /contractors/{id}/availability/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getContractorAvailability tags: [Contractors] summary: Get contractor availability responses: '200': description: Availability slots for the contractor. /public-contractors/: get: operationId: listPublicContractors tags: [Contractors] summary: List public contractor profiles description: Read-only public tutor profiles for website listings. responses: '200': description: Paginated list of public contractor profiles. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' /agents/: get: operationId: listAgents tags: [Agents] summary: List agents (affiliates) responses: '200': description: Paginated list of agents. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createAgent tags: [Agents] summary: Create an agent responses: '201': description: Agent created. /agents/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getAgent tags: [Agents] summary: Retrieve an agent responses: '200': description: An agent. /services/: get: operationId: listServices tags: [Services] summary: List services (jobs) parameters: - $ref: '#/components/parameters/Page' responses: '200': description: Paginated list of services. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createService tags: [Services] summary: Create a service requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Service' responses: '201': description: Service created. /services/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getService tags: [Services] summary: Retrieve a service responses: '200': description: A service. content: application/json: schema: $ref: '#/components/schemas/Service' post: operationId: updateService tags: [Services] summary: Update a service responses: '200': description: Service updated. delete: operationId: deleteService tags: [Services] summary: Delete a service responses: '204': description: Service deleted. /services/{id}/add-contractor/: parameters: - $ref: '#/components/parameters/Id' post: operationId: addServiceContractor tags: [Services] summary: Add a contractor to a service responses: '200': description: Contractor added. /services/{id}/remove-contractor/: parameters: - $ref: '#/components/parameters/Id' post: operationId: removeServiceContractor tags: [Services] summary: Remove a contractor from a service responses: '200': description: Contractor removed. /services/{id}/add-recipient/: parameters: - $ref: '#/components/parameters/Id' post: operationId: addServiceRecipient tags: [Services] summary: Add a recipient to a service responses: '200': description: Recipient added. /services/{id}/remove-recipient/: parameters: - $ref: '#/components/parameters/Id' post: operationId: removeServiceRecipient tags: [Services] summary: Remove a recipient from a service responses: '200': description: Recipient removed. /appointments/: get: operationId: listAppointments tags: [Appointments] summary: List appointments (lessons) parameters: - $ref: '#/components/parameters/Page' responses: '200': description: Paginated list of appointments. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createAppointment tags: [Appointments] summary: Create an appointment requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Appointment' responses: '201': description: Appointment created. /appointments/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getAppointment tags: [Appointments] summary: Retrieve an appointment responses: '200': description: An appointment. content: application/json: schema: $ref: '#/components/schemas/Appointment' post: operationId: updateAppointment tags: [Appointments] summary: Update an appointment responses: '200': description: Appointment updated. delete: operationId: deleteAppointment tags: [Appointments] summary: Delete an appointment responses: '204': description: Appointment deleted. /invoices/: get: operationId: listInvoices tags: [Invoices] summary: List invoices parameters: - $ref: '#/components/parameters/Page' responses: '200': description: Paginated list of invoices. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createInvoice tags: [Invoices] summary: Create an invoice responses: '201': description: Invoice created. /invoices/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getInvoice tags: [Invoices] summary: Retrieve an invoice responses: '200': description: An invoice. content: application/json: schema: $ref: '#/components/schemas/Invoice' /invoices/{id}/take-payment/: parameters: - $ref: '#/components/parameters/Id' post: operationId: takeInvoicePayment tags: [Invoices] summary: Take payment for an invoice description: Charges the client's stored payment method against the invoice. responses: '200': description: Payment taken. /payment-orders/: get: operationId: listPaymentOrders tags: [Payments] summary: List payment orders (contractor payouts) responses: '200': description: Paginated list of payment orders. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' /payment-orders/{id}/: parameters: - $ref: '#/components/parameters/Id' get: operationId: getPaymentOrder tags: [Payments] summary: Retrieve a payment order responses: '200': description: A payment order. /payment-orders/{id}/take-payment/: parameters: - $ref: '#/components/parameters/Id' post: operationId: takePaymentOrderPayment tags: [Payments] summary: Take payment for a payment order responses: '200': description: Payment taken. /proforma-invoices/: get: operationId: listProformaInvoices tags: [Payments] summary: List proforma invoices (credit requests) responses: '200': description: Paginated list of proforma invoices. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createProformaInvoice tags: [Payments] summary: Create a proforma invoice responses: '201': description: Proforma invoice created. /proforma-invoices/{id}/take-payment/: parameters: - $ref: '#/components/parameters/Id' post: operationId: takeProformaPayment tags: [Payments] summary: Take payment for a proforma invoice responses: '200': description: Payment taken. /adhoccharges/: get: operationId: listAdHocCharges tags: [Payments] summary: List ad hoc charges responses: '200': description: Paginated list of ad hoc charges. content: application/json: schema: $ref: '#/components/schemas/PaginatedList' post: operationId: createAdHocCharge tags: [Payments] summary: Create an ad hoc charge responses: '201': description: Ad hoc charge created. /ahc-categories/: get: operationId: listAdHocChargeCategories tags: [Payments] summary: List ad hoc charge categories responses: '200': description: List of ad hoc charge categories. /subjects/: get: operationId: listSubjects tags: [Reference] summary: List subjects responses: '200': description: List of subjects. /countries/: get: operationId: listCountries tags: [Reference] summary: List countries responses: '200': description: List of countries. /contractor-skills/: get: operationId: listContractorSkills tags: [Reference] summary: List contractor skills responses: '200': description: List of contractor skills. /qualification-levels/: get: operationId: listQualificationLevels tags: [Reference] summary: List qualification levels responses: '200': description: List of qualification levels. /labels/: get: operationId: listLabels tags: [Reference] summary: List labels responses: '200': description: List of labels. /pipeline-stages/: get: operationId: listPipelineStages tags: [Reference] summary: List pipeline stages responses: '200': description: List of pipeline stages. /action-types/: get: operationId: listActionTypes tags: [Webhooks] summary: List webhook action types description: >- Returns the catalog of 150+ action types that can trigger a webhook - the `action` values delivered in the webhook `events` payload. responses: '200': description: List of action types. components: securitySchemes: tokenAuth: type: apiKey in: header name: Authorization description: 'Private API key sent as: Authorization: token ' parameters: Id: name: id in: path required: true description: The object ID. schema: type: integer Page: name: page in: query required: false description: Page number for paginated results (100 objects per page). schema: type: integer responses: Unauthorized: description: Missing or invalid API key. NotFound: description: Object not found. schemas: PaginatedList: type: object properties: count: type: integer next: type: string nullable: true previous: type: string nullable: true results: type: array items: type: object Client: type: object properties: id: type: integer first_name: type: string last_name: type: string email: type: string phone: type: string status: type: string pipeline_stage: type: integer nullable: true labels: type: array items: type: integer required: - last_name Recipient: type: object properties: id: type: integer first_name: type: string last_name: type: string email: type: string client: type: integer description: ID of the paying client this recipient belongs to. date_of_birth: type: string format: date required: - last_name Contractor: type: object properties: id: type: integer first_name: type: string last_name: type: string email: type: string status: type: string skills: type: array items: type: integer qualifications: type: array items: type: integer required: - last_name Service: type: object properties: id: type: integer name: type: string status: type: string dft_charge_type: type: string dft_charge_rate: type: string subject: type: integer nullable: true Appointment: type: object properties: id: type: integer service: type: integer start: type: string format: date-time finish: type: string format: date-time topic: type: string location: type: string nullable: true recipients: type: array items: type: integer contractors: type: array items: type: integer Invoice: type: object properties: id: type: integer client: type: integer display_id: type: string gross: type: string net: type: string tax: type: string status: type: string date_sent: type: string format: date-time nullable: true