service88 Ops

Service API

Service marketplace — bookings, providers, service types, and scheduling.

Queries

QUERY

adminServiceOrder

#

The service job behind an order, for the admin console. Addressed by **order** id rather than request id because that is what the console has: service jobs are listed through adminListOrders, which returns OrderEntity rows, and nothing exposed the way back to the request they were created from. requests.order_id has been written by selectOffer since orders existed and find_by_order_id has been on the repo since the cross-vertical cancellation flow needed it — only the read was missing. Returns null for an order with no service request behind it: an order of another kind, or one whose request was hard-deleted. That is a legitimate answer for a console that lists orders by kind and can be pointed at any id, not an error worth raising. Separate from serviceRequest(id:), which is scoped to the customer who raised the request and the providers bidding on it, and redacts the address for a provider who has not paid to unlock it. An admin is neither of those parties, so that query answers NotFound for them.

Argumente

  • orderId!
Gibt zurück
QUERY

adminServiceQuestions

#

Every question on a service, for the console's question builder. Named adminServiceQuestions, not serviceQuestions, because BrowseQuery already owns that name. Two resolvers declaring the same field on a MergedObject do not conflict loudly — one simply wins the merge, and the browse one did, so this query has been unreachable since it was written and the console had no way to read a *disabled* question or an isEnabled flag at all. The difference is not only the flag. BrowseQuestionResponse is the customer's view of a question; this returns the whole row, which is what an editor needs.

Argumente

  • serviceId!
  • includeDisabledBoolean
Gibt zurück[!]!
QUERY

availableRequests

#

Open leads I can bid on. serviceId narrows the board to one of my services. Omit it for the union across everything I offer — the provider home feed wants that, and used to fake it with one query per service stitched together on the client, which skewed paging whenever one of them failed.

Argumente

  • serviceId
  • pagination
Gibt zurück!
QUERY

browseCategories

#

Browse active service categories.

Argumente

  • parentId
Gibt zurück[!]!
QUERY

browseServices

#

Browse active services in a category.

Argumente

  • categoryId!
Gibt zurück[!]!
QUERY

creditPackages

#

Packages a provider can buy right now.

Gibt zurück[!]!
QUERY

myCreditBalance

#

How many credits I have left.

Gibt zurück!
QUERY

myCreditTransactions

#

My credit history, newest first.

Argumente

  • limitInt!

    Standard

    20
  • offsetInt!

    Standard

    0
Gibt zurück[!]!
QUERY

myOfferForRequest

#

My own response to one request — a quote, a call request, or a request for more information — or null if I have not responded. A provider's job screen needs their own offer beside the request: its status picks the primary action, and startedAt is what separates a booked job from one under way. Nothing addressed it by request, so the client paged myOffers looking for a match and stopped after three pages — past which a busy provider's own bid simply disappeared.

Argumente

  • requestId!
Gibt zurück
QUERY

myOffers

#

List my submitted offers. Takes pagination and returns page_info like every other list on the platform. It used to take bare limit/offset and return a plain array, which left the client with no total and no way to know whether another page existed.

Argumente

  • status
  • pagination
Gibt zurück!
QUERY

myProviderDayCounts

#

Jobs per day for the signed-in provider, for the home week strip. Days with no jobs are absent rather than returned as zero — the client knows which dates it asked for.

Argumente

  • from!
  • to!
Gibt zurück[!]!
QUERY

myProviderEarningsChart

#

The signed-in provider's earnings chart.

Argumente

  • timeframe!
Gibt zurück!
QUERY

myProviderProfile

#

Get my provider profile.

Gibt zurück
QUERY

myProviderServices

#

The services I offer, including any I have paused.

Gibt zurück[!]!
QUERY

myServiceRequests

#

List my service requests.

Argumente

  • status
  • pagination
Gibt zurück!
QUERY

mySkippedRequests

#

Leads I dismissed with skipRequest, newest dismissal first. availableRequests filters these out, so the Skipped tab had no source at all and could only show what the current session happened to remember. unskipRequest puts one back on the board.

Argumente

  • pagination
Gibt zurück!
QUERY

pendingServiceProviders

#

