> For the complete documentation index, see [llms.txt](https://docs.atomyx.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.atomyx.io/atomyx-submit/troubleshooting/atomyx-submit-troubleshooting/api-integration-issues.md).

# API Integration Issues

API integration issues affect communication between Atomyx Submit and surrounding systems, especially ERP platforms, ordering systems, callbacks, and processing services.

Use this page when API calls fail, Submit jobs are not created as expected, callbacks do not reach the receiving system, or callback payloads cannot be processed correctly.

### Public API environment

The public Submit API currently uses production.

```
https://submit.atomyx.io/api
```

Production API requests create real Submit jobs. When testing, use clearly identifiable test references, avoid real customer data unless required, and only use artwork files that are safe for testing.

Example test reference:

```
TEST-ORDER-10001
```

Staging is for internal Atomyx use only unless Atomyx has specifically provided access. A public sandbox environment is planned but is not currently available.

### Authentication failures

#### Typical symptoms

* API requests fail with authentication or authorisation errors
* the API returns `401 Unauthorized`
* flows that used to work stop working after an API key change
* all users or submissions are affected, not just one submission

#### What to check

* the API key is valid
* the API key has permission to create Submit jobs
* the API key belongs to the environment being used
* the `Authorization` header is present
* the header uses `Bearer`, not `Token` or `Basic`
* there are no extra spaces or copied characters in the key
* the request is being sent to the correct base URL

#### Expected header format

```http
Authorization: Bearer YOUR_API_KEY
```

Example:

```http
POST /jobs HTTP/1.1
Host: submit.atomyx.io
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

#### How to resolve it

* verify the configured key carefully
* replace expired or revoked keys
* test the request independently from the portal or ERP workflow
* confirm the expected header format
* confirm the API key has Submit access in Atomyx Vault

### Bad request or invalid request body

#### Typical symptoms

* the API returns `400 Bad Request`
* the job is not created
* the request works in one tool but not another
* the API response indicates missing or invalid fields

#### What to check

* the request body is valid JSON
* the `Content-Type` header is set to `application/json`
* the required `externalId` field is present
* optional fields match the schema in the API Reference
* the payload being sent by the ERP or integration is the same payload tested manually

#### Minimum valid payload

```json
{
  "externalId": "TEST-ORDER-10001"
}
```

#### How to resolve it

* validate the JSON before sending it
* start with the minimum valid payload
* add optional fields one at a time
* compare the generated ERP payload with a known working test payload
* check the API Reference for the current schema

### Invalid metadata

#### Typical symptoms

* the job is created, but metadata does not appear correctly
* the receiving Submit UI does not show expected order or customer information
* metadata values appear under the wrong labels
* the API rejects the payload when metadata is included

#### What to check

Metadata should be sent as an array of properties.

Example:

```json
{
  "metadata": [
    {
      "propertyId": "orderNumber",
      "propertyName": "Order number",
      "value": "TEST-ORDER-10001"
    }
  ]
}
```

Check that each metadata item includes:

* `propertyId`
* `propertyName`
* `value`

#### How to resolve it

* standardise metadata field names between the ERP and Submit
* confirm whether the receiving system expects a custom mapping
* avoid changing field names without updating both sides of the integration
* inspect live payloads using controlled test submissions where helpful

### Branding does not appear

#### Typical symptoms

* the Submit page opens, but the expected logo is missing
* the colour does not match the expected brand colour
* the logo fails to load in the end-user experience

#### What to check

* `brand.color` is a valid hex colour
* `brand.logo` is a publicly accessible URL
* the logo URL can be accessed without authentication
* the logo is suitable for display in the Submit UI

Example:

```json
{
  "brand": {
    "color": "#1A73E8",
    "logo": "https://example.com/assets/logo.png"
  }
}
```

#### How to resolve it

* open the logo URL in a private/incognito browser window
* confirm the image can be loaded without login
* check that the URL is HTTPS
* confirm the colour value is a valid hex code
* test with a simple known-good logo URL

### Artwork is not processed

#### Typical symptoms

* the job is created, but artwork does not process
* Submit waits for upload even though artwork was supplied
* the artwork file cannot be accessed by Submit
* preflight or proof generation does not start as expected

#### What to check

If artwork is supplied during job creation, the artwork URL must be publicly accessible.

Example:

```json
{
  "artwork": {
    "url": "https://example.com/files/artwork.pdf"
  }
}
```

Check that:

* the file URL is accessible by Atomyx Submit
* the file does not require login
* the file URL has not expired
* the file type is supported by the intended workflow
* the file can be downloaded from outside the customer network

#### How to resolve it

* test the artwork URL from outside the customer system
* avoid short-lived or session-protected file URLs unless explicitly supported
* confirm the file type and size are within the supported limits
* retry using a known-good publicly accessible PDF

### Upload URL does not work

#### Typical symptoms

* the API returns an `uploadURL`, but the URL does not open
* the user sees an error when opening the upload URL
* the user cannot upload artwork through the returned Submit page

#### What to check

* the job was created successfully
* the URL was copied completely
* the user is opening the URL in a supported browser
* the job has not expired or been cancelled
* the correct URL is being shown to the end user

#### How to resolve it

* copy the returned `uploadURL` directly from the API response
* test the URL in a clean browser session
* recreate the job if the URL has expired
* confirm whether any customer firewall or browser policy is blocking the page

### Webhook or callback not firing

#### Typical symptoms

* the submission progresses, but the ERP does not receive updates
* proof completion is visible in Submit, but not in the external system
* there are no visible callback records in the receiving platform
* the callback receiver logs do not show any incoming request

#### What to check

* `callbackURL` is configured and correct
* the callback URL includes the correct protocol and path
* the endpoint is publicly reachable
* the receiving server accepts HTTP `POST` requests
* the receiving server accepts `Content-Type: application/json`
* the event expected by the ERP is actually enabled or supported
* firewall or network rules allow inbound callback traffic
* the receiving system is not rejecting the request before logging it

#### Confirmed callback method

Callbacks are sent as HTTP `POST` requests with JSON payloads.

```http
POST /your-callback-endpoint HTTP/1.1
Content-Type: application/json
```

#### Confirmed callback events

Callbacks are expected for these submission workflow events:

| Event              | Description                                   |
| ------------------ | --------------------------------------------- |
| `uploaded`         | File has arrived                              |
| `preflighting`     | Full preflight has started                    |
| `preflight_passed` | Preflight completed successfully              |
| `preflight_failed` | Preflight completed with failure              |
| `proof_generated`  | Proof page or proof output has been generated |
| `approved`         | Customer approved the proof                   |
| `rejected`         | Customer rejected the proof                   |

A separate `created` callback event is not currently documented. The external ERP or ordering system creates the Submit session/job, so creation is normally already known by the external system.

#### How to resolve it

* confirm the callback URL including protocol, domain, and path
* test the receiver endpoint independently
* confirm the receiver accepts JSON `POST` requests
* validate security requirements such as HMAC verification
* inspect delivery logs and receiving-system logs together
* ensure the receiver responds quickly with a successful status code

### Callback signature failure

#### Typical symptoms

* callbacks arrive but are rejected by the receiving system
* the receiver reports an invalid signature
* callbacks work in a temporary test endpoint but fail in the ERP
* signature checks fail after payload parsing or middleware changes

#### What to check

Atomyx Submit authenticates outbound callbacks using HMAC signatures.

The receiving system should verify the HMAC signature before trusting or processing the callback payload.

Check:

* the correct shared secret is being used
* the signing algorithm is correct
* the exact signature header name is correct
* whether the signature is calculated over the raw body only or over timestamp and raw body
* timestamp tolerance, if timestamps are used
* whether middleware is changing the body before signature verification

#### How to resolve it

* verify the signature before parsing and re-serialising JSON
* use the raw request body for signature verification if required
* confirm the shared secret has not been rotated or copied incorrectly
* confirm the header name and signing format with Atomyx
* log signature verification failures carefully without exposing secrets

Recommended implementation to confirm or adopt:

* HMAC-SHA256
* signature generated over the raw request body, or over `timestamp + "." + raw_body`
* per-tenant shared secret
* timestamp included to help prevent replay attacks

Possible headers to confirm:

```http
X-Atomyx-Signature: sha256=<hex-signature>
X-Atomyx-Timestamp: 2026-05-11T10:23:45Z
X-Atomyx-Event: preflight_passed
X-Atomyx-Delivery: del_...
User-Agent: AtomyxSubmit/<version>
```

### Incorrect callback payload format

#### Typical symptoms

* callbacks are received, but cannot be processed correctly
* field names or types do not match what the ERP expects
* the receiving system cannot identify the order or artwork
* preflight failures cannot be mapped to the ERP workflow

#### What to check

Confirmed callback payload content includes:

| Field or content area        | Description                                                                                                                             |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Current submission status    | Current status such as `uploaded`, `preflighting`, `preflight_passed`, `preflight_failed`, `proof_generated`, `approved`, or `rejected` |
| File references              | URLs to generated or processed files, such as processed PDF, proof page, or preflight report                                            |
| Structured error information | Error codes, affected checks, and severity details when preflight fails                                                                 |
| `order_ref`                  | The order reference originally supplied when the session/job was created                                                                |

Recommended fields to confirm or standardise:

| Field                | Description                                    |
| -------------------- | ---------------------------------------------- |
| `event_id`           | Unique ID for the callback event               |
| `event_type`         | Event name, such as `preflight_passed`         |
| `occurred_at`        | ISO 8601 timestamp for when the event occurred |
| `session_id`         | Submit session or job ID                       |
| `order_ref`          | External order reference                       |
| `artwork_version_id` | Artwork version ID, where relevant             |
| `status`             | Current submission status                      |
| `files`              | Related file URLs                              |
| `errors`             | Structured error details                       |
| `attempt`            | Callback delivery attempt number               |

#### Example payload

> This example represents the recommended callback shape and should be confirmed against the final implementation before being treated as the official schema.

```json
{
  "event_id": "evt_123",
  "event_type": "preflight_passed",
  "occurred_at": "2026-05-11T10:23:45Z",
  "session_id": "ses_123",
  "order_ref": "ERP-12345",
  "artwork_version_id": "av_123",
  "status": "preflight_passed",
  "files": {
    "processed_pdf": "https://example.com/files/processed.pdf",
    "proof": "https://example.com/proofs/123",
    "preflight_report": "https://example.com/reports/123"
  },
  "errors": [],
  "attempt": 1
}
```

#### How to resolve it

* compare expected and actual payloads
* standardise naming and data formats
* inspect live payloads using controlled test endpoints where helpful
* document the expected contract clearly on both sides
* confirm how the ERP maps `order_ref`, status, file references, and preflight errors

### Duplicate callback received

#### Typical symptoms

* the same callback appears more than once
* the ERP processes the same status update twice
* duplicate notes, status changes, or workflow actions appear in the receiving system

#### What to check

Callbacks should be handled as at-least-once delivery.

This means the same event may be delivered more than once, especially if a response times out or a retry is triggered.

Check whether the receiving system:

* records event IDs or delivery IDs
* handles repeated status updates safely
* treats callbacks as idempotent
* responds quickly after validation and storage

#### How to resolve it

* use an event ID or delivery ID to deduplicate callbacks
* make callback processing idempotent
* avoid assuming events always arrive exactly once
* avoid assuming callbacks always arrive in perfect order
* store the callback first, acknowledge it, then process it asynchronously

### Timeout errors

#### Typical symptoms

* requests fail intermittently
* the same operations work manually but not consistently in workflow
* long-running operations exceed the configured timeout window
* callbacks appear to be resent even though the receiver eventually processed them

#### What to check

* endpoint latency
* server load
* timeout configuration
* whether the operation should actually be asynchronous
* whether the callback receiver does too much work before responding

#### How to resolve it

* respond to callbacks quickly, ideally within 5 seconds
* acknowledge receipt before doing long-running work
* move expensive processing to an asynchronous queue
* add retry logic with backoff for transient outbound requests from the ERP
* monitor receiver latency and failed callback attempts

### Callback retries and expected response

Retry behaviour is not yet fully documented.

Recommended behaviour to document and implement:

* any `2xx` response should be treated as successful
* `200 OK` and `204 No Content` should both be accepted
* non-2xx responses should be treated as failed delivery attempts
* timeouts should be treated as failed delivery attempts
* failed deliveries should be retried with backoff
* permanent callback failures should be surfaced in Manage as workflow exceptions

Recommended receiving pattern:

1. Verify the HMAC signature.
2. Store the callback event.
3. Return a `2xx` response quickly.
4. Process the event asynchronously.

### Production testing mistakes

#### Typical symptoms

* a test job was accidentally created in production
* test order references appear in live Submit records
* a customer-facing upload URL was generated during a test

#### What to check

* the external ID used for the test
* approximate time of creation
* which API key was used
* whether any test artwork or customer data was uploaded
* whether the job needs to be cancelled, ignored, or cleaned up

#### How to resolve it

Contact Atomyx support and provide:

* the external ID
* approximate time of creation
* environment
* any returned Submit job ID
* whether artwork was uploaded
* whether any customer data was included

### Practical guidance

Keep the external ERP or ordering system as the system of record.

Design status changes so they are explicit and easy to trace across both sides of the integration. For every integration, agree and document:

* who creates the Submit job
* which external reference identifies the order or job
* which status values are expected
* which callback events are used
* how callback signatures are verified
* how duplicate callbacks are handled
* how failed callbacks are retried or surfaced
* where integration logs can be inspected

### Related pages

* API Integration
* Submit API Overview
* Authentication
* Getting an API Key
* API Reference
* Callbacks and Status Updates
* Submit Architecture
* Authentication and API Keys in Vault
* Submit Troubleshooting


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.atomyx.io/atomyx-submit/troubleshooting/atomyx-submit-troubleshooting/api-integration-issues.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
