# ERPLab

> ERPLab hosts high-fidelity, tenant-isolated ERP simulators (Oracle Fusion Cloud ERP and more) with the same REST, SOAP and OAuth 2.0 integration surface as the real vendors, so integration code can be built and validated end-to-end without a production ERP.

Each simulator is served under a tenant-specific base URL of the form `https://erplab.cloud/sim/{environmentKey}`. Sign in at https://erplab.cloud/auth to obtain an `environmentKey` and OAuth 2.0 client credentials for your tenant. Public documentation and OpenAPI specifications below describe the exact endpoints, payload shapes, query grammar, error envelopes and workflows every simulator exposes; they are the authoritative contract.

## Authentication

All REST and SOAP calls require an OAuth 2.0 bearer token. Only the client-credentials grant is supported, and `scope` is REQUIRED on the token request — Oracle marks it required, and a request without it is refused with `400 invalid_request`.

```http
POST https://erplab.cloud/sim/{environmentKey}/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=urn:opc:resource:consumer::all&client_id={client_id}&client_secret={client_secret}
```

Credentials may instead be sent as `Authorization: Basic base64(client_id:client_secret)`; `grant_type` and `scope` stay in the form body either way.

```json
{ "access_token": "…", "token_type": "Bearer", "expires_in": 3600, "scope": "urn:opc:resource:consumer::all" }
```

Send `Authorization: Bearer {access_token}` on every subsequent call. Tokens are valid for 3600 seconds; cache one and re-mint shortly before it expires rather than minting per request.

Request `urn:opc:resource:consumer::all` on its own — combining it with another scope is refused with `400 invalid_scope`, as is any scope beyond the one granted to the client. A `401 invalid_client` means an unknown client, a wrong secret, a revoked client, or a credential used against a different environment key; all four are reported identically and cannot be told apart.

## Reading the contract

The OpenAPI document is authoritative **per operation**. A child collection implements fewer query parameters than its parent, so read the parameter list on the operation you are about to call rather than assuming the parent's — a parameter the operation does not declare is refused with `400 REST-01003` naming it, never accepted and ignored. Child collections and actions have their own schemas, not the parent resource's.

Not every attribute can be filtered. Each one in the OpenAPI schema carries `x-queryable`, and that flag is **Oracle's**: this simulator is 1:1 with Oracle on every attribute it emits, so a filter that works here works against a real Oracle pod, and one refused here is refused there. Read the flag rather than guessing — a filter on an attribute marked false is refused with `400 REST-01003`, never silently ignored.

Oracle names this flag `queryable` and serves it from `<resource>/describe`, which this simulator implements too — `GET {base}/fscmRestApi/resources/11.13.18.05/receivablesInvoices/describe` returns Oracle's metadata document with `mandatory`, `updatable` and `queryable` per attribute. Prefer it over this OpenAPI document when you want metadata through a mechanism a real pod also serves, so your client stays portable. `x-queryable` is the same fact republished in the schema, because OpenAPI requires a vendor extension to start with `x-`. Three resources carry a note on their schema saying Oracle's own flag for them was never confirmed — read the note before relying on a filter there.

Every error body carries `o:errorCode`. That is the field to branch on; `title` and `detail` are prose and may be reworded. The envelope is `{ title, status, type, o:errorCode, detail, o:errorDetails? }`.

To confirm that a payment landed, read `standardReceiptApplications` under `receivablesCustomerAccountActivities` — creating a receipt never applies it, and the invoice balance changes only once a separate asynchronous process has applied the cash.

## Docs

- [Oracle Fusion Cloud ERP — integration documentation (Markdown)](https://erplab.cloud/api/public/oracle-fusion/docs.md): Full reference as plain text — authentication, every REST resource with its attributes and query parameters, SOAP services, the capability matrix with support status, the error reference, and the end-to-end integration guide. Fetch this one; it needs no JavaScript.
- [Oracle Fusion Cloud ERP — OpenAPI 3.1 specification](https://erplab.cloud/api/public/oracle-fusion/openapi.json): Machine-readable API contract. Use this to discover endpoints, request/response schemas, path/query parameters and security schemes. Authoritative per operation.
- [Oracle Fusion Cloud ERP — integration documentation (browser)](https://erplab.cloud/public/oracle-fusion): The same content as a web page. Client-rendered, so it requires JavaScript — use the Markdown link above for programmatic access.

## Task guides

- [Oracle Fusion — External Provider Integration Guide](https://erplab.cloud/api/public/oracle-fusion/docs.md#external-provider-integration-guide): End-to-end walkthrough — connect, authenticate, list/read/write each supported resource, filter with the `q` grammar, run incremental sync with `LastUpdateDate`, split installments, and recover from errors.
- [Oracle Fusion — Capability matrix](https://erplab.cloud/api/public/oracle-fusion/docs.md#capability-matrix): Every capability with its support status. This is where to check whether something is unsupported before building against it.
- [Oracle Fusion — Error reference](https://erplab.cloud/api/public/oracle-fusion/docs.md#errors): Error envelope shape, status codes, error codes and recovery actions.

## Optional

- [ERPLab public index](https://erplab.cloud/public): List of all published ERP simulators and their documentation.
- [Sign in](https://erplab.cloud/auth): Obtain a tenant environment key and OAuth 2.0 client credentials.