List providers pending approval.

Argumente

  • pagination
Gibt zurück!
QUERY

predefinedInfoQuestions

#

Questions a provider can ask about jobs for this service, so the app can render the checklist rather than a blank box.

Argumente

  • serviceId!
Gibt zurück[!]!
QUERY

requestInfoRequests

#

Every question asked about one request, oldest first. Readable by the customer who raised the request and by any provider who has responded to it. The provider's ask screen used to keep a session-local list that emptied on every reopen; the customer had no list at all.

Argumente

  • requestId!
Gibt zurück[!]!
QUERY

requestOffers

#

List offers for a service request (customer only). Bids on a request, ordered by sort. Defaults to RECOMMENDED, which uses the same scorer Quick Match uses — so the list the customer sees and the choice made on their behalf cannot disagree.

Argumente

  • requestId!
  • sort
Gibt zurück[!]!
QUERY

rootServiceCategories

#

List root-level service categories (no parent).

Argumente

  • includeInactiveBoolean
  • pagination
Gibt zurück!
QUERY

searchServices

#

Search live services by name or description, across every category. browse_services is category-scoped, so a customer could only find a trade by knowing which category it sits under. A query shorter than two characters returns nothing rather than most of the catalogue.

Argumente

  • queryString!
  • limitInt
Gibt zurück[!]!
QUERY

service

#

Get a service by ID.

Argumente

  • id!
Gibt zurück
QUERY

serviceCategories

#

List service categories with pagination.

Argumente

  • parentId
  • includeInactiveBoolean
  • pagination
Gibt zurück!
QUERY

serviceCategory

#

Get a service category by ID.

Argumente

  • id!
Gibt zurück
QUERY

serviceCreditPackages

#

Every package, including retired ones. Admin view.

Gibt zurück[!]!
QUERY

serviceCreditSettings

#

This workspace's credit policy. Returns the defaults when none has been configured.

Gibt zurück!
QUERY

serviceMarketplaceHealth

#

Service health check query.

Gibt zurückString!
QUERY

servicePriceAdjustments

#

Every extended-fee request on a job, newest first. Includes the refused and withdrawn ones on purpose: they are the record of what was asked for, and a customer looking at a job they argued about should be able to see the argument. Readable by the job's customer and by the provider who holds it.

Argumente

  • requestId!
Gibt zurück[!]!
QUERY

serviceProvider

#

Get a service provider by ID.

Argumente

  • id!
Gibt zurück
QUERY

serviceProviderCountNear

#

How many providers offer this service within reach of this location. Separate from the list so the header count does not pay to build and sort rows the screen never renders.

Argumente

  • serviceId!
  • latitudeFloat!
  • longitudeFloat!
Gibt zurückInt!
QUERY

serviceProviders

#

List service providers with pagination and filters.

Argumente

  • status
  • searchString
  • pagination
Gibt zurück!
QUERY

serviceProvidersNear

#

Providers who offer this service and can reach this location, nearest first.

Argumente

  • serviceId!
  • latitudeFloat!
  • longitudeFloat!
  • limitInt
Gibt zurück[!]!
QUERY

serviceQuestion

#

Get a service question by ID.

Argumente

  • id!
Gibt zurück
QUERY

serviceQuestions

#

Get questions for a service (for request form).

Argumente

  • serviceId!
Gibt zurück[!]!
QUERY

serviceRequest

#

One service request, by id. Readable by the customer who raised it and by a provider who has responded to it or can still bid on it; the address stays redacted for a provider who has neither unlocked the lead nor won the job. Both apps needed this and neither had it: the customer's detail screen was paging through myServiceRequests looking for one id, and the provider's job detail could not be rendered at all once a job left the open lead board.

Argumente

  • id!
Gibt zurück!
QUERY

servicesByCategory

#

List services by category with pagination.

Argumente

  • categoryId!
  • includeInactiveBoolean
  • pagination
Gibt zurück!
QUERY

serviceStats

#

Headline numbers for a service's detail screen.

Argumente

  • serviceId!
Gibt zurück!

Mutations

MUTATION

approveServiceProvider

#

Approve a service provider (set status to Active).

