{"openapi":"3.1.0","info":{"title":"DSS Public API","description":"Public OAuth 2.0 API for Digital Sea Service. See https://docs.digitalseaservice.com for the developer guide.","version":"1.0.0","contact":{"name":"DSS Developer Support","email":"admin@digitalseaservice.com","url":"https://docs.digitalseaservice.com"},"license":{"name":"Proprietary"},"termsOfService":"https://digitalseaservice.com/terms"},"paths":{"/oauth/authorize":{"get":{"tags":["oauth"],"summary":"Authorize Get","operationId":"authorize_get_oauth_authorize_get","parameters":[{"name":"response_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Type"}},{"name":"client_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"}},{"name":"redirect_uri","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Uri"}},{"name":"scope","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"code_challenge","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Challenge"}},{"name":"code_challenge_method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"S256","title":"Code Challenge Method"}},{"name":"user_hint","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Hint"}},{"name":"prompt","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["oauth"],"summary":"Authorize Post","operationId":"authorize_post_oauth_authorize_post","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_authorize_post_oauth_authorize_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/token":{"post":{"tags":["oauth"],"summary":"Token Endpoint","operationId":"token_endpoint_oauth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_token_endpoint_oauth_token_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/revoke":{"post":{"tags":["oauth"],"summary":"Revoke Endpoint","operationId":"revoke_endpoint_oauth_revoke_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_revoke_endpoint_oauth_revoke_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/oauth/userinfo":{"get":{"tags":["oauth"],"summary":"Userinfo Endpoint","operationId":"userinfo_endpoint_oauth_userinfo_get","responses":{"200":{"description":"Basic profile for the authenticated user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}}}}},"/v1/me":{"get":{"tags":["v1"],"summary":"Get the authenticated user's profile","operationId":"get_me_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"description":"`invalid_token` — bearer token missing, malformed, expired, or revoked.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — the token lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"`not_found` — no matching record for the authenticated user.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["profile:read"]},{"bearerAuth":[]}]}},"/v1/me/sea-time":{"get":{"tags":["sea-time"],"summary":"Get aggregate sea-time totals","operationId":"get_sea_time_v1_me_sea_time_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeaTimeResponse"}}}},"304":{"description":"Resource has not changed since the conditional header."},"401":{"description":"`invalid_token` — bearer token missing, malformed, expired, or revoked.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — the token lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"`not_found` — no matching record for the authenticated user.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["seatime:read"]},{"bearerAuth":[]}]}},"/v1/me/sea-time/recent":{"get":{"tags":["sea-time"],"summary":"Get the rolling 12-month sea-time trend","operationId":"get_sea_time_recent_v1_me_sea_time_recent_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeaTimeRecentResponse"}}}},"304":{"description":"Resource has not changed since the conditional header."},"401":{"description":"`invalid_token` — bearer token missing, malformed, expired, or revoked.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — the token lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"`not_found` — no matching record for the authenticated user.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["seatime:read"]},{"bearerAuth":[]}]}},"/v1/me/vessels":{"get":{"tags":["vessels"],"summary":"List the authenticated user's vessel history","operationId":"list_vessels_v1_me_vessels_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor from a prior response.","title":"Cursor"},"description":"Opaque cursor from a prior response."},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Page size; max 200.","title":"Limit"},"description":"Page size; max 200."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VesselsResponse"}}}},"304":{"description":"Resource has not changed since the conditional header."},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — bearer token missing, malformed, expired, or revoked.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — the token lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"400":{"description":"`invalid_request` — a query parameter (e.g. cursor) was malformed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["vessels:read"]},{"bearerAuth":[]}]}},"/v1/webhooks/test":{"get":{"tags":["webhooks"],"summary":"Fire a webhook.test event to your registered URL","operationId":"fire_test_webhook_v1_webhooks_test_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResponse"}}}},"401":{"description":"`invalid_token` — bearer token missing, malformed, expired, or revoked.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`partner_suspended` — the calling partner has been suspended.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"`not_found` — the partner record backing the token was not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"`no_webhook_configured` — no webhook URL or signing secret is registered.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearerAuth":[]},{"oauth2":[]}]}},"/v1/partners/sponsorships":{"post":{"tags":["partners"],"summary":"Provision a crew member into a sponsored seat","description":"Auto-provision the account+vessel and grant Premium in one call (JIT).","operationId":"create_sponsorship_v1_partners_sponsorships_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSponsorshipRequest"}}}},"responses":{"200":{"description":"Idempotent replay — an open seat already existed for this email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSponsorshipResponse"}}}},"201":{"description":"A new sponsored member was provisioned and granted Premium."},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — partner suspended, or this endpoint is not available to the calling partner.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]},"get":{"tags":["partners"],"summary":"List this partner's sponsored seats","description":"Return a keyset-paginated, partner-scoped roster (newest first).","operationId":"list_sponsorships_v1_partners_sponsorships_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status.","title":"Status"},"description":"Filter by status."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Page size (max 200).","default":50,"title":"Limit"},"description":"Page size (max 200)."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor from a prior page.","title":"Cursor"},"description":"Opaque cursor from a prior page."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SponsorshipList"}}}},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — partner suspended, or this endpoint is not available to the calling partner.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]}},"/v1/partners/sponsorships/{sponsorship_id}":{"get":{"tags":["partners"],"summary":"Get one sponsored seat","description":"Fetch a single seat; a cross-partner id resolves to 404 (not 403).","operationId":"get_sponsorship_v1_partners_sponsorships__sponsorship_id__get","parameters":[{"name":"sponsorship_id","in":"path","required":true,"schema":{"type":"string","title":"Sponsorship Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SponsorshipItem"}}}},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — partner suspended, or this endpoint is not available to the calling partner.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]},"delete":{"tags":["partners"],"summary":"Remove a sponsored seat","description":"Remove a seat — downgrades the crew member to Free immediately.\n\nPartner-scoped: a cross-partner id resolves to 404 before any teardown.","operationId":"delete_sponsorship_v1_partners_sponsorships__sponsorship_id__delete","parameters":[{"name":"sponsorship_id","in":"path","required":true,"schema":{"type":"string","title":"Sponsorship Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteSponsorshipResponse"}}}},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — partner suspended, or this endpoint is not available to the calling partner.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]}},"/v1/partners/sponsorships/reconcile":{"post":{"tags":["partners"],"summary":"Reconcile seats against the partner's authoritative active list","description":"Cancel seats the partner no longer lists (guarded, dry-run by default).\n\nPartner-scoped: only this partner's live seats are considered. Safety rails:\nan empty ``active_refs`` is a 400; a mass-cancel over the threshold is refused\nunless ``override_threshold`` is set; nothing is cancelled unless ``apply`` is\ntrue. See :func:`dss_api.sponsorship.roster.reconcile_roster`.","operationId":"reconcile_sponsorships_v1_partners_sponsorships_reconcile_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileRequest"}}}},"responses":{"200":{"description":"The reconcile diff (dry run, or the result of an applied cancel).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileResponse"}}}},"400":{"description":"active_refs was empty — rejected to prevent a cancel-all."},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"`insufficient_scope` — partner suspended, or this endpoint is not available to the calling partner.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]}},"/v1/partners/members/left":{"post":{"tags":["partners"],"summary":"Notify DSS that a YWC member has left","description":"Close James's billed seat when the member is no longer in YWC.","operationId":"member_left_v1_partners_members_left_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberLeftRequest"}}}},"responses":{"200":{"description":"Seat closed, or already closed (idempotent).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberLeftResponse"}}}},"400":{"description":"Neither user_id nor a resolvable external_ref was provided."},"403":{"description":"Caller is not Yacht Workers Council."},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"`service_unavailable` — the dashboard member-left call failed; retry with backoff.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]}},"/v1/partners/sso/tickets":{"post":{"tags":["partners"],"summary":"Mint a one-time DSS login URL for a Connected YWC member","description":"Issue a 60-second, single-use login ticket bound to this YWC consent.","operationId":"create_sso_ticket_v1_partners_sso_tickets_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoTicketRequest"}}}},"responses":{"200":{"description":"Ticket minted. Redirect the browser to login_url.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoTicketResponse"}}}},"400":{"description":"user_id was missing."},"403":{"description":"Caller is not YWC, or the member has no live Connect consent."},"422":{"description":"`invalid_request` — request validation failed; see the `errors` array.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ValidationProblemDetails"}}}},"401":{"description":"`invalid_token` — Basic credentials missing, malformed, or incorrect.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"`rate_limit_exceeded` — per-client request budget exhausted.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"`internal_error` — an unexpected error occurred; reference `instance`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"basicAuth":[]}]}}},"components":{"schemas":{"Body_authorize_post_oauth_authorize_post":{"properties":{"action":{"type":"string","title":"Action"},"client_id":{"type":"string","title":"Client Id"},"redirect_uri":{"type":"string","title":"Redirect Uri"},"response_type":{"type":"string","title":"Response Type","default":"code"},"scope":{"type":"string","title":"Scope","default":""},"state":{"type":"string","title":"State","default":""},"code_challenge":{"type":"string","title":"Code Challenge"},"code_challenge_method":{"type":"string","title":"Code Challenge Method","default":"S256"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"},"_admin_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admin Token"}},"type":"object","required":["action","client_id","redirect_uri","code_challenge"],"title":"Body_authorize_post_oauth_authorize_post"},"Body_revoke_endpoint_oauth_revoke_post":{"properties":{"token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"},"token_type_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token Type Hint"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"}},"type":"object","title":"Body_revoke_endpoint_oauth_revoke_post"},"Body_token_endpoint_oauth_token_post":{"properties":{"grant_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Grant Type"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"redirect_uri":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Uri"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Secret"},"code_verifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Verifier"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"},"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}},"type":"object","title":"Body_token_endpoint_oauth_token_post"},"CreateSponsorshipRequest":{"properties":{"email":{"type":"string","minLength":3,"title":"Email","description":"Crew member's email (normalised)."},"first_name":{"type":"string","maxLength":100,"minLength":1,"title":"First Name","description":"Crew member's first name."},"last_name":{"type":"string","maxLength":100,"minLength":1,"title":"Last Name","description":"Crew member's last name."},"position":{"type":"string","minLength":1,"title":"Position","description":"Crew rank/role for the account."},"vessel_imo":{"anyOf":[{"type":"string","pattern":"^\\d{7}$"},{"type":"null"}],"title":"Vessel Imo","description":"7-digit IMO of the vessel to track. **Optional** — a member between jobs, shoreside, or on a hull with no IMO still gets their account and Premium, with the seat reported as unresolved. Re-submit the same email later with an IMO to attach the vessel; that is a vessel move, not a second seat."},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Crew member's phone (E.164)."},"vessel_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vessel Name","description":"Vessel display name (optional)."},"join_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Join Date","description":"Crew join date on the vessel."},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref","description":"Partner's own opaque reference."}},"type":"object","required":["email","first_name","last_name","position"],"title":"CreateSponsorshipRequest","description":"Attach an existing DSS member to a sponsored Premium seat.\n\nThe email must already have a Digital Sea Service account (normal signup).\nNew members are not created here — send them to the signup URL in\n``account_requires_signup``. ``vessel_imo`` is optional.","example":{"email":"jane@example.com","external_ref":"ywc-beta-0042","first_name":"Jane","join_date":"2026-07-01T00:00:00Z","last_name":"Doe","phone":"+447700900123","position":"Chief Stewardess","vessel_imo":"9074729","vessel_name":"MY Example"}},"CreateSponsorshipResponse":{"properties":{"sponsorship_id":{"type":"string","title":"Sponsorship Id"},"status":{"type":"string","title":"Status"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id","description":"The member's DSS user id — the same id delivered in the ``data.user_id`` of ``user.sea_time.updated`` webhooks. Persist it to correlate future webhooks to your own member record. Null until the seat is active (e.g. an invited-but-unclaimed seat)."},"vessel_resolved":{"type":"boolean","title":"Vessel Resolved","description":"False when the IMO did not match a vessel (soft failure).","default":false},"claim_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claim Url","description":"Always null for JIT — there is no claim link."},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At","description":"Per-user sponsored term end (activated_at + term_months)."}},"type":"object","required":["sponsorship_id","status"],"title":"CreateSponsorshipResponse","description":"The provisioned seat — returned 201 on create, 200 on idempotent replay.","example":{"expires_at":"2027-07-24T09:00:00Z","sponsorship_id":"665f00000000000000000042","status":"active","user_id":"aQ0mtT8kRgVv7C3o1p2q3r4s5t6u","vessel_resolved":true}},"DeleteSponsorshipResponse":{"properties":{"sponsorship_id":{"type":"string","title":"Sponsorship Id"},"status":{"type":"string","title":"Status"}},"type":"object","required":["sponsorship_id","status"],"title":"DeleteSponsorshipResponse","description":"Confirmation that a seat was removed and the crew member downgraded.","example":{"sponsorship_id":"665f00000000000000000042","status":"cancelled"}},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MeResponse":{"properties":{"user_id":{"type":"string","title":"User Id","description":"Stable DSS user identifier."},"name":{"type":"string","title":"Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role","description":"The crew member's current rank/position."},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"Country of residence. Always ``null`` in V1 — DSS does not yet carry this on the user record. See docs/internal/data-model-gaps.md."},"photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Photo Url","description":"Profile photo URL. Always ``null`` in V1 — DSS stores avatars in a private bucket with no public URL. See docs/internal/data-model-gaps.md."},"record_updated_at":{"type":"string","format":"date-time","title":"Record Updated At"},"membership":{"$ref":"#/components/schemas/Membership","description":"The member's current DSS membership. Requires ``profile:read``."}},"type":"object","required":["user_id","name","record_updated_at","membership"],"title":"MeResponse","description":"The authenticated user's profile.","example":{"membership":{"expires_at":"2027-07-25T09:14:00Z","since":"2026-07-25","source":"sponsored","sponsored_by_you":true,"tier":"premium"},"name":"Alex Crew","record_updated_at":"2026-05-26T09:14:00Z","role":"Chief Officer","user_id":"sFmjAD7I8bQexmTiTbZZQwq10X43"}},"MemberLeftRequest":{"properties":{"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id","description":"DSS user id from Connect (Firebase uid). Preferred."},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref","description":"Partner's own id, e.g. ywc-user-123. Used if user_id is omitted."},"reason":{"anyOf":[{"type":"string","enum":["account_deleted","membership_lapsed"]},{"type":"null"}],"title":"Reason","description":"Why they left. Both values close the billed seat the same way."}},"type":"object","title":"MemberLeftRequest","description":"Tell DSS this member is no longer in the partner's system.","example":{"external_ref":"ywc-user-123","reason":"membership_lapsed","user_id":"aQ0mtT8kRgVv7C3o1p2q3r4s5t6u"}},"MemberLeftResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"ended":{"type":"boolean","title":"Ended","description":"True when an open billed seat was closed."},"downgraded":{"type":"boolean","title":"Downgraded","description":"True when sponsored Crew Premium was dropped (false if already self-pay)."}},"type":"object","required":["user_id","ended","downgraded"],"title":"MemberLeftResponse","description":"Confirmation that DSS processed the leave (idempotent).","example":{"downgraded":true,"ended":true,"user_id":"aQ0mtT8kRgVv7C3o1p2q3r4s5t6u"}},"Membership":{"properties":{"tier":{"type":"string","title":"Tier","description":"``\"premium\"`` or ``\"free\"``."},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"How Premium is paid for: ``self`` (the member's own subscription), ``sponsored`` (a partner pays for the seat), or ``vessel`` (the member's yacht covers the crew). ``null`` when the member is Free."},"since":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since","description":"Date Premium began, ``YYYY-MM-DD``. ``null`` when the member is Free."},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At","description":"When a sponsored seat's term ends. Present only when YOU sponsor this member; ``null`` otherwise."},"sponsored_by_you":{"type":"boolean","title":"Sponsored By You","description":"True when the sponsoring partner is you. Members sponsored by a different partner report ``source: \"sponsored\"`` but never name that partner.","default":false}},"type":"object","required":["tier"],"title":"Membership","description":"The crew member's current DSS membership.\n\nLets a partner tell whether a member already holds Premium — without it, a\nmirrored \"upgrade\" prompt stays visible even to members the partner is\nsponsoring. Computed by the DSS dashboard, so vessel-covered Premium counts;\nreading the stored subscription tier alone would report those members Free."},"ReconcileRequest":{"properties":{"active_refs":{"items":{"type":"string"},"type":"array","title":"Active Refs","description":"Partner's authoritative list of active member emails / external refs."},"apply":{"type":"boolean","title":"Apply","description":"False = dry run (default). True = actually cancel the diff.","default":false},"max_cancel":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Max Cancel","description":"Hard ceiling on cancellations; exceeding it trips the threshold guard."},"override_threshold":{"type":"boolean","title":"Override Threshold","description":"Apply even when the mass-cancel threshold guard trips.","default":false}},"type":"object","required":["active_refs"],"title":"ReconcileRequest","description":"Reconcile DSS seats against the partner's authoritative active-member list.\n\n``active_refs`` is the partner's own list of currently-active member\nidentifiers (each matched against a seat's ``email`` AND ``external_ref``).\nAn **empty** list is rejected (400) so a bad/empty export can never be read\nas \"cancel everyone\". By default this is a DRY RUN (``apply=false``): the diff\nis returned and nothing is cancelled. A mass-cancel that exceeds ``max_cancel``\n(or the default safety fraction) is refused unless ``override_threshold`` is\ntrue.","example":{"active_refs":["jane@example.com","ywc-beta-0042"],"apply":false,"max_cancel":25,"override_threshold":false}},"ReconcileResponse":{"properties":{"active_seats":{"type":"integer","title":"Active Seats"},"to_cancel":{"items":{"$ref":"#/components/schemas/ReconcileToCancelItem"},"type":"array","title":"To Cancel"},"missing_refs":{"items":{"type":"string"},"type":"array","title":"Missing Refs"},"applied":{"type":"boolean","title":"Applied"},"cancelled_count":{"type":"integer","title":"Cancelled Count"},"threshold_exceeded":{"type":"boolean","title":"Threshold Exceeded"}},"type":"object","required":["active_seats","to_cancel","missing_refs","applied","cancelled_count","threshold_exceeded"],"title":"ReconcileResponse","description":"The reconcile diff plus what (if anything) was applied.","example":{"active_seats":42,"applied":false,"cancelled_count":0,"missing_refs":["newjoiner@example.com"],"threshold_exceeded":false,"to_cancel":[{"email":"gone@example.com","sponsorship_id":"665f00000000000000000042"}]}},"ReconcileToCancelItem":{"properties":{"sponsorship_id":{"type":"string","title":"Sponsorship Id"},"email":{"type":"string","title":"Email"}},"type":"object","required":["sponsorship_id","email"],"title":"ReconcileToCancelItem","description":"One seat the partner no longer lists (a cancel candidate)."},"SeaTimeRecentResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"months":{"items":{"$ref":"#/components/schemas/_RecentMonth"},"type":"array","title":"Months","description":"Most-recent month first; max 12."},"record_updated_at":{"type":"string","format":"date-time","title":"Record Updated At"}},"type":"object","required":["user_id","months","record_updated_at"],"title":"SeaTimeRecentResponse","description":"Rolling 12-month trend of declared sea time.","example":{"months":[{"days_at_sea":18,"month":"2026-05","nautical_miles":1240},{"days_at_sea":22,"month":"2026-04","nautical_miles":1480}],"record_updated_at":"2026-05-22T14:21:00Z","user_id":"65a1f0e2c3b4d5e6f7a8b9c0"}},"SeaTimeResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"totals":{"$ref":"#/components/schemas/_DeclaredTotals"},"verified":{"$ref":"#/components/schemas/_VerifiedTotals"},"by_role":{"items":{"$ref":"#/components/schemas/_RoleBreakdown"},"type":"array","title":"By Role"},"record_updated_at":{"type":"string","format":"date-time","title":"Record Updated At"}},"type":"object","required":["user_id","totals","verified","by_role","record_updated_at"],"title":"SeaTimeResponse","description":"Aggregate sea-time totals for the authenticated user.","example":{"by_role":[{"days":320,"role":"Deckhand"},{"days":480,"role":"Bosun"},{"days":1042,"role":"Mate"}],"record_updated_at":"2026-05-22T14:21:00Z","totals":{"days_at_sea":1842,"nautical_miles":87423,"vessels_served":14,"years_active":6.2},"user_id":"65a1f0e2c3b4d5e6f7a8b9c0","verified":{"days_at_sea":1680,"nautical_miles":79215}}},"SponsorshipItem":{"properties":{"sponsorship_id":{"type":"string","title":"Sponsorship Id"},"email":{"type":"string","title":"Email"},"crew_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crew Name"},"status":{"type":"string","title":"Status"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id","description":"The member's DSS user id — the same id delivered in ``user.sea_time.updated`` webhooks. Null until the seat is active."},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref"},"invited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Invited At"},"activated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Activated At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["sponsorship_id","email","status"],"title":"SponsorshipItem","description":"Public projection of one sponsored seat — no token hash, no Stripe ids.","example":{"activated_at":"2026-07-04T10:30:00Z","crew_name":"Jane Doe","email":"jane@example.com","expires_at":"2027-07-04T10:30:00Z","external_ref":"ywc-beta-0042","invited_at":"2026-07-03T09:00:00Z","sponsorship_id":"665f00000000000000000042","status":"active"}},"SponsorshipList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SponsorshipItem"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"SponsorshipList","description":"A page of sponsorships plus the opaque cursor for the next page.","example":{"items":[{"activated_at":"2026-07-04T10:30:00Z","crew_name":"Jane Doe","email":"jane@example.com","expires_at":"2027-07-04T10:30:00Z","external_ref":"ywc-beta-0042","invited_at":"2026-07-03T09:00:00Z","sponsorship_id":"665f00000000000000000042","status":"active"}]}},"SsoTicketRequest":{"properties":{"user_id":{"type":"string","minLength":1,"title":"User Id","description":"DSS user id from Connect (Firebase uid)."}},"type":"object","required":["user_id"],"title":"SsoTicketRequest","description":"Ask DSS for a one-time login URL for an already-Connected member.","example":{"user_id":"aQ0mtT8kRgVv7C3o1p2q3r4s5t6u"}},"SsoTicketResponse":{"properties":{"login_url":{"type":"string","title":"Login Url"},"expires_in":{"type":"integer","title":"Expires In","description":"Seconds until the ticket stops working."}},"type":"object","required":["login_url","expires_in"],"title":"SsoTicketResponse","description":"Redirect the member's browser to ``login_url`` immediately.","example":{"expires_in":60,"login_url":"https://app.digitalseaservice.com/auth/partner?ticket=abc"}},"TestResponse":{"properties":{"event_id":{"type":"string","title":"Event Id"},"delivery_id":{"type":"string","title":"Delivery Id"},"target_url":{"type":"string","title":"Target Url"}},"type":"object","required":["event_id","delivery_id","target_url"],"title":"TestResponse","description":"Result of firing a ``webhook.test`` event.","example":{"delivery_id":"dlv_77f1bb31c0c64e6db4f5e8a9c2d3e4f5","event_id":"evt_3f4a9c8e2b1d4f5a8c9e0d1f2a3b4c5d","target_url":"https://yachtworkerscouncil.com/integrations/dss/webhook"}},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VesselsResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"vessels":{"items":{"$ref":"#/components/schemas/_VesselPeriod"},"type":"array","title":"Vessels"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Opaque cursor for the next page. ``null`` when the page is the last one."},"record_updated_at":{"type":"string","format":"date-time","title":"Record Updated At","description":"Most-recently-updated crew-list record for the user. Same value across every page of a stable scan — drives the page-stable ``ETag``."}},"type":"object","required":["user_id","vessels","record_updated_at"],"title":"VesselsResponse","description":"Page of vessel periods for the authenticated user.","example":{"next_cursor":"eyJsYXN0X2lkIjoiMDFIVjlYS...","record_updated_at":"2026-05-22T14:21:00Z","user_id":"65a1f0e2c3b4d5e6f7a8b9c0","vessels":[{"days":99,"id":"69961ffbbd7419b471faab60","imo":"1012725","name":"M/V Endeavour","nautical_miles":4280,"period_end":"2025-04-20T00:00:00Z","period_start":"2025-01-12T00:00:00Z","role":"Chief Officer"}]}},"_DeclaredTotals":{"properties":{"days_at_sea":{"type":"integer","minimum":0.0,"title":"Days At Sea","description":"Total days the crew has logged at sea."},"nautical_miles":{"type":"integer","minimum":0.0,"title":"Nautical Miles","description":"Total nautical miles travelled."},"vessels_served":{"type":"integer","minimum":0.0,"title":"Vessels Served","description":"Distinct vessels served."},"years_active":{"type":"number","minimum":0.0,"title":"Years Active","description":"Earliest-to-latest span in years."}},"type":"object","required":["days_at_sea","nautical_miles","vessels_served","years_active"],"title":"_DeclaredTotals","description":"Crew-declared aggregate sea time.","example":{"days_at_sea":1842,"nautical_miles":87423,"vessels_served":14,"years_active":6.2}},"_RecentMonth":{"properties":{"month":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","title":"Month","description":"ISO year-month."},"days_at_sea":{"type":"integer","minimum":0.0,"title":"Days At Sea"},"nautical_miles":{"type":"integer","minimum":0.0,"title":"Nautical Miles"}},"type":"object","required":["month","days_at_sea","nautical_miles"],"title":"_RecentMonth","description":"One month's contribution to the rolling 12-month trend.","example":{"days_at_sea":18,"month":"2026-05","nautical_miles":1240}},"_RoleBreakdown":{"properties":{"role":{"type":"string","title":"Role"},"days":{"type":"integer","minimum":0.0,"title":"Days"}},"type":"object","required":["role","days"],"title":"_RoleBreakdown","description":"Days at sea served in a single role.","example":{"days":480,"role":"Bosun"}},"_VerifiedTotals":{"properties":{"days_at_sea":{"type":"integer","minimum":0.0,"title":"Days At Sea"},"nautical_miles":{"type":"integer","minimum":0.0,"title":"Nautical Miles"}},"type":"object","required":["days_at_sea","nautical_miles"],"title":"_VerifiedTotals","description":"Independently confirmed subset of the declared totals.","example":{"days_at_sea":1680,"nautical_miles":79215}},"_VesselPeriod":{"properties":{"id":{"type":"string","title":"Id","description":"Stable identifier for this vessel period (crew-list id)."},"name":{"type":"string","title":"Name"},"imo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Imo","description":"IMO number as a string when DSS holds it, else ``null``."},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role","description":"Rank/position served in this period."},"period_start":{"type":"string","format":"date-time","title":"Period Start"},"period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period End","description":"``null`` while still aboard."},"days":{"type":"integer","minimum":0.0,"title":"Days","description":"Qualifying sea-service days logged in the period."},"nautical_miles":{"type":"integer","minimum":0.0,"title":"Nautical Miles"}},"type":"object","required":["id","name","period_start","days","nautical_miles"],"title":"_VesselPeriod","description":"A single period the crew member served on a vessel.","example":{"days":99,"id":"69961ffbbd7419b471faab60","imo":"1012725","name":"M/V Endeavour","nautical_miles":4280,"period_end":"2025-04-20T00:00:00Z","period_start":"2025-01-12T00:00:00Z","role":"Chief Officer"}},"ProblemDetails":{"type":"object","description":"RFC 7807 Problem Details. Returned with the `application/problem+json` content type on every resource (`/v1/*`) error.","properties":{"type":{"type":"string","format":"uri","description":"Stable URL identifying the error type; resolves to its docs page."},"title":{"type":"string","description":"Short, human-readable summary of the error type."},"status":{"type":"integer","description":"HTTP status code."},"detail":{"type":"string","description":"Explanation specific to this occurrence."},"instance":{"type":"string","description":"Request correlation id; matches the `X-Request-Id` header."}},"required":["type","title","status","detail","instance"]},"ValidationProblemDetails":{"description":"Problem Details for a 422, carrying a per-field `errors` array.","allOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"type":"object","properties":{"errors":{"type":"array","description":"One entry per field that failed validation.","items":{"type":"object","additionalProperties":true}}}}]},"UserInfo":{"type":"object","description":"OIDC-style basic profile returned by `/oauth/userinfo`. Profile fields are present only when the token carries the `profile:read` scope.","properties":{"sub":{"type":"string","description":"Stable DSS user identifier (subject)."},"name":{"type":["string","null"]},"role":{"type":["string","null"]},"country":{"type":["string","null"]},"picture":{"type":["string","null"],"description":"Profile photo URL."}},"required":["sub"]}},"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 Authorization Code flow with PKCE. See the integration guide at docs.digitalseaservice.com for the full step-by-step.","flows":{"authorizationCode":{"authorizationUrl":"http://localhost:8080/oauth/authorize","tokenUrl":"http://localhost:8080/oauth/token","refreshUrl":"http://localhost:8080/oauth/token","scopes":{"profile:read":"Read the crew member's name, role, country, and photo URL.","seatime:read":"Read aggregate sea-time totals and the 12-month trend.","vessels:read":"Read the crew member's vessel history."}}}},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Opaque"},"basicAuth":{"type":"http","scheme":"basic","description":"HTTP Basic for `/v1/partners/*`. Username is the partner `client_id`; password is the `client_secret`."}}},"servers":[{"url":"https://api.digitalseaservice.com","description":"Production"},{"url":"https://api.dev.digitalseaservice.com","description":"Sandbox (dev)"}]}