> ## Documentation Index
> Fetch the complete documentation index at: https://docs.legitmark.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow

> Step-by-step process from service request creation to image upload and validation.

## Step-by-Step Implementation

<Steps>
  <Step title="Create Service Request">
    When an item is ready for authentication, create a service request. This provides you with the specific image requirements for the selected item category.

    **API Reference:** [`POST /api/v2/sr`](/api-reference#tag/Service-Requests/operation/initiate-service-request)

    **Required Headers:**

    ```javascript theme={null}
    const headers = {
      'Authorization': 'Bearer leo_xxxxxxxxx',      // Your API key
      'Content-Type': 'application/json'
    };
    ```

    **Request Data:**

    * **Service UUID** (optional): Your partner service identifier. If omitted, auto-resolved based on your organization and item type.
    * **Item Taxonomy**: Category, type, and brand UUIDs from your taxonomy mapping
    * **External ID** (optional): Your internal item identifier for correlation

    <CodeGroup>
      ```javascript HTTP theme={null}
      const response = await fetch('https://api.legitmark.com/api/v2/sr', {
        method: 'POST',
        headers,
        body: JSON.stringify({
          // service is optional — auto-resolved if omitted
          external_id: 'your-internal-ref-123',
          item: {
            category: 'category-uuid',
            type: 'type-uuid',
            brand: 'brand-uuid',
          }
        })
      });
      ```

      ```typescript SDK theme={null}
      const { sr } = await legitmark.sr.create({
        // service is optional — auto-resolved if omitted
        external_id: 'your-internal-ref-123',
        item: {
          category: 'category-uuid',
          type: 'type-uuid',
          brand: 'brand-uuid',
        },
      });
      ```
    </CodeGroup>

    **Dependencies:**

    * Taxonomy mapping configured (see [Taxonomy](/partner/taxonomy))
  </Step>

  <Step title="Get Image Requirements">
    Retrieve the specific image sides required for your item category. This tells you exactly which photos to capture.

    **API Reference:** [`GET /api/v2/sr/{sr_uuid}`](/api-reference#tag/Service-Requests/operation/get-service-request) with query parameters

    Fetch the service request with `requirements=true` and `sides=true` to get the full image requirements:

    <CodeGroup>
      ```javascript HTTP theme={null}
      const response = await fetch(
        `https://api.legitmark.com/api/v2/sr/${srUuid}?requirements=true&sides=true&item=true`,
        { headers }
      );
      const { sr } = await response.json();

      // sr.requirements contains side_groups with required/optional sides
      for (const group of sr.requirements.side_groups) {
        for (const side of group.sides) {
          console.log(`${side.name}: ${side.required ? 'required' : 'optional'}`);
        }
      }
      ```

      ```typescript SDK theme={null}
      const { sr } = await legitmark.sr.getWithRequirements(srUuid);

      console.log(`Required photos: ${sr.requirements?.total_required}`);

      for (const group of sr.requirements?.side_groups || []) {
        for (const side of group.sides) {
          console.log(`${side.name}: ${side.required ? 'required' : 'optional'}`);
        }
      }
      ```
    </CodeGroup>

    **Response Data:**

    * **Side groups** - Organized image requirements by group
    * **Required sides** - Mandatory images for authentication
    * **Optional sides** - Additional images that enhance authentication
    * **Template images** - Visual guides for each required angle

    **Image Requirements:**

    * **Format:** JPG/JPEG/PNG
    * **Size:** 600 x 600 px minimum
    * **File Size:** 5 MB maximum per image
    * **Quality:** Clear, well-lit, focused images
  </Step>

  <Step title="Upload Images">
    Upload images using Legitmark's secure CDN system. For each required side, get a pre-signed URL and upload directly to S3.

    **API Reference:** Media Management endpoints

    * [`GET https://asset.legitmark.com/intent`](/api-reference/media-management/generate-upload-url) - Get pre-signed upload URL
    * [`PUT /{presigned-url}`](/api-reference/media-management/upload-image) - Direct S3 upload

    **Upload Process:**

    1. **Get upload URL** with query parameters: `sr` (service request UUID) and `side` (side UUID with file extension)
    2. **Upload directly** to the pre-signed S3 URL using PUT request with binary data

    <CodeGroup>
      ```javascript HTTP theme={null}
      // Step 1: Get a pre-signed upload URL
      const intentResponse = await fetch(
        `https://asset.legitmark.com/intent?sr=${srUuid}&side=${sideUuid}.jpg`,
        { headers }
      );
      const { url: presignedUrl } = await intentResponse.json();

      // Step 2: Upload binary image data to the pre-signed URL
      await fetch(presignedUrl, {
        method: 'PUT',
        body: imageFile,
        headers: { 'Content-Type': 'image/jpeg' }
      });
      ```

      ```typescript SDK theme={null}
      // Upload from file path
      await legitmark.images.uploadForSide(srUuid, sideUuid, './photo.jpg');

      // Or from buffer
      await legitmark.images.uploadForSide(srUuid, sideUuid, imageBuffer);
      ```
    </CodeGroup>
  </Step>

  <Step title="Check Progress">
    Verify that all required images have been uploaded before submitting.

    Fetch the service request with `sides=true` to get the current progress, which includes counts of uploaded required and optional images:

    <CodeGroup>
      ```javascript HTTP theme={null}
      const response = await fetch(
        `https://api.legitmark.com/api/v2/sr/${srUuid}?sides=true`,
        { headers }
      );
      const { sr } = await response.json();

      const progress = sr.sides.progress;
      console.log(`Uploaded: ${progress.current_required}/${progress.total_required}`);
      console.log(`Ready to submit: ${progress.met}`);
      ```

      ```typescript SDK theme={null}
      const progress = await legitmark.sr.getProgress(srUuid);

      console.log(`Uploaded: ${progress.current_required}/${progress.total_required}`);
      console.log(`Ready to submit: ${progress.met}`);
      ```
    </CodeGroup>

    **Progress Response:**

    ```json theme={null}
    {
      "current_required": 2,
      "total_required": 2,
      "current_optional": 1,
      "total_optional": 3,
      "met": true
    }
    ```

    When `met` is `true`, all required images are uploaded and the service request can be submitted.
  </Step>

  <Step title="Submit for Authentication">
    Once progress requirements are met, submit the service request for expert authentication.

    **API Reference:** [`POST /api/v2/sr/{sr_uuid}/submit`](/api-reference#tag/Service-Requests/operation/submit-service-request)

    <CodeGroup>
      ```javascript HTTP theme={null}
      const response = await fetch(
        `https://api.legitmark.com/api/v2/sr/${srUuid}/submit`,
        { method: 'POST', headers }
      );
      const { sr } = await response.json();
      console.log(`Submitted! State: ${sr.state.primary}/${sr.state.supplement}`);
      ```

      ```typescript SDK theme={null}
      const progress = await legitmark.sr.getProgress(srUuid);

      if (progress.met) {
        const { sr } = await legitmark.sr.submit(srUuid);
        console.log(`Submitted! State: ${sr.state.primary}/${sr.state.supplement}`);
      }
      ```
    </CodeGroup>

    **Post-Submission Process:**

    1. **Quality Control Review**: Image and data verification
    2. **Authentication Review**: Expert authentication by specialists
    3. **Results Notification**: Webhook updates at each stage (see [States](/partner/service-request-states))
  </Step>
</Steps>

## Implementation Patterns

### Error Handling

<CodeGroup>
  ```javascript HTTP theme={null}
  async function createServiceRequest(itemData) {
    try {
      const response = await fetch('https://api.legitmark.com/api/v2/sr', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer leo_xxxxxxxxx',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(itemData)
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(`Service request failed: ${error.error.message}`);
      }

      return await response.json();
    } catch (error) {
      console.error('Service request creation failed:', error);
      // Implement retry logic or user notification
    }
  }
  ```

  ```typescript SDK theme={null}
  import { Legitmark, LegitmarkError, withRetry } from 'legitmark';

  const legitmark = new Legitmark('leo_your_api_key');

  // Built-in retry with exponential backoff
  const { sr } = await withRetry(
    () => legitmark.sr.create({
      item: { category: '...', type: '...', brand: '...' },
    }),
    {
      attempts: 3,
      onRetry: (error, attempt) => console.log(`Retry ${attempt}...`),
    }
  );
  ```
</CodeGroup>

### Batch Image Upload

<CodeGroup>
  ```javascript HTTP theme={null}
  async function uploadAllImages(srUuid, imageFiles) {
    const uploadPromises = imageFiles.map(async ({ sideUuid, file }) => {
      const intentResponse = await fetch(
        `https://asset.legitmark.com/intent?sr=${srUuid}&side=${sideUuid}.jpg`,
        { headers: { 'Authorization': 'Bearer leo_xxxxxxxxx' } }
      );
      const { url } = await intentResponse.json();

      return fetch(url, {
        method: 'PUT',
        body: file,
        headers: { 'Content-Type': 'image/jpeg' }
      });
    });

    const results = await Promise.allSettled(uploadPromises);
    return results.map((result, index) => ({
      sideUuid: imageFiles[index].sideUuid,
      success: result.status === 'fulfilled' && result.value.ok,
      error: result.status === 'rejected' ? result.reason : null
    }));
  }
  ```

  ```typescript SDK theme={null}
  // The SDK handles intent + upload in one call
  for (const { sideUuid, filePath } of imagesToUpload) {
    await legitmark.images.uploadForSide(srUuid, sideUuid, filePath);
  }
  ```
</CodeGroup>

## Best Practices

### Pre-Sale Optimization

* **Cache image requirements** for frequently used categories
* **Validate images client-side** before storage
* **Compress images** while maintaining quality standards
* **Store images locally** until item sells

### Upload Optimization

* **Use parallel uploads** for multiple images
* **Implement retry logic** for failed uploads
* **Show upload progress** to users
* **Validate upload completion** before proceeding

### Validation Strategy

* **Check requirements** before finalization
* **Handle validation errors** gracefully
* **Provide user feedback** on missing requirements
* **Retry validation** after corrections

## TypeScript SDK

The official [TypeScript SDK](https://github.com/legitmark-eng/legitmark-typescript) (`npm install legitmark`) handles the complete workflow with type safety, automatic retries, and a clean resource-based API:

```typescript theme={null}
import { Legitmark } from 'legitmark';