Argumente

  • input!
Gibt zurück!
MUTATION

askForInformation

#

Ask the customer for what you need before quoting.

Argumente

  • input!
Gibt zurück[!]!
MUTATION

cancelServiceFee

#

Take back a fee request the customer has not answered yet.

Argumente

  • adjustmentId!
Gibt zurück!
MUTATION

cancelServiceRequest

#

Cancel a service request.

Argumente

  • requestId!
Gibt zurück!
MUTATION

confirmCompletion

#

Customer confirms completion.

Argumente

  • requestId!
Gibt zurück!
MUTATION

confirmServiceCreditPurchase

#

Finish a purchase that needed 3DS. Safe to call more than once.

Argumente

  • purchaseId!
Gibt zurück!
MUTATION

confirmServicePayment3ds

#

Finish a card payment the customer had to authenticate (3DS). payServiceRequest hands back a client secret when the bank wants a challenge and leaves the job awaiting payment. This is what the client calls once the challenge is done — without it the customer authenticated and the booking stayed unpaid for ever. Safe to call twice: a payment already captured returns the job as it stands rather than charging again.

Argumente

  • input!
Gibt zurück!
MUTATION

createPushProvider

#

Create a push provider (FCM). Platform-owned providers require a platform admin; tenant-owned providers are scoped to the caller's tenant.

Argumente

  • input!
Gibt zurück!
MUTATION

createService

#

Create a new service.

Argumente

  • input!
Gibt zurück!
MUTATION

createServiceCategory

#

Create a new service category.

Argumente

  • input!
Gibt zurück!
MUTATION

createServiceCreditPackage

#

Argumente

  • input!
Gibt zurück!
MUTATION

createServiceQuestion

#

Create a new service question.

Argumente

  • input!
Gibt zurück!
MUTATION

createServiceRequest

#

Create a new service request.

Argumente

  • input!
Gibt zurück!
MUTATION

decideServiceFee

#

The customer's answer. Approving is the only thing that moves a job's total after the customer has been shown it, so it is deliberately a separate call from reading the request — and it is idempotent: the second answer is refused rather than applied.

Argumente

  • adjustmentId!
  • approvedBoolean!
Gibt zurück!
MUTATION

deletePushProvider

#

Delete a push provider.

Argumente

  • idString!
Gibt zurückBoolean!
MUTATION

deleteService

#

Delete a service (soft delete).

Argumente

  • id!
Gibt zurückBoolean!
MUTATION

deleteServiceCategory

#

Delete a service category (soft delete).

Argumente

  • id!
Gibt zurückBoolean!
MUTATION

deleteServiceCreditPackage

#

Retire a package. Past purchases keep referencing it.

Argumente

  • id!
Gibt zurückBoolean!
MUTATION

deleteServiceQuestion

#

Delete a service question.

Argumente

  • id!
Gibt zurückBoolean!
MUTATION

generateServiceQuestionTemplate

#

Ask the tenant's default LLM for a starter set of intake questions for a new service category. The admin reviews, edits, and accepts; this mutation does NOT persist the questions. Admin-only. Requires the tenant to have serviceQuestionGenEnabled turned on under Settings → AI Features and at least one configured AI provider with a remaining monthly budget.

Argumente

  • input!
Gibt zurück!
MUTATION

markServiceComplete

#

Provider marks a service as complete.

Argumente

  • requestId!
  • completionNotesString
Gibt zurück!
MUTATION

payServiceRequest

#

Pay for an accepted job.

Argumente

  • input!
Gibt zurück!
MUTATION

proposeServiceFee

#

Ask the customer to agree to an extended fee on a job in progress. One at a time per job: a second request while the first is unanswered is refused, because the customer would otherwise be agreeing to one of two live figures.

Argumente

  • input!
Gibt zurück!
MUTATION

purchaseServiceCreditPackage

#

Buy a credit package.

Argumente

  • input!
Gibt zurück!
MUTATION

raiseDispute

#

Customer raises a dispute.

Argumente

  • requestId!
  • reasonString!
Gibt zurück!
MUTATION

recordServiceCashPayment

#

