{"openapi":"3.1.0","info":{"title":"FromSunday.io Developer API","version":"1.0.0","description":"Limited-access API for authorized FromSunday.io Sales Preview automation. Developer keys are issued by platform administrators; this is not a general public church-content API.","contact":{"name":"FromSunday.io Support","email":"support@fromsunday.io","url":"https://fromsunday.io/contact"},"license":{"name":"Proprietary","url":"https://fromsunday.io/terms"}},"servers":[{"url":"https://fromsunday.io/api/developer/v1"}],"externalDocs":{"description":"Developer guide","url":"https://fromsunday.io/developers"},"security":[{"bearerAuth":[]}],"paths":{"/":{"get":{"operationId":"getDeveloperApiInfo","summary":"Read API version and discovery links","security":[],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{"$ref":"#/components/schemas/ApiInfoResult"},"error":{"type":"null"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/MissingApiKey"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"default":{"$ref":"#/components/responses/UnexpectedError"}}}},"/sales-previews":{"post":{"operationId":"createSalesPreview","summary":"Create a Sales Preview","description":"Requires sales_previews:create. The JSON idempotencyKey makes exact retries return the existing logical result.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSalesPreviewRequest"}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{"$ref":"#/components/schemas/CreateSalesPreviewResult"},"error":{"type":"null"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/MissingApiKey"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"default":{"$ref":"#/components/responses/UnexpectedError"}}}},"/sales-previews/{previewId}":{"get":{"operationId":"getSalesPreview","summary":"Read a Sales Preview","description":"Requires sales_previews:read. These trusted platform-admin credentials currently have platform-wide Sales Preview access by identifier.","parameters":[{"name":"previewId","in":"path","required":true,"description":"Sales Preview identifier returned by the create operation.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{"$ref":"#/components/schemas/SalesPreviewResult"},"error":{"type":"null"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/MissingApiKey"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"default":{"$ref":"#/components/responses/UnexpectedError"}}},"patch":{"operationId":"updateSalesPreview","summary":"Update approved Sales Preview metadata","description":"Requires sales_previews:update. Legacy keys carrying create, upload, and read scopes remain accepted by the current v1 implementation.","parameters":[{"name":"previewId","in":"path","required":true,"description":"Sales Preview identifier returned by the create operation.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSalesPreviewRequest"}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{"$ref":"#/components/schemas/SalesPreviewResult"},"error":{"type":"null"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/MissingApiKey"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"default":{"$ref":"#/components/responses/UnexpectedError"}}}},"/sales-previews/{previewId}/upload/init":{"post":{"operationId":"initializeSalesPreviewUpload","summary":"Initialize a sermon upload","description":"Requires sales_previews:upload. Returns the authorized upload target. Retry with the same JSON idempotencyKey for the same logical upload.","parameters":[{"name":"previewId","in":"path","required":true,"description":"Sales Preview identifier returned by the create operation.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadInitRequest"}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{"$ref":"#/components/schemas/UploadInitResult"},"error":{"type":"null"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/MissingApiKey"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"default":{"$ref":"#/components/responses/UnexpectedError"}}}},"/sales-previews/{previewId}/upload/complete":{"post":{"operationId":"completeSalesPreviewUpload","summary":"Complete a sermon upload and start processing","description":"Requires sales_previews:upload. The same developer key, preview ID, idempotencyKey, and initialized objectPath must be used.","parameters":[{"name":"previewId","in":"path","required":true,"description":"Sales Preview identifier returned by the create operation.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadCompleteRequest"}}}},"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"type":"object","required":["data","error"],"properties":{"data":{"$ref":"#/components/schemas/UploadCompleteResult"},"error":{"type":"null"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/MissingApiKey"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"},"default":{"$ref":"#/components/responses/UnexpectedError"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"FromSunday developer API key (fsdk_...)","description":"Send the raw key once in the Authorization header. Keys are created by a FromSunday.io platform administrator and are shown only once."}},"responses":{"ValidationError":{"description":"JSON body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"MissingApiKey":{"description":"The Authorization bearer credential is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"The credential is invalid, expired, revoked, or lacks the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"The requested Developer API resource or endpoint was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalError":{"description":"The operation failed on the server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"UnexpectedError":{"description":"Unexpected Developer API error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"ApiInfoResult":{"type":"object","required":["name","version","status","documentation","openapi"],"properties":{"name":{"type":"string"},"version":{"type":"string","enum":["v1"]},"status":{"type":"string","enum":["available"]},"documentation":{"type":"string","format":"uri"},"openapi":{"type":"string","format":"uri"}}},"CreateSalesPreviewResult":{"type":"object","required":["idempotencyKey","previewId","videoId","previewPath","previewExpiresAt"],"properties":{"idempotencyKey":{"type":"string"},"previewId":{"type":"string","format":"uuid"},"videoId":{"type":"string","format":"uuid"},"previewPath":{"type":"string","pattern":"^/da/preview/"},"previewExpiresAt":{"type":"string","format":"date-time"}}},"SalesPreviewResult":{"type":"object","required":["preview"],"properties":{"preview":{"$ref":"#/components/schemas/SalesPreview"}}},"SalesPreview":{"type":"object","required":["id","churchId","videoId","churchSlug","previewStatus","previewExpiresAt","createdAt","updatedAt","salesTracking","salesFollowUpTimeline","token","previewUrl","previewUrlUnavailableReason"],"properties":{"id":{"type":"string","format":"uuid"},"churchId":{"type":"string","format":"uuid"},"videoId":{"type":"string","format":"uuid"},"churchSlug":{"type":"string"},"displayChurchName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"previewStatus":{"type":"string"},"previewExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"revokedAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"deletedAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"activatedAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"sourceUrl":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}]},"sourceHost":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}]},"sourceProvider":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"contactEmail":{"anyOf":[{"type":"string","maxLength":320,"format":"email"},{"type":"null"}]},"contactPerson":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"contactPhone":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"country":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"denomination":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"churchWebsite":{"anyOf":[{"type":"string","maxLength":2048,"format":"uri"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"sermonTitle":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"speakerName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"sermonDate":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"salesTracking":{"type":"object","additionalProperties":true},"salesFollowUpTimeline":{"type":"array","items":{"type":"object"}},"token":{"type":"object","additionalProperties":true},"video":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"previewUrl":{"type":"null"},"previewUrlUnavailableReason":{"type":"string","enum":["raw_token_not_stored"]}}},"UploadInitResult":{"type":"object","required":["idempotencyKey","previewId","videoId","bucket","objectPath","uploadUrl","signedUpload","tusUploadUrl","mediaType"],"properties":{"idempotencyKey":{"type":"string"},"previewId":{"type":"string","format":"uuid"},"videoId":{"type":"string","format":"uuid"},"bucket":{"type":"string"},"objectPath":{"type":"string"},"uploadUrl":{"type":"string","format":"uri"},"signedUpload":{"type":"object","additionalProperties":true},"tusUploadUrl":{"type":"string","format":"uri"},"mediaType":{"type":"string","enum":["video","audio"]}}},"UploadCompleteResult":{"type":"object","required":["idempotencyKey","videoId","previewId","originalVideoUrl","workflowRunId"],"properties":{"idempotencyKey":{"type":"string"},"videoId":{"type":"string","format":"uuid"},"previewId":{"type":"string","format":"uuid"},"originalVideoUrl":{"type":"string","format":"uri"},"workflowRunId":{"type":"string"}}},"ErrorResponse":{"type":"object","required":["data","error"],"properties":{"data":{"type":"null"},"error":{"type":"object","required":["message","code"],"properties":{"message":{"type":"string"},"code":{"type":"string","examples":["VALIDATION_ERROR","MISSING_API_KEY","INVALID_API_KEY","INSUFFICIENT_SCOPE","INTERNAL_ERROR"]},"resolution":{"type":"string"}}}}},"CreateSalesPreviewRequest":{"type":"object","required":["idempotencyKey","churchName"],"properties":{"idempotencyKey":{"type":"string","minLength":8,"maxLength":160},"churchName":{"type":"string","minLength":1,"maxLength":200},"contactEmail":{"anyOf":[{"type":"string","maxLength":320,"format":"email"},{"type":"null"}]},"contactPerson":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"contactPhone":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"country":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"denomination":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"churchWebsite":{"anyOf":[{"type":"string","maxLength":2048,"format":"uri"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"sermonTitle":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"speakerName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"sermonDate":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"expiresInDays":{"type":"integer","minimum":1,"maximum":180,"default":90}}},"UpdateSalesPreviewRequest":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"churchName":{"type":"string","minLength":1,"maxLength":200},"contactEmail":{"anyOf":[{"type":"string","maxLength":320,"format":"email"},{"type":"null"}]},"contactPerson":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"contactPhone":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"denomination":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}]},"churchWebsite":{"anyOf":[{"type":"string","maxLength":2048,"format":"uri"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"sermonTitle":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"speakerName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"sermonDate":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"sentAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"lastCallAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"callNotes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"agreementStatus":{"type":"string","enum":["none","verbal","signed","declined"]},"agreementNotes":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"pipelineStage":{"type":"string","enum":["preview_created","preview_verified","preview_sent","followup_waiting","followup_snoozed","followup_done","won","lost","new","contacted","sent","reviewing","negotiating"]},"followUpAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"ownerName":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"nextAction":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}]},"emailStatus":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"emailRecipient":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}]},"emailSender":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"emailSubject":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"emailBody":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"emailApprovedAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"emailLoggedAt":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}]},"rescheduleReason":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"rescheduleNextAngle":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}]},"rescheduleNote":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"lostReason":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]}}},"UploadInitRequest":{"type":"object","required":["idempotencyKey","fileName","fileSize"],"properties":{"idempotencyKey":{"type":"string","minLength":8,"maxLength":160},"fileName":{"type":"string","minLength":1,"maxLength":512,"description":"Allowed extensions: .mp4, .mov, .avi, .webm, .mp3, .wav, .aac, .m4a, .flac, and .ogg (case-insensitive)."},"fileSize":{"type":"integer","minimum":1,"maximum":6979321856,"description":"Video files may be at most 6,979,321,856 bytes; audio files may be at most 1,073,741,824 bytes."},"contentType":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}]},"language":{"type":"string","enum":["da","en","no","de"],"default":"da"}}},"UploadCompleteRequest":{"allOf":[{"$ref":"#/components/schemas/UploadInitRequest"},{"type":"object","required":["objectPath"],"properties":{"objectPath":{"type":"string","minLength":1,"maxLength":2048}}}]}}}}