const legitmark = new Legitmark('leo_your_api_key');

// 1. Browse taxonomy
const { data: categories } = await legitmark.taxonomy.getTree({ activeOnly: true });

// 2. Create service request (service auto-resolved if omitted)
const { sr } = await legitmark.sr.create({
  item: { category: '...', type: '...', brand: '...' },
});

// 3. Get requirements
const { sr: srWithReqs } = await legitmark.sr.getWithRequirements(sr.uuid);

// 4. Upload images (handles intent + upload automatically)
await legitmark.images.uploadForSide(sr.uuid, sideUuid, './photo.jpg');

// 5. Check progress and submit
const progress = await legitmark.sr.getProgress(sr.uuid);
if (progress.met) {
  await legitmark.sr.submit(sr.uuid);
}
```

See the [SDK documentation](https://github.com/legitmark-eng/legitmark-typescript) for installation, configuration, and detailed usage.

## Testing and Debugging

### Test Service Request Creation

Use the [Interactive API Reference](/api-reference#tag/Service-Requests/operation/initiate-service-request) to test service request creation with your actual credentials.

### Validate Image Upload Flow

Test the complete upload process:

1. Create a test service request
2. Fetch image requirements via `GET /api/v2/sr/{uuid}?requirements=true&sides=true`
3. Upload test images via the intent flow
4. Verify progress via `GET /api/v2/sr/{uuid}?sides=true`
5. Submit via `POST /api/v2/sr/{uuid}/submit`

## Next Steps

Once workflow implementation is complete:

1. **Setup** [Webhooks](/webhook-reference/introduction) for real-time status notifications
2. **Review** [States](/partner/service-request-states) for handling authentication results
3. **Test end-to-end** workflow with sample items