Provider confirms cash changed hands. Cash-only — card and wallet settle through the PSP.

Argumente

  • requestId!
Gibt zurück!
MUTATION

registerAsProvider

#

Register as a service provider.

Argumente

  • input!
Gibt zurück!
MUTATION

reorderServiceQuestions

#

Reorder service questions.

Argumente

  • input!
Gibt zurückBoolean!
MUTATION

respondToInformationRequest

#

Answer one of a provider's questions.

Argumente

  • infoRequestId!
  • responseString!
Gibt zurück!
MUTATION

selectOffer

#

Select an offer for a service request. Select an offer for a service request. couponCode is optional and forgiving: a code that is invalid, expired, not applicable or under its minimum is ignored and the booking goes through at full price. Refusing the whole selection over a coupon would strand a customer who has already chosen and a provider who has already paid a credit to be chosen.

Argumente

  • offerId!
  • couponCodeString
Gibt zurück!
MUTATION

serviceMarketplacePing

#

Service health check mutation.

Gibt zurückString!
MUTATION

setDefaultPushProvider

#

Set a push provider as the default within its owner scope.

Argumente

  • idString!
Gibt zurückBoolean!
MUTATION

setMyProviderAvailability

#

Turn "Available to take jobs" on or off.

Argumente

  • onlineBoolean!
Gibt zurück!
MUTATION

setMyProviderServices

#

Replace the services you offer. Services you leave out are paused, not deleted, so their completed-job count and rating survive.

Argumente

  • input[!]!
Gibt zurück[!]!
MUTATION

skipRequest

#

"Not Interested" — dismiss a lead so it stops appearing in your list. Idempotent; call unskipRequest to bring it back.

Argumente

  • requestId!
  • reasonString
Gibt zurückBoolean!
MUTATION

startServiceJob

#

Provider marks the job as started. Records started_at on the accepted offer, which is what distinguishes a booked job from one under way.

Argumente

  • requestId!
Gibt zurück!
MUTATION

submitOffer

#

Submit an offer on a service request.

Argumente

  • input!
Gibt zurück!
MUTATION

suspendServiceProvider

#

Suspend a service provider.

Argumente

  • input!
Gibt zurück!
MUTATION

testPushProvider

#

Test a push provider. Without device_token it just verifies the credentials authenticate with Google; with a device_token it sends a real test notification to that device for an end-to-end check.

Argumente

  • idString!
  • deviceTokenString
Gibt zurück!
MUTATION

unlockRequest

#

Spend credits to see a lead's address, photos and contact details before quoting for it. Safe to call more than once — an already-open lead is not charged again.

Argumente

  • requestId!
Gibt zurück!
MUTATION

unskipRequest

#

Undo a dismissal.

Argumente

  • requestId!
Gibt zurückBoolean!
MUTATION

unsuspendServiceProvider

#

Unsuspend a service provider (set status back to Active).

Argumente

  • providerId!
Gibt zurück!
MUTATION

updateMyProviderProfile

#

Update provider profile.

Argumente

  • input!
Gibt zurück!
MUTATION

updatePushProvider

#

Update a push provider's name, credentials, or metadata.

Argumente

  • input!
Gibt zurück!
MUTATION

updateService

#

Update an existing service.

Argumente

  • input!
Gibt zurück!
MUTATION

updateServiceCategory

#

Update an existing service category.

Argumente

  • input!
Gibt zurück!
MUTATION

updateServiceCreditPackage

#

Argumente

  • input!
Gibt zurück!
MUTATION

updateServiceCreditSettings

#

Change the credit policy. Omitted fields keep their current value.

Argumente

  • input!
Gibt zurück!
MUTATION

updateServiceQuestion

#

Update an existing service question.

Argumente

  • input!
Gibt zurück!
MUTATION

withdrawOffer

#

Take back a bid the customer has not chosen yet. The credit it cost is **not** refunded: unlocking a lead reveals the address and contact details, and a refunded withdrawal would make "bid, read the lead, withdraw" a free way to browse the board. An accepted offer cannot be withdrawn — that is a booked job with an order behind it, and leaving one goes through cancellation.

Argumente

  • offerId!
Gibt zurück